Remove PIDL
This commit is contained in:
parent
c09d87c6e4
commit
6e26a3eed5
110 changed files with 0 additions and 45856 deletions
|
@ -1,41 +0,0 @@
|
||||||
MANIFEST
|
|
||||||
tests/parse_idl.pl
|
|
||||||
tests/Util.pm
|
|
||||||
tests/ndr_refptr.pl
|
|
||||||
tests/ndr_string.pl
|
|
||||||
tests/ndr_simple.pl
|
|
||||||
tests/ndr_align.pl
|
|
||||||
tests/ndr_alloc.pl
|
|
||||||
tests/ndr_array.pl
|
|
||||||
tests/ndr.pl
|
|
||||||
tests/samba-ndr.pl
|
|
||||||
tests/util.pl
|
|
||||||
tests/test_util.pl
|
|
||||||
tests/ndr_represent.pl
|
|
||||||
tests/ndr_compat.pl
|
|
||||||
tests/ndr_fullptr.pl
|
|
||||||
tests/ndr_tagtype.pl
|
|
||||||
tests/header.pl
|
|
||||||
lib/Parse/Pidl/Samba3/ClientNDR.pm
|
|
||||||
lib/Parse/Pidl/Samba3/ServerNDR.pm
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Server.pm
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Parser.pm
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Client.pm
|
|
||||||
lib/Parse/Pidl/Samba4/Header.pm
|
|
||||||
lib/Parse/Pidl/Samba4/TDR.pm
|
|
||||||
lib/Parse/Pidl/Samba4/Template.pm
|
|
||||||
lib/Parse/Pidl/Samba4.pm
|
|
||||||
lib/Parse/Pidl/Wireshark/Conformance.pm
|
|
||||||
lib/Parse/Pidl/Wireshark/NDR.pm
|
|
||||||
lib/Parse/Pidl/Typelist.pm
|
|
||||||
lib/Parse/Pidl/Dump.pm
|
|
||||||
lib/Parse/Pidl/Compat.pm
|
|
||||||
lib/Parse/Pidl/Util.pm
|
|
||||||
lib/Parse/Pidl/NDR.pm
|
|
||||||
lib/Parse/Pidl.pm
|
|
||||||
Makefile.PL
|
|
||||||
idl.yp
|
|
||||||
TODO
|
|
||||||
README
|
|
||||||
pidl
|
|
||||||
META.yml
|
|
|
@ -1,18 +0,0 @@
|
||||||
name: Parse-Pidl
|
|
||||||
abstract: Generate parsers / DCE/RPC-clients from IDL
|
|
||||||
author:
|
|
||||||
- Andrew Tridgell <tridge@samba.org>
|
|
||||||
- Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
- Stefan Metzmacher <metze@samba.org>
|
|
||||||
- Tim Potter <tpot@samba.org>
|
|
||||||
license: gplv3
|
|
||||||
installdirs: site
|
|
||||||
homepage: http://www.samba.org/
|
|
||||||
bugtracker: http://bugzilla.samba.org/
|
|
||||||
requires:
|
|
||||||
Parse::Yapp: 0
|
|
||||||
recommends:
|
|
||||||
Data::Dumper: 0
|
|
||||||
meta-spec:
|
|
||||||
version: 1.3
|
|
||||||
url: http://module-build.sourceforge.net/META-spec-v1.3.html
|
|
|
@ -1,40 +0,0 @@
|
||||||
{
|
|
||||||
"abstract" : "unknown",
|
|
||||||
"author" : [
|
|
||||||
"unknown"
|
|
||||||
],
|
|
||||||
"dynamic_config" : 0,
|
|
||||||
"generated_by" : "ExtUtils::MakeMaker version 7.1002, CPAN::Meta::Converter version 2.150005",
|
|
||||||
"license" : [
|
|
||||||
"unknown"
|
|
||||||
],
|
|
||||||
"meta-spec" : {
|
|
||||||
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
|
|
||||||
"version" : "2"
|
|
||||||
},
|
|
||||||
"name" : "Parse-Pidl",
|
|
||||||
"no_index" : {
|
|
||||||
"directory" : [
|
|
||||||
"t",
|
|
||||||
"inc"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"prereqs" : {
|
|
||||||
"build" : {
|
|
||||||
"requires" : {
|
|
||||||
"ExtUtils::MakeMaker" : "0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"configure" : {
|
|
||||||
"requires" : {
|
|
||||||
"ExtUtils::MakeMaker" : "0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtime" : {
|
|
||||||
"requires" : {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"release_status" : "stable",
|
|
||||||
"version" : "0.02",
|
|
||||||
"x_serialization_backend" : "JSON::PP version 2.27300_01"
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
---
|
|
||||||
abstract: unknown
|
|
||||||
author:
|
|
||||||
- unknown
|
|
||||||
build_requires:
|
|
||||||
ExtUtils::MakeMaker: '0'
|
|
||||||
configure_requires:
|
|
||||||
ExtUtils::MakeMaker: '0'
|
|
||||||
dynamic_config: 0
|
|
||||||
generated_by: 'ExtUtils::MakeMaker version 7.1002, CPAN::Meta::Converter version 2.150005'
|
|
||||||
license: unknown
|
|
||||||
meta-spec:
|
|
||||||
url: http://module-build.sourceforge.net/META-spec-v1.4.html
|
|
||||||
version: '1.4'
|
|
||||||
name: Parse-Pidl
|
|
||||||
no_index:
|
|
||||||
directory:
|
|
||||||
- t
|
|
||||||
- inc
|
|
||||||
requires: {}
|
|
||||||
version: '0.02'
|
|
||||||
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
|
|
|
@ -1,991 +0,0 @@
|
||||||
# This Makefile is for the Parse::Pidl extension to perl.
|
|
||||||
#
|
|
||||||
# It was generated automatically by MakeMaker version
|
|
||||||
# 7.1002 (Revision: 71002) from the contents of
|
|
||||||
# Makefile.PL. Don't edit this file, edit Makefile.PL instead.
|
|
||||||
#
|
|
||||||
# ANY CHANGES MADE HERE WILL BE LOST!
|
|
||||||
#
|
|
||||||
# MakeMaker ARGV: ()
|
|
||||||
#
|
|
||||||
|
|
||||||
# MakeMaker Parameters:
|
|
||||||
|
|
||||||
# BUILD_REQUIRES => { }
|
|
||||||
# CONFIGURE_REQUIRES => { }
|
|
||||||
# EXE_FILES => [q[pidl]]
|
|
||||||
# NAME => q[Parse::Pidl]
|
|
||||||
# PREREQ_PM => { }
|
|
||||||
# TEST_REQUIRES => { }
|
|
||||||
# VERSION_FROM => q[lib/Parse/Pidl.pm]
|
|
||||||
# test => { TESTS=>q[tests/*.pl] }
|
|
||||||
|
|
||||||
# --- MakeMaker post_initialize section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker const_config section:
|
|
||||||
|
|
||||||
# These definitions are from config.sh (via /usr/lib/x86_64-linux-gnu/perl/5.24/Config.pm).
|
|
||||||
# They may have been overridden via Makefile.PL or on the command line.
|
|
||||||
AR = ar
|
|
||||||
CC = x86_64-linux-gnu-gcc
|
|
||||||
CCCDLFLAGS = -fPIC
|
|
||||||
CCDLFLAGS = -Wl,-E
|
|
||||||
DLEXT = so
|
|
||||||
DLSRC = dl_dlopen.xs
|
|
||||||
EXE_EXT =
|
|
||||||
FULL_AR = /usr/bin/ar
|
|
||||||
LD = x86_64-linux-gnu-gcc
|
|
||||||
LDDLFLAGS = -shared -L/usr/local/lib -fstack-protector-strong
|
|
||||||
LDFLAGS = -fstack-protector-strong -L/usr/local/lib
|
|
||||||
LIBC = libc-2.24.so
|
|
||||||
LIB_EXT = .a
|
|
||||||
OBJ_EXT = .o
|
|
||||||
OSNAME = linux
|
|
||||||
OSVERS = 3.16.0
|
|
||||||
RANLIB = :
|
|
||||||
SITELIBEXP = /usr/local/share/perl/5.24.1
|
|
||||||
SITEARCHEXP = /usr/local/lib/x86_64-linux-gnu/perl/5.24.1
|
|
||||||
SO = so
|
|
||||||
VENDORARCHEXP = /usr/lib/x86_64-linux-gnu/perl5/5.24
|
|
||||||
VENDORLIBEXP = /usr/share/perl5
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker constants section:
|
|
||||||
AR_STATIC_ARGS = cr
|
|
||||||
DIRFILESEP = /
|
|
||||||
DFSEP = $(DIRFILESEP)
|
|
||||||
NAME = Parse::Pidl
|
|
||||||
NAME_SYM = Parse_Pidl
|
|
||||||
VERSION = 0.02
|
|
||||||
VERSION_MACRO = VERSION
|
|
||||||
VERSION_SYM = 0_02
|
|
||||||
DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\"
|
|
||||||
XS_VERSION = 0.02
|
|
||||||
XS_VERSION_MACRO = XS_VERSION
|
|
||||||
XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\"
|
|
||||||
INST_ARCHLIB = blib/arch
|
|
||||||
INST_SCRIPT = blib/script
|
|
||||||
INST_BIN = blib/bin
|
|
||||||
INST_LIB = blib/lib
|
|
||||||
INST_MAN1DIR = blib/man1
|
|
||||||
INST_MAN3DIR = blib/man3
|
|
||||||
MAN1EXT = 1p
|
|
||||||
MAN3EXT = 3pm
|
|
||||||
INSTALLDIRS = site
|
|
||||||
DESTDIR =
|
|
||||||
PREFIX = $(SITEPREFIX)
|
|
||||||
PERLPREFIX = /usr
|
|
||||||
SITEPREFIX = /usr/local
|
|
||||||
VENDORPREFIX = /usr
|
|
||||||
INSTALLPRIVLIB = /usr/share/perl/5.24
|
|
||||||
DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB)
|
|
||||||
INSTALLSITELIB = /usr/local/share/perl/5.24.1
|
|
||||||
DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB)
|
|
||||||
INSTALLVENDORLIB = /usr/share/perl5
|
|
||||||
DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB)
|
|
||||||
INSTALLARCHLIB = /usr/lib/x86_64-linux-gnu/perl/5.24
|
|
||||||
DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB)
|
|
||||||
INSTALLSITEARCH = /usr/local/lib/x86_64-linux-gnu/perl/5.24.1
|
|
||||||
DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH)
|
|
||||||
INSTALLVENDORARCH = /usr/lib/x86_64-linux-gnu/perl5/5.24
|
|
||||||
DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH)
|
|
||||||
INSTALLBIN = /usr/bin
|
|
||||||
DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN)
|
|
||||||
INSTALLSITEBIN = /usr/local/bin
|
|
||||||
DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN)
|
|
||||||
INSTALLVENDORBIN = /usr/bin
|
|
||||||
DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN)
|
|
||||||
INSTALLSCRIPT = /usr/bin
|
|
||||||
DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT)
|
|
||||||
INSTALLSITESCRIPT = /usr/local/bin
|
|
||||||
DESTINSTALLSITESCRIPT = $(DESTDIR)$(INSTALLSITESCRIPT)
|
|
||||||
INSTALLVENDORSCRIPT = /usr/bin
|
|
||||||
DESTINSTALLVENDORSCRIPT = $(DESTDIR)$(INSTALLVENDORSCRIPT)
|
|
||||||
INSTALLMAN1DIR = /usr/share/man/man1
|
|
||||||
DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR)
|
|
||||||
INSTALLSITEMAN1DIR = /usr/local/man/man1
|
|
||||||
DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR)
|
|
||||||
INSTALLVENDORMAN1DIR = /usr/share/man/man1
|
|
||||||
DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR)
|
|
||||||
INSTALLMAN3DIR = /usr/share/man/man3
|
|
||||||
DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR)
|
|
||||||
INSTALLSITEMAN3DIR = /usr/local/man/man3
|
|
||||||
DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR)
|
|
||||||
INSTALLVENDORMAN3DIR = /usr/share/man/man3
|
|
||||||
DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR)
|
|
||||||
PERL_LIB = /usr/share/perl/5.24
|
|
||||||
PERL_ARCHLIB = /usr/lib/x86_64-linux-gnu/perl/5.24
|
|
||||||
PERL_ARCHLIBDEP = /usr/lib/x86_64-linux-gnu/perl/5.24
|
|
||||||
LIBPERL_A = libperl.a
|
|
||||||
FIRST_MAKEFILE = Makefile
|
|
||||||
MAKEFILE_OLD = Makefile.old
|
|
||||||
MAKE_APERL_FILE = Makefile.aperl
|
|
||||||
PERLMAINCC = $(CC)
|
|
||||||
PERL_INC = /usr/lib/x86_64-linux-gnu/perl/5.24/CORE
|
|
||||||
PERL_INCDEP = /usr/lib/x86_64-linux-gnu/perl/5.24/CORE
|
|
||||||
PERL = "/usr/bin/perl"
|
|
||||||
FULLPERL = "/usr/bin/perl"
|
|
||||||
ABSPERL = $(PERL)
|
|
||||||
PERLRUN = $(PERL)
|
|
||||||
FULLPERLRUN = $(FULLPERL)
|
|
||||||
ABSPERLRUN = $(ABSPERL)
|
|
||||||
PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"
|
|
||||||
FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"
|
|
||||||
ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"
|
|
||||||
PERL_CORE = 0
|
|
||||||
PERM_DIR = 755
|
|
||||||
PERM_RW = 644
|
|
||||||
PERM_RWX = 755
|
|
||||||
|
|
||||||
MAKEMAKER = /usr/share/perl/5.24/ExtUtils/MakeMaker.pm
|
|
||||||
MM_VERSION = 7.1002
|
|
||||||
MM_REVISION = 71002
|
|
||||||
|
|
||||||
# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle).
|
|
||||||
# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle)
|
|
||||||
# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar)
|
|
||||||
# DLBASE = Basename part of dynamic library. May be just equal BASEEXT.
|
|
||||||
MAKE = make
|
|
||||||
FULLEXT = Parse/Pidl
|
|
||||||
BASEEXT = Pidl
|
|
||||||
PARENT_NAME = Parse
|
|
||||||
DLBASE = $(BASEEXT)
|
|
||||||
VERSION_FROM = lib/Parse/Pidl.pm
|
|
||||||
OBJECT =
|
|
||||||
LDFROM = $(OBJECT)
|
|
||||||
LINKTYPE = dynamic
|
|
||||||
BOOTDEP =
|
|
||||||
|
|
||||||
# Handy lists of source code files:
|
|
||||||
XS_FILES =
|
|
||||||
C_FILES =
|
|
||||||
O_FILES =
|
|
||||||
H_FILES =
|
|
||||||
MAN1PODS = pidl
|
|
||||||
MAN3PODS = lib/Parse/Pidl/Dump.pm \
|
|
||||||
lib/Parse/Pidl/NDR.pm \
|
|
||||||
lib/Parse/Pidl/Util.pm \
|
|
||||||
lib/Parse/Pidl/Wireshark/Conformance.pm \
|
|
||||||
lib/Parse/Pidl/Wireshark/NDR.pm
|
|
||||||
|
|
||||||
# Where is the Config information that we are using/depend on
|
|
||||||
CONFIGDEP = $(PERL_ARCHLIBDEP)$(DFSEP)Config.pm $(PERL_INCDEP)$(DFSEP)config.h
|
|
||||||
|
|
||||||
# Where to build things
|
|
||||||
INST_LIBDIR = $(INST_LIB)/Parse
|
|
||||||
INST_ARCHLIBDIR = $(INST_ARCHLIB)/Parse
|
|
||||||
|
|
||||||
INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT)
|
|
||||||
INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT)
|
|
||||||
|
|
||||||
INST_STATIC =
|
|
||||||
INST_DYNAMIC =
|
|
||||||
INST_BOOT =
|
|
||||||
|
|
||||||
# Extra linker info
|
|
||||||
EXPORT_LIST =
|
|
||||||
PERL_ARCHIVE =
|
|
||||||
PERL_ARCHIVEDEP =
|
|
||||||
PERL_ARCHIVE_AFTER =
|
|
||||||
|
|
||||||
|
|
||||||
TO_INST_PM = lib/Parse/Pidl.pm \
|
|
||||||
lib/Parse/Pidl/CUtil.pm \
|
|
||||||
lib/Parse/Pidl/Compat.pm \
|
|
||||||
lib/Parse/Pidl/Dump.pm \
|
|
||||||
lib/Parse/Pidl/Expr.pm \
|
|
||||||
lib/Parse/Pidl/IDL.pm \
|
|
||||||
lib/Parse/Pidl/NDR.pm \
|
|
||||||
lib/Parse/Pidl/ODL.pm \
|
|
||||||
lib/Parse/Pidl/Samba3/ClientNDR.pm \
|
|
||||||
lib/Parse/Pidl/Samba3/ServerNDR.pm \
|
|
||||||
lib/Parse/Pidl/Samba3/Template.pm \
|
|
||||||
lib/Parse/Pidl/Samba4.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/COM/Header.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/COM/Proxy.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/COM/Stub.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/Header.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Client.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Parser.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Server.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/Python.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/TDR.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/Template.pm \
|
|
||||||
lib/Parse/Pidl/Typelist.pm \
|
|
||||||
lib/Parse/Pidl/Util.pm \
|
|
||||||
lib/Parse/Pidl/Wireshark/Conformance.pm \
|
|
||||||
lib/Parse/Pidl/Wireshark/NDR.pm \
|
|
||||||
lib/Parse/Yapp/Driver.pm \
|
|
||||||
lib/wscript_build
|
|
||||||
|
|
||||||
PM_TO_BLIB = lib/Parse/Pidl.pm \
|
|
||||||
blib/lib/Parse/Pidl.pm \
|
|
||||||
lib/Parse/Pidl/CUtil.pm \
|
|
||||||
blib/lib/Parse/Pidl/CUtil.pm \
|
|
||||||
lib/Parse/Pidl/Compat.pm \
|
|
||||||
blib/lib/Parse/Pidl/Compat.pm \
|
|
||||||
lib/Parse/Pidl/Dump.pm \
|
|
||||||
blib/lib/Parse/Pidl/Dump.pm \
|
|
||||||
lib/Parse/Pidl/Expr.pm \
|
|
||||||
blib/lib/Parse/Pidl/Expr.pm \
|
|
||||||
lib/Parse/Pidl/IDL.pm \
|
|
||||||
blib/lib/Parse/Pidl/IDL.pm \
|
|
||||||
lib/Parse/Pidl/NDR.pm \
|
|
||||||
blib/lib/Parse/Pidl/NDR.pm \
|
|
||||||
lib/Parse/Pidl/ODL.pm \
|
|
||||||
blib/lib/Parse/Pidl/ODL.pm \
|
|
||||||
lib/Parse/Pidl/Samba3/ClientNDR.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba3/ClientNDR.pm \
|
|
||||||
lib/Parse/Pidl/Samba3/ServerNDR.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba3/ServerNDR.pm \
|
|
||||||
lib/Parse/Pidl/Samba3/Template.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba3/Template.pm \
|
|
||||||
lib/Parse/Pidl/Samba4.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/COM/Header.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4/COM/Header.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/COM/Proxy.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4/COM/Proxy.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/COM/Stub.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4/COM/Stub.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/Header.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4/Header.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Client.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4/NDR/Client.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Parser.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4/NDR/Parser.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Server.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4/NDR/Server.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/Python.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4/Python.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/TDR.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4/TDR.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/Template.pm \
|
|
||||||
blib/lib/Parse/Pidl/Samba4/Template.pm \
|
|
||||||
lib/Parse/Pidl/Typelist.pm \
|
|
||||||
blib/lib/Parse/Pidl/Typelist.pm \
|
|
||||||
lib/Parse/Pidl/Util.pm \
|
|
||||||
blib/lib/Parse/Pidl/Util.pm \
|
|
||||||
lib/Parse/Pidl/Wireshark/Conformance.pm \
|
|
||||||
blib/lib/Parse/Pidl/Wireshark/Conformance.pm \
|
|
||||||
lib/Parse/Pidl/Wireshark/NDR.pm \
|
|
||||||
blib/lib/Parse/Pidl/Wireshark/NDR.pm \
|
|
||||||
lib/Parse/Yapp/Driver.pm \
|
|
||||||
blib/lib/Parse/Yapp/Driver.pm \
|
|
||||||
lib/wscript_build \
|
|
||||||
blib/lib/wscript_build
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker platform_constants section:
|
|
||||||
MM_Unix_VERSION = 7.1002
|
|
||||||
PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker tool_autosplit section:
|
|
||||||
# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
|
|
||||||
AUTOSPLITFILE = $(ABSPERLRUN) -e 'use AutoSplit; autosplit($$$$ARGV[0], $$$$ARGV[1], 0, 1, 1)' --
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker tool_xsubpp section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker tools_other section:
|
|
||||||
SHELL = /bin/sh
|
|
||||||
CHMOD = chmod
|
|
||||||
CP = cp
|
|
||||||
MV = mv
|
|
||||||
NOOP = $(TRUE)
|
|
||||||
NOECHO = @
|
|
||||||
RM_F = rm -f
|
|
||||||
RM_RF = rm -rf
|
|
||||||
TEST_F = test -f
|
|
||||||
TOUCH = touch
|
|
||||||
UMASK_NULL = umask 0
|
|
||||||
DEV_NULL = > /dev/null 2>&1
|
|
||||||
MKPATH = $(ABSPERLRUN) -MExtUtils::Command -e 'mkpath' --
|
|
||||||
EQUALIZE_TIMESTAMP = $(ABSPERLRUN) -MExtUtils::Command -e 'eqtime' --
|
|
||||||
FALSE = false
|
|
||||||
TRUE = true
|
|
||||||
ECHO = echo
|
|
||||||
ECHO_N = echo -n
|
|
||||||
UNINST = 0
|
|
||||||
VERBINST = 0
|
|
||||||
MOD_INSTALL = $(ABSPERLRUN) -MExtUtils::Install -e 'install([ from_to => {@ARGV}, verbose => '\''$(VERBINST)'\'', uninstall_shadows => '\''$(UNINST)'\'', dir_mode => '\''$(PERM_DIR)'\'' ]);' --
|
|
||||||
DOC_INSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'perllocal_install' --
|
|
||||||
UNINSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'uninstall' --
|
|
||||||
WARN_IF_OLD_PACKLIST = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'warn_if_old_packlist' --
|
|
||||||
MACROSTART =
|
|
||||||
MACROEND =
|
|
||||||
USEMAKEFILE = -f
|
|
||||||
FIXIN = $(ABSPERLRUN) -MExtUtils::MY -e 'MY->fixin(shift)' --
|
|
||||||
CP_NONEMPTY = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'cp_nonempty' --
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker makemakerdflt section:
|
|
||||||
makemakerdflt : all
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker dist section:
|
|
||||||
TAR = tar
|
|
||||||
TARFLAGS = cvf
|
|
||||||
ZIP = zip
|
|
||||||
ZIPFLAGS = -r
|
|
||||||
COMPRESS = gzip --best
|
|
||||||
SUFFIX = .gz
|
|
||||||
SHAR = shar
|
|
||||||
PREOP = $(NOECHO) $(NOOP)
|
|
||||||
POSTOP = $(NOECHO) $(NOOP)
|
|
||||||
TO_UNIX = $(NOECHO) $(NOOP)
|
|
||||||
CI = ci -u
|
|
||||||
RCS_LABEL = rcs -Nv$(VERSION_SYM): -q
|
|
||||||
DIST_CP = best
|
|
||||||
DIST_DEFAULT = tardist
|
|
||||||
DISTNAME = Parse-Pidl
|
|
||||||
DISTVNAME = Parse-Pidl-0.02
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker macro section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker depend section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker cflags section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker const_loadlibs section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker const_cccmd section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker post_constants section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker pasthru section:
|
|
||||||
|
|
||||||
PASTHRU = LIBPERL_A="$(LIBPERL_A)"\
|
|
||||||
LINKTYPE="$(LINKTYPE)"\
|
|
||||||
LD="$(LD)"\
|
|
||||||
PREFIX="$(PREFIX)"
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker special_targets section:
|
|
||||||
.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT)
|
|
||||||
|
|
||||||
.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker c_o section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker xs_c section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker xs_o section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker top_targets section:
|
|
||||||
all :: pure_all manifypods
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
|
|
||||||
pure_all :: config pm_to_blib subdirs linkext
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
subdirs :: $(MYEXTLIB)
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
config :: $(FIRST_MAKEFILE) blibdirs
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
help :
|
|
||||||
perldoc ExtUtils::MakeMaker
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker blibdirs section:
|
|
||||||
blibdirs : $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
# Backwards compat with 6.18 through 6.25
|
|
||||||
blibdirs.ts : blibdirs
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
$(INST_LIBDIR)$(DFSEP).exists :: Makefile.PL
|
|
||||||
$(NOECHO) $(MKPATH) $(INST_LIBDIR)
|
|
||||||
$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_LIBDIR)
|
|
||||||
$(NOECHO) $(TOUCH) $(INST_LIBDIR)$(DFSEP).exists
|
|
||||||
|
|
||||||
$(INST_ARCHLIB)$(DFSEP).exists :: Makefile.PL
|
|
||||||
$(NOECHO) $(MKPATH) $(INST_ARCHLIB)
|
|
||||||
$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHLIB)
|
|
||||||
$(NOECHO) $(TOUCH) $(INST_ARCHLIB)$(DFSEP).exists
|
|
||||||
|
|
||||||
$(INST_AUTODIR)$(DFSEP).exists :: Makefile.PL
|
|
||||||
$(NOECHO) $(MKPATH) $(INST_AUTODIR)
|
|
||||||
$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_AUTODIR)
|
|
||||||
$(NOECHO) $(TOUCH) $(INST_AUTODIR)$(DFSEP).exists
|
|
||||||
|
|
||||||
$(INST_ARCHAUTODIR)$(DFSEP).exists :: Makefile.PL
|
|
||||||
$(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR)
|
|
||||||
$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHAUTODIR)
|
|
||||||
$(NOECHO) $(TOUCH) $(INST_ARCHAUTODIR)$(DFSEP).exists
|
|
||||||
|
|
||||||
$(INST_BIN)$(DFSEP).exists :: Makefile.PL
|
|
||||||
$(NOECHO) $(MKPATH) $(INST_BIN)
|
|
||||||
$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_BIN)
|
|
||||||
$(NOECHO) $(TOUCH) $(INST_BIN)$(DFSEP).exists
|
|
||||||
|
|
||||||
$(INST_SCRIPT)$(DFSEP).exists :: Makefile.PL
|
|
||||||
$(NOECHO) $(MKPATH) $(INST_SCRIPT)
|
|
||||||
$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_SCRIPT)
|
|
||||||
$(NOECHO) $(TOUCH) $(INST_SCRIPT)$(DFSEP).exists
|
|
||||||
|
|
||||||
$(INST_MAN1DIR)$(DFSEP).exists :: Makefile.PL
|
|
||||||
$(NOECHO) $(MKPATH) $(INST_MAN1DIR)
|
|
||||||
$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN1DIR)
|
|
||||||
$(NOECHO) $(TOUCH) $(INST_MAN1DIR)$(DFSEP).exists
|
|
||||||
|
|
||||||
$(INST_MAN3DIR)$(DFSEP).exists :: Makefile.PL
|
|
||||||
$(NOECHO) $(MKPATH) $(INST_MAN3DIR)
|
|
||||||
$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN3DIR)
|
|
||||||
$(NOECHO) $(TOUCH) $(INST_MAN3DIR)$(DFSEP).exists
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker linkext section:
|
|
||||||
|
|
||||||
linkext :: $(LINKTYPE)
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker dlsyms section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker dynamic_bs section:
|
|
||||||
|
|
||||||
BOOTSTRAP =
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker dynamic section:
|
|
||||||
|
|
||||||
dynamic :: $(FIRST_MAKEFILE) $(BOOTSTRAP) $(INST_DYNAMIC)
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker dynamic_lib section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker static section:
|
|
||||||
|
|
||||||
## $(INST_PM) has been moved to the all: target.
|
|
||||||
## It remains here for awhile to allow for old usage: "make static"
|
|
||||||
static :: $(FIRST_MAKEFILE) $(INST_STATIC)
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker static_lib section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker manifypods section:
|
|
||||||
|
|
||||||
POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--"
|
|
||||||
POD2MAN = $(POD2MAN_EXE)
|
|
||||||
|
|
||||||
|
|
||||||
manifypods : pure_all \
|
|
||||||
lib/Parse/Pidl/Dump.pm \
|
|
||||||
lib/Parse/Pidl/NDR.pm \
|
|
||||||
lib/Parse/Pidl/Util.pm \
|
|
||||||
lib/Parse/Pidl/Wireshark/Conformance.pm \
|
|
||||||
lib/Parse/Pidl/Wireshark/NDR.pm \
|
|
||||||
pidl
|
|
||||||
$(NOECHO) $(POD2MAN) --section=$(MAN1EXT) --perm_rw=$(PERM_RW) -u \
|
|
||||||
pidl $(INST_MAN1DIR)/pidl.$(MAN1EXT)
|
|
||||||
$(NOECHO) $(POD2MAN) --section=$(MAN3EXT) --perm_rw=$(PERM_RW) -u \
|
|
||||||
lib/Parse/Pidl/Dump.pm $(INST_MAN3DIR)/Parse::Pidl::Dump.$(MAN3EXT) \
|
|
||||||
lib/Parse/Pidl/NDR.pm $(INST_MAN3DIR)/Parse::Pidl::NDR.$(MAN3EXT) \
|
|
||||||
lib/Parse/Pidl/Util.pm $(INST_MAN3DIR)/Parse::Pidl::Util.$(MAN3EXT) \
|
|
||||||
lib/Parse/Pidl/Wireshark/Conformance.pm $(INST_MAN3DIR)/Parse::Pidl::Wireshark::Conformance.$(MAN3EXT) \
|
|
||||||
lib/Parse/Pidl/Wireshark/NDR.pm $(INST_MAN3DIR)/Parse::Pidl::Wireshark::NDR.$(MAN3EXT)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker processPL section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker installbin section:
|
|
||||||
|
|
||||||
EXE_FILES = pidl
|
|
||||||
|
|
||||||
pure_all :: $(INST_SCRIPT)/pidl
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
realclean ::
|
|
||||||
$(RM_F) \
|
|
||||||
$(INST_SCRIPT)/pidl
|
|
||||||
|
|
||||||
$(INST_SCRIPT)/pidl : pidl $(FIRST_MAKEFILE) $(INST_SCRIPT)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists
|
|
||||||
$(NOECHO) $(RM_F) $(INST_SCRIPT)/pidl
|
|
||||||
$(CP) pidl $(INST_SCRIPT)/pidl
|
|
||||||
$(FIXIN) $(INST_SCRIPT)/pidl
|
|
||||||
-$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_SCRIPT)/pidl
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker subdirs section:
|
|
||||||
|
|
||||||
# none
|
|
||||||
|
|
||||||
# --- MakeMaker clean_subdirs section:
|
|
||||||
clean_subdirs :
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker clean section:
|
|
||||||
|
|
||||||
# Delete temporary files but do not touch installed files. We don't delete
|
|
||||||
# the Makefile here so a later make realclean still has a makefile to use.
|
|
||||||
|
|
||||||
clean :: clean_subdirs
|
|
||||||
- $(RM_F) \
|
|
||||||
$(BASEEXT).bso $(BASEEXT).def \
|
|
||||||
$(BASEEXT).exp $(BASEEXT).x \
|
|
||||||
$(BOOTSTRAP) $(INST_ARCHAUTODIR)/extralibs.all \
|
|
||||||
$(INST_ARCHAUTODIR)/extralibs.ld $(MAKE_APERL_FILE) \
|
|
||||||
*$(LIB_EXT) *$(OBJ_EXT) \
|
|
||||||
*perl.core MYMETA.json \
|
|
||||||
MYMETA.yml blibdirs.ts \
|
|
||||||
core core.*perl.*.? \
|
|
||||||
core.[0-9] core.[0-9][0-9] \
|
|
||||||
core.[0-9][0-9][0-9] core.[0-9][0-9][0-9][0-9] \
|
|
||||||
core.[0-9][0-9][0-9][0-9][0-9] lib$(BASEEXT).def \
|
|
||||||
mon.out perl \
|
|
||||||
perl$(EXE_EXT) perl.exe \
|
|
||||||
perlmain.c pm_to_blib \
|
|
||||||
pm_to_blib.ts so_locations \
|
|
||||||
tmon.out
|
|
||||||
- $(RM_RF) \
|
|
||||||
blib
|
|
||||||
$(NOECHO) $(RM_F) $(MAKEFILE_OLD)
|
|
||||||
- $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL)
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker realclean_subdirs section:
|
|
||||||
realclean_subdirs :
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker realclean section:
|
|
||||||
# Delete temporary files (via clean) and also delete dist files
|
|
||||||
realclean purge :: clean realclean_subdirs
|
|
||||||
- $(RM_F) \
|
|
||||||
$(MAKEFILE_OLD) $(FIRST_MAKEFILE)
|
|
||||||
- $(RM_RF) \
|
|
||||||
$(DISTVNAME)
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker metafile section:
|
|
||||||
metafile : create_distdir
|
|
||||||
$(NOECHO) $(ECHO) Generating META.yml
|
|
||||||
$(NOECHO) $(ECHO) '---' > META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'abstract: unknown' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'author:' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) ' - unknown' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'build_requires:' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: '\''0'\''' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'configure_requires:' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: '\''0'\''' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'dynamic_config: 1' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'generated_by: '\''ExtUtils::MakeMaker version 7.1002, CPAN::Meta::Converter version 2.150005'\''' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'license: unknown' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'meta-spec:' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) ' url: http://module-build.sourceforge.net/META-spec-v1.4.html' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) ' version: '\''1.4'\''' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'name: Parse-Pidl' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'no_index:' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) ' directory:' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) ' - t' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) ' - inc' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'requires: {}' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'version: '\''0.02'\''' >> META_new.yml
|
|
||||||
$(NOECHO) $(ECHO) 'x_serialization_backend: '\''CPAN::Meta::YAML version 0.018'\''' >> META_new.yml
|
|
||||||
-$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml
|
|
||||||
$(NOECHO) $(ECHO) Generating META.json
|
|
||||||
$(NOECHO) $(ECHO) '{' > META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "abstract" : "unknown",' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "author" : [' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "unknown"' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' ],' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "dynamic_config" : 1,' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "generated_by" : "ExtUtils::MakeMaker version 7.1002, CPAN::Meta::Converter version 2.150005",' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "license" : [' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "unknown"' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' ],' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "meta-spec" : {' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "version" : "2"' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' },' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "name" : "Parse-Pidl",' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "no_index" : {' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "directory" : [' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "t",' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "inc"' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' ]' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' },' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "prereqs" : {' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "build" : {' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' }' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' },' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "configure" : {' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' }' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' },' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "runtime" : {' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "requires" : {}' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' }' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' },' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "release_status" : "stable",' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "version" : "0.02",' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) ' "x_serialization_backend" : "JSON::PP version 2.27300_01"' >> META_new.json
|
|
||||||
$(NOECHO) $(ECHO) '}' >> META_new.json
|
|
||||||
-$(NOECHO) $(MV) META_new.json $(DISTVNAME)/META.json
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker signature section:
|
|
||||||
signature :
|
|
||||||
cpansign -s
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker dist_basics section:
|
|
||||||
distclean :: realclean distcheck
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
distcheck :
|
|
||||||
$(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck
|
|
||||||
|
|
||||||
skipcheck :
|
|
||||||
$(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck
|
|
||||||
|
|
||||||
manifest :
|
|
||||||
$(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest
|
|
||||||
|
|
||||||
veryclean : realclean
|
|
||||||
$(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker dist_core section:
|
|
||||||
|
|
||||||
dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE)
|
|
||||||
$(NOECHO) $(ABSPERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \
|
|
||||||
-e ' if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' --
|
|
||||||
|
|
||||||
tardist : $(DISTVNAME).tar$(SUFFIX)
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
uutardist : $(DISTVNAME).tar$(SUFFIX)
|
|
||||||
uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu
|
|
||||||
$(NOECHO) $(ECHO) 'Created $(DISTVNAME).tar$(SUFFIX)_uu'
|
|
||||||
|
|
||||||
$(DISTVNAME).tar$(SUFFIX) : distdir
|
|
||||||
$(PREOP)
|
|
||||||
$(TO_UNIX)
|
|
||||||
$(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME)
|
|
||||||
$(RM_RF) $(DISTVNAME)
|
|
||||||
$(COMPRESS) $(DISTVNAME).tar
|
|
||||||
$(NOECHO) $(ECHO) 'Created $(DISTVNAME).tar$(SUFFIX)'
|
|
||||||
$(POSTOP)
|
|
||||||
|
|
||||||
zipdist : $(DISTVNAME).zip
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
$(DISTVNAME).zip : distdir
|
|
||||||
$(PREOP)
|
|
||||||
$(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME)
|
|
||||||
$(RM_RF) $(DISTVNAME)
|
|
||||||
$(NOECHO) $(ECHO) 'Created $(DISTVNAME).zip'
|
|
||||||
$(POSTOP)
|
|
||||||
|
|
||||||
shdist : distdir
|
|
||||||
$(PREOP)
|
|
||||||
$(SHAR) $(DISTVNAME) > $(DISTVNAME).shar
|
|
||||||
$(RM_RF) $(DISTVNAME)
|
|
||||||
$(NOECHO) $(ECHO) 'Created $(DISTVNAME).shar'
|
|
||||||
$(POSTOP)
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker distdir section:
|
|
||||||
create_distdir :
|
|
||||||
$(RM_RF) $(DISTVNAME)
|
|
||||||
$(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \
|
|
||||||
-e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');"
|
|
||||||
|
|
||||||
distdir : create_distdir distmeta
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker dist_test section:
|
|
||||||
disttest : distdir
|
|
||||||
cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL
|
|
||||||
cd $(DISTVNAME) && $(MAKE) $(PASTHRU)
|
|
||||||
cd $(DISTVNAME) && $(MAKE) test $(PASTHRU)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker dist_ci section:
|
|
||||||
ci :
|
|
||||||
$(ABSPERLRUN) -MExtUtils::Manifest=maniread -e '@all = sort keys %{ maniread() };' \
|
|
||||||
-e 'print(qq{Executing $(CI) @all\n});' \
|
|
||||||
-e 'system(qq{$(CI) @all}) == 0 or die $$!;' \
|
|
||||||
-e 'print(qq{Executing $(RCS_LABEL) ...\n});' \
|
|
||||||
-e 'system(qq{$(RCS_LABEL) @all}) == 0 or die $$!;' --
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker distmeta section:
|
|
||||||
distmeta : create_distdir metafile
|
|
||||||
$(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -e q{META.yml};' \
|
|
||||||
-e 'eval { maniadd({q{META.yml} => q{Module YAML meta-data (added by MakeMaker)}}) }' \
|
|
||||||
-e ' or print "Could not add META.yml to MANIFEST: $$$${'\''@'\''}\n"' --
|
|
||||||
$(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -f q{META.json};' \
|
|
||||||
-e 'eval { maniadd({q{META.json} => q{Module JSON meta-data (added by MakeMaker)}}) }' \
|
|
||||||
-e ' or print "Could not add META.json to MANIFEST: $$$${'\''@'\''}\n"' --
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker distsignature section:
|
|
||||||
distsignature : distmeta
|
|
||||||
$(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) }' \
|
|
||||||
-e ' or print "Could not add SIGNATURE to MANIFEST: $$$${'\''@'\''}\n"' --
|
|
||||||
$(NOECHO) cd $(DISTVNAME) && $(TOUCH) SIGNATURE
|
|
||||||
cd $(DISTVNAME) && cpansign -s
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker install section:
|
|
||||||
|
|
||||||
install :: pure_install doc_install
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
install_perl :: pure_perl_install doc_perl_install
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
install_site :: pure_site_install doc_site_install
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
install_vendor :: pure_vendor_install doc_vendor_install
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
pure_install :: pure_$(INSTALLDIRS)_install
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
doc_install :: doc_$(INSTALLDIRS)_install
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
pure__install : pure_site_install
|
|
||||||
$(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
|
|
||||||
|
|
||||||
doc__install : doc_site_install
|
|
||||||
$(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
|
|
||||||
|
|
||||||
pure_perl_install :: all
|
|
||||||
$(NOECHO) umask 022; $(MOD_INSTALL) \
|
|
||||||
"$(INST_LIB)" "$(DESTINSTALLPRIVLIB)" \
|
|
||||||
"$(INST_ARCHLIB)" "$(DESTINSTALLARCHLIB)" \
|
|
||||||
"$(INST_BIN)" "$(DESTINSTALLBIN)" \
|
|
||||||
"$(INST_SCRIPT)" "$(DESTINSTALLSCRIPT)" \
|
|
||||||
"$(INST_MAN1DIR)" "$(DESTINSTALLMAN1DIR)" \
|
|
||||||
"$(INST_MAN3DIR)" "$(DESTINSTALLMAN3DIR)"
|
|
||||||
$(NOECHO) $(WARN_IF_OLD_PACKLIST) \
|
|
||||||
"$(SITEARCHEXP)/auto/$(FULLEXT)"
|
|
||||||
|
|
||||||
|
|
||||||
pure_site_install :: all
|
|
||||||
$(NOECHO) umask 02; $(MOD_INSTALL) \
|
|
||||||
read "$(SITEARCHEXP)/auto/$(FULLEXT)/.packlist" \
|
|
||||||
write "$(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist" \
|
|
||||||
"$(INST_LIB)" "$(DESTINSTALLSITELIB)" \
|
|
||||||
"$(INST_ARCHLIB)" "$(DESTINSTALLSITEARCH)" \
|
|
||||||
"$(INST_BIN)" "$(DESTINSTALLSITEBIN)" \
|
|
||||||
"$(INST_SCRIPT)" "$(DESTINSTALLSITESCRIPT)" \
|
|
||||||
"$(INST_MAN1DIR)" "$(DESTINSTALLSITEMAN1DIR)" \
|
|
||||||
"$(INST_MAN3DIR)" "$(DESTINSTALLSITEMAN3DIR)"
|
|
||||||
$(NOECHO) $(WARN_IF_OLD_PACKLIST) \
|
|
||||||
"$(PERL_ARCHLIB)/auto/$(FULLEXT)"
|
|
||||||
|
|
||||||
pure_vendor_install :: all
|
|
||||||
$(NOECHO) umask 022; $(MOD_INSTALL) \
|
|
||||||
"$(INST_LIB)" "$(DESTINSTALLVENDORLIB)" \
|
|
||||||
"$(INST_ARCHLIB)" "$(DESTINSTALLVENDORARCH)" \
|
|
||||||
"$(INST_BIN)" "$(DESTINSTALLVENDORBIN)" \
|
|
||||||
"$(INST_SCRIPT)" "$(DESTINSTALLVENDORSCRIPT)" \
|
|
||||||
"$(INST_MAN1DIR)" "$(DESTINSTALLVENDORMAN1DIR)" \
|
|
||||||
"$(INST_MAN3DIR)" "$(DESTINSTALLVENDORMAN3DIR)"
|
|
||||||
|
|
||||||
|
|
||||||
doc_perl_install :: all
|
|
||||||
|
|
||||||
doc_site_install :: all
|
|
||||||
$(NOECHO) $(ECHO) Appending installation info to "$(DESTINSTALLSITEARCH)/perllocal.pod"
|
|
||||||
-$(NOECHO) umask 02; $(MKPATH) "$(DESTINSTALLSITEARCH)"
|
|
||||||
-$(NOECHO) umask 02; $(DOC_INSTALL) \
|
|
||||||
"Module" "$(NAME)" \
|
|
||||||
"installed into" $(INSTALLSITELIB) \
|
|
||||||
LINKTYPE "$(LINKTYPE)" \
|
|
||||||
VERSION "$(VERSION)" \
|
|
||||||
EXE_FILES "$(EXE_FILES)" \
|
|
||||||
>> "$(DESTINSTALLSITEARCH)/perllocal.pod"
|
|
||||||
|
|
||||||
doc_vendor_install :: all
|
|
||||||
|
|
||||||
|
|
||||||
uninstall :: uninstall_from_$(INSTALLDIRS)dirs
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
uninstall_from_perldirs ::
|
|
||||||
|
|
||||||
uninstall_from_sitedirs ::
|
|
||||||
$(NOECHO) $(UNINSTALL) "$(SITEARCHEXP)/auto/$(FULLEXT)/.packlist"
|
|
||||||
|
|
||||||
uninstall_from_vendordirs ::
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker force section:
|
|
||||||
# Phony target to force checking subdirectories.
|
|
||||||
FORCE :
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker perldepend section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker makefile section:
|
|
||||||
# We take a very conservative approach here, but it's worth it.
|
|
||||||
# We move Makefile to Makefile.old here to avoid gnu make looping.
|
|
||||||
$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP)
|
|
||||||
$(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?"
|
|
||||||
$(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..."
|
|
||||||
-$(NOECHO) $(RM_F) $(MAKEFILE_OLD)
|
|
||||||
-$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD)
|
|
||||||
- $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL)
|
|
||||||
$(PERLRUN) Makefile.PL
|
|
||||||
$(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <=="
|
|
||||||
$(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <=="
|
|
||||||
$(FALSE)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker staticmake section:
|
|
||||||
|
|
||||||
# --- MakeMaker makeaperl section ---
|
|
||||||
MAP_TARGET = perl
|
|
||||||
FULLPERL = "/usr/bin/perl"
|
|
||||||
|
|
||||||
$(MAP_TARGET) :: static $(MAKE_APERL_FILE)
|
|
||||||
$(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@
|
|
||||||
|
|
||||||
$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib
|
|
||||||
$(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET)
|
|
||||||
$(NOECHO) $(PERLRUNINST) \
|
|
||||||
Makefile.PL DIR="" \
|
|
||||||
MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
|
|
||||||
MAKEAPERL=1 NORECURS=1 CCCDLFLAGS=
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker test section:
|
|
||||||
|
|
||||||
TEST_VERBOSE=0
|
|
||||||
TEST_TYPE=test_$(LINKTYPE)
|
|
||||||
TEST_FILE = test.pl
|
|
||||||
TEST_FILES = tests/*.pl
|
|
||||||
TESTDB_SW = -d
|
|
||||||
|
|
||||||
testdb :: testdb_$(LINKTYPE)
|
|
||||||
|
|
||||||
test :: $(TEST_TYPE) subdirs-test
|
|
||||||
|
|
||||||
subdirs-test ::
|
|
||||||
$(NOECHO) $(NOOP)
|
|
||||||
|
|
||||||
|
|
||||||
test_dynamic :: pure_all
|
|
||||||
PERL_DL_NONLAZY=1 PERL_USE_UNSAFE_INC=1 $(FULLPERLRUN) "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES)
|
|
||||||
|
|
||||||
testdb_dynamic :: pure_all
|
|
||||||
PERL_DL_NONLAZY=1 PERL_USE_UNSAFE_INC=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE)
|
|
||||||
|
|
||||||
test_ : test_dynamic
|
|
||||||
|
|
||||||
test_static :: test_dynamic
|
|
||||||
testdb_static :: testdb_dynamic
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker ppd section:
|
|
||||||
# Creates a PPD (Perl Package Description) for a binary distribution.
|
|
||||||
ppd :
|
|
||||||
$(NOECHO) $(ECHO) '<SOFTPKG NAME="$(DISTNAME)" VERSION="$(VERSION)">' > $(DISTNAME).ppd
|
|
||||||
$(NOECHO) $(ECHO) ' <ABSTRACT></ABSTRACT>' >> $(DISTNAME).ppd
|
|
||||||
$(NOECHO) $(ECHO) ' <AUTHOR></AUTHOR>' >> $(DISTNAME).ppd
|
|
||||||
$(NOECHO) $(ECHO) ' <IMPLEMENTATION>' >> $(DISTNAME).ppd
|
|
||||||
$(NOECHO) $(ECHO) ' <ARCHITECTURE NAME="x86_64-linux-gnu-thread-multi-5.24" />' >> $(DISTNAME).ppd
|
|
||||||
$(NOECHO) $(ECHO) ' <CODEBASE HREF="" />' >> $(DISTNAME).ppd
|
|
||||||
$(NOECHO) $(ECHO) ' </IMPLEMENTATION>' >> $(DISTNAME).ppd
|
|
||||||
$(NOECHO) $(ECHO) '</SOFTPKG>' >> $(DISTNAME).ppd
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker pm_to_blib section:
|
|
||||||
|
|
||||||
pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM)
|
|
||||||
$(NOECHO) $(ABSPERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', q[$(PM_FILTER)], '\''$(PERM_DIR)'\'')' -- \
|
|
||||||
lib/Parse/Pidl.pm blib/lib/Parse/Pidl.pm \
|
|
||||||
lib/Parse/Pidl/CUtil.pm blib/lib/Parse/Pidl/CUtil.pm \
|
|
||||||
lib/Parse/Pidl/Compat.pm blib/lib/Parse/Pidl/Compat.pm \
|
|
||||||
lib/Parse/Pidl/Dump.pm blib/lib/Parse/Pidl/Dump.pm \
|
|
||||||
lib/Parse/Pidl/Expr.pm blib/lib/Parse/Pidl/Expr.pm \
|
|
||||||
lib/Parse/Pidl/IDL.pm blib/lib/Parse/Pidl/IDL.pm \
|
|
||||||
lib/Parse/Pidl/NDR.pm blib/lib/Parse/Pidl/NDR.pm \
|
|
||||||
lib/Parse/Pidl/ODL.pm blib/lib/Parse/Pidl/ODL.pm \
|
|
||||||
lib/Parse/Pidl/Samba3/ClientNDR.pm blib/lib/Parse/Pidl/Samba3/ClientNDR.pm \
|
|
||||||
lib/Parse/Pidl/Samba3/ServerNDR.pm blib/lib/Parse/Pidl/Samba3/ServerNDR.pm \
|
|
||||||
lib/Parse/Pidl/Samba3/Template.pm blib/lib/Parse/Pidl/Samba3/Template.pm \
|
|
||||||
lib/Parse/Pidl/Samba4.pm blib/lib/Parse/Pidl/Samba4.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/COM/Header.pm blib/lib/Parse/Pidl/Samba4/COM/Header.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/COM/Proxy.pm blib/lib/Parse/Pidl/Samba4/COM/Proxy.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/COM/Stub.pm blib/lib/Parse/Pidl/Samba4/COM/Stub.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/Header.pm blib/lib/Parse/Pidl/Samba4/Header.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Client.pm blib/lib/Parse/Pidl/Samba4/NDR/Client.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Parser.pm blib/lib/Parse/Pidl/Samba4/NDR/Parser.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/NDR/Server.pm blib/lib/Parse/Pidl/Samba4/NDR/Server.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/Python.pm blib/lib/Parse/Pidl/Samba4/Python.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/TDR.pm blib/lib/Parse/Pidl/Samba4/TDR.pm \
|
|
||||||
lib/Parse/Pidl/Samba4/Template.pm blib/lib/Parse/Pidl/Samba4/Template.pm \
|
|
||||||
lib/Parse/Pidl/Typelist.pm blib/lib/Parse/Pidl/Typelist.pm \
|
|
||||||
lib/Parse/Pidl/Util.pm blib/lib/Parse/Pidl/Util.pm \
|
|
||||||
lib/Parse/Pidl/Wireshark/Conformance.pm blib/lib/Parse/Pidl/Wireshark/Conformance.pm \
|
|
||||||
lib/Parse/Pidl/Wireshark/NDR.pm blib/lib/Parse/Pidl/Wireshark/NDR.pm \
|
|
||||||
lib/Parse/Yapp/Driver.pm blib/lib/Parse/Yapp/Driver.pm \
|
|
||||||
lib/wscript_build blib/lib/wscript_build
|
|
||||||
$(NOECHO) $(TOUCH) pm_to_blib
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker selfdocument section:
|
|
||||||
|
|
||||||
|
|
||||||
# --- MakeMaker postamble section:
|
|
||||||
lib/Parse/Pidl/IDL.pm: idl.yp
|
|
||||||
yapp -m 'Parse::Pidl::IDL' -o lib/Parse/Pidl/IDL.pm idl.yp
|
|
||||||
|
|
||||||
lib/Parse/Pidl/Expr.pm: expr.yp
|
|
||||||
yapp -m 'Parse::Pidl::Expr' -o lib/Parse/Pidl/Expr.pm expr.yp
|
|
||||||
|
|
||||||
|
|
||||||
# End.
|
|
|
@ -1,17 +0,0 @@
|
||||||
use ExtUtils::MakeMaker;
|
|
||||||
WriteMakefile(
|
|
||||||
'NAME' => 'Parse::Pidl',
|
|
||||||
'VERSION_FROM' => 'lib/Parse/Pidl.pm',
|
|
||||||
'EXE_FILES' => [ 'pidl' ],
|
|
||||||
'test' => { 'TESTS' => 'tests/*.pl' }
|
|
||||||
);
|
|
||||||
|
|
||||||
sub MY::postamble {
|
|
||||||
<<'EOT';
|
|
||||||
lib/Parse/Pidl/IDL.pm: idl.yp
|
|
||||||
yapp -m 'Parse::Pidl::IDL' -o lib/Parse/Pidl/IDL.pm idl.yp
|
|
||||||
|
|
||||||
lib/Parse/Pidl/Expr.pm: expr.yp
|
|
||||||
yapp -m 'Parse::Pidl::Expr' -o lib/Parse/Pidl/Expr.pm expr.yp
|
|
||||||
EOT
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
Introduction:
|
|
||||||
=============
|
|
||||||
This directory contains the source code of the pidl (Perl IDL)
|
|
||||||
compiler for Samba 4.
|
|
||||||
|
|
||||||
The main sources for pidl are available using Git as part of
|
|
||||||
the Samba source tree. Use:
|
|
||||||
git clone git://git.samba.org/samba.git
|
|
||||||
|
|
||||||
Pidl works by building a parse tree from a .pidl file (a simple
|
|
||||||
dump of it's internal parse tree) or a .idl file
|
|
||||||
(a file format mostly like the IDL file format midl uses).
|
|
||||||
The IDL file parser is in idl.yp (a yacc file converted to
|
|
||||||
perl code by yapp)
|
|
||||||
|
|
||||||
Standalone installation:
|
|
||||||
========================
|
|
||||||
Run Makefile.PL to generate the Makefile.
|
|
||||||
|
|
||||||
Then run "make install" (as root) to install.
|
|
||||||
|
|
||||||
Internals overview:
|
|
||||||
===================
|
|
||||||
|
|
||||||
After a parse tree is present, pidl will call one of it's backends
|
|
||||||
(which one depends on the options given on the command-line). Here is
|
|
||||||
a list of current backends:
|
|
||||||
|
|
||||||
-- Generic --
|
|
||||||
Parse::Pidl::Dump - Converts the parse tree back to an IDL file
|
|
||||||
Parse::Pidl::Samba4::Header - Generates header file with data structures defined in IDL file
|
|
||||||
Parse::Pidl::NDR - Generates intermediate datastructures for use by NDR parses/generators
|
|
||||||
Parse::Pidl::ODL - Generates IDL structures from ODL structures for use in the NDR parser generator
|
|
||||||
Parse::Pidl::Test - Utility functions for use in pidl's testsuite
|
|
||||||
|
|
||||||
-- Samba NDR --
|
|
||||||
Parse::Pidl::Samba4::NDR::Client - Generates client call functions in C using the NDR parser
|
|
||||||
Parse::Pidl::Samba4::NDR::Parser - Generates pull/push functions for parsing NDR
|
|
||||||
Parse::Pidl::Samba4::NDR::Server - Generates server side implementation in C
|
|
||||||
Parse::Pidl::Samba4::TDR - Parser generator for the "Trivial Data Representation"
|
|
||||||
Parse::Pidl::Samba4::Template - Generates stubs in C for server implementation
|
|
||||||
Parse::Pidl::Samba4::Python - Generates bindings for Python
|
|
||||||
|
|
||||||
-- Samba COM / DCOM --
|
|
||||||
Parse::Pidl::Samba4::COM::Proxy - Generates proxy object for DCOM (client-side)
|
|
||||||
Parse::Pidl::Samba4::COM::Stub - Generates stub call handler for DCOM (server-side)
|
|
||||||
Parse::Pidl::Samba4::COM::Header - Generates headers for COM
|
|
||||||
|
|
||||||
-- Wireshark --
|
|
||||||
Parse::Pidl::Wireshark::NDR - Generates a parser for the Wireshark network sniffer
|
|
||||||
Parse::Pidl::Wireshark::Conformance - Reads conformance files containing additional data for generating Wireshark parsers
|
|
||||||
|
|
||||||
-- Utility modules --
|
|
||||||
Parse::Pidl::Util - Misc utility functions used by *.pm and pidl.pl
|
|
||||||
Parse::Pidl::Typelist - Utility functions for keeping track of known types and their representation in C
|
|
||||||
|
|
||||||
Tips for hacking on pidl:
|
|
||||||
- Inspect pidl's parse tree by using the --keep option and looking at the
|
|
||||||
generated .pidl file.
|
|
||||||
- The various backends have a lot in common, if you don't understand how one
|
|
||||||
implements something, look at the others.
|
|
||||||
- See pidl(1) and the documentation on midl
|
|
||||||
- See 'info bison' and yapp(1) for information on the file format of idl.yp
|
|
||||||
- Run the tests (all in tests/)
|
|
|
@ -1,44 +0,0 @@
|
||||||
- warn when union instances don't have a discriminant
|
|
||||||
|
|
||||||
- true multiple dimension array / strings in arrays support
|
|
||||||
|
|
||||||
- compatibility mode for generating MIDL-readable data:
|
|
||||||
- strip out pidl-specific properties
|
|
||||||
|
|
||||||
- make bitmap an optional attribute on enum
|
|
||||||
- support nested elements
|
|
||||||
- support typedefs properly (e.g. allow "typedef void **bla;")
|
|
||||||
- make typedefs generate real typedefs
|
|
||||||
- improve represent_as(): allow it to be used for arrays and other complex
|
|
||||||
types
|
|
||||||
|
|
||||||
- --explain-ndr option that dumps out parse tree ?
|
|
||||||
|
|
||||||
- separate tables for NDR and DCE/RPC
|
|
||||||
- maybe no tables for NDR at all? we only need them for ndrdump
|
|
||||||
and that can use dlsym()
|
|
||||||
|
|
||||||
- allow data structures outside of interfaces
|
|
||||||
|
|
||||||
- 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
|
|
||||||
|
|
||||||
- support converting structs to tuples in Python rather than objects
|
|
||||||
- convert structs with a single mattering member to that member directly, e.g.:
|
|
||||||
struct bar {
|
|
||||||
int size;
|
|
||||||
[size_is(size)] uint32 *array;
|
|
||||||
};
|
|
||||||
|
|
||||||
should be converted to an array of uint32's
|
|
||||||
|
|
||||||
- python: fill in size members automatically in some places if the struct isn't being returned
|
|
||||||
(so we don't have to cope with the array growing)
|
|
|
@ -1,44 +0,0 @@
|
||||||
###################################################
|
|
||||||
# package to parse IDL files and generate code for
|
|
||||||
# rpc functions in Samba
|
|
||||||
# Copyright tridge@samba.org 2000-2003
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(warning error fatal $VERSION);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw ( $VERSION );
|
|
||||||
|
|
||||||
$VERSION = '0.02';
|
|
||||||
|
|
||||||
sub warning
|
|
||||||
{
|
|
||||||
my ($l,$m) = @_;
|
|
||||||
if ($l) {
|
|
||||||
print STDERR "$l->{FILE}:$l->{LINE}: ";
|
|
||||||
}
|
|
||||||
print STDERR "warning: $m\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub error
|
|
||||||
{
|
|
||||||
my ($l,$m) = @_;
|
|
||||||
if ($l) {
|
|
||||||
print STDERR "$l->{FILE}:$l->{LINE}: ";
|
|
||||||
}
|
|
||||||
print STDERR "error: $m\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub fatal($$)
|
|
||||||
{
|
|
||||||
my ($e,$s) = @_;
|
|
||||||
die("$e->{FILE}:$e->{LINE}: $s\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,52 +0,0 @@
|
||||||
###################################################
|
|
||||||
# C utility functions for pidl
|
|
||||||
# Copyright jelmer@samba.org 2005-2007
|
|
||||||
# released under the GNU GPL
|
|
||||||
package Parse::Pidl::CUtil;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT = qw(get_pointer_to get_value_of get_array_element);
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
sub get_pointer_to($)
|
|
||||||
{
|
|
||||||
my $var_name = shift;
|
|
||||||
|
|
||||||
if ($var_name =~ /^\*(.*)$/) {
|
|
||||||
return $1;
|
|
||||||
} elsif ($var_name =~ /^\&(.*)$/) {
|
|
||||||
return "&($var_name)";
|
|
||||||
} else {
|
|
||||||
return "&$var_name";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_value_of($)
|
|
||||||
{
|
|
||||||
my $var_name = shift;
|
|
||||||
|
|
||||||
if ($var_name =~ /^\&(.*)$/) {
|
|
||||||
return $1;
|
|
||||||
} else {
|
|
||||||
return "*$var_name";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_array_element($$)
|
|
||||||
{
|
|
||||||
my ($var_name, $idx) = @_;
|
|
||||||
|
|
||||||
if ($var_name =~ /^\*.*$/) {
|
|
||||||
$var_name = "($var_name)";
|
|
||||||
} elsif ($var_name =~ /^\&.*$/) {
|
|
||||||
$var_name = "($var_name)";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "$var_name"."[$idx]";
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,168 +0,0 @@
|
||||||
###################################################
|
|
||||||
# IDL Compatibility checker
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Compat;
|
|
||||||
|
|
||||||
use Parse::Pidl qw(warning);
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
my %supported_properties = (
|
|
||||||
# interface
|
|
||||||
"helpstring" => ["INTERFACE", "FUNCTION"],
|
|
||||||
"version" => ["INTERFACE"],
|
|
||||||
"uuid" => ["INTERFACE"],
|
|
||||||
"endpoint" => ["INTERFACE"],
|
|
||||||
"pointer_default" => ["INTERFACE"],
|
|
||||||
"no_srv_register" => ["INTERFACE"],
|
|
||||||
|
|
||||||
# dcom
|
|
||||||
"object" => ["INTERFACE"],
|
|
||||||
"local" => ["INTERFACE", "FUNCTION"],
|
|
||||||
"iid_is" => ["ELEMENT"],
|
|
||||||
"call_as" => ["FUNCTION"],
|
|
||||||
"idempotent" => ["FUNCTION"],
|
|
||||||
|
|
||||||
# function
|
|
||||||
"in" => ["ELEMENT"],
|
|
||||||
"out" => ["ELEMENT"],
|
|
||||||
|
|
||||||
# pointer
|
|
||||||
"ref" => ["ELEMENT"],
|
|
||||||
"ptr" => ["ELEMENT"],
|
|
||||||
"unique" => ["ELEMENT"],
|
|
||||||
"ignore" => ["ELEMENT"],
|
|
||||||
|
|
||||||
"value" => ["ELEMENT"],
|
|
||||||
|
|
||||||
# generic
|
|
||||||
"public" => ["FUNCTION", "TYPEDEF"],
|
|
||||||
"nopush" => ["FUNCTION", "TYPEDEF"],
|
|
||||||
"nopull" => ["FUNCTION", "TYPEDEF"],
|
|
||||||
"noprint" => ["FUNCTION", "TYPEDEF"],
|
|
||||||
"nopython" => ["FUNCTION", "TYPEDEF"],
|
|
||||||
|
|
||||||
# union
|
|
||||||
"switch_is" => ["ELEMENT"],
|
|
||||||
"switch_type" => ["ELEMENT", "TYPEDEF"],
|
|
||||||
"case" => ["ELEMENT"],
|
|
||||||
"default" => ["ELEMENT"],
|
|
||||||
|
|
||||||
# subcontext
|
|
||||||
"subcontext" => ["ELEMENT"],
|
|
||||||
"subcontext_size" => ["ELEMENT"],
|
|
||||||
|
|
||||||
# enum
|
|
||||||
"enum16bit" => ["TYPEDEF"],
|
|
||||||
"v1_enum" => ["TYPEDEF"],
|
|
||||||
|
|
||||||
# bitmap
|
|
||||||
"bitmap8bit" => ["TYPEDEF"],
|
|
||||||
"bitmap16bit" => ["TYPEDEF"],
|
|
||||||
"bitmap32bit" => ["TYPEDEF"],
|
|
||||||
"bitmap64bit" => ["TYPEDEF"],
|
|
||||||
|
|
||||||
# array
|
|
||||||
"range" => ["ELEMENT"],
|
|
||||||
"size_is" => ["ELEMENT"],
|
|
||||||
"string" => ["ELEMENT"],
|
|
||||||
"noheader" => ["ELEMENT"],
|
|
||||||
"charset" => ["ELEMENT"],
|
|
||||||
"length_is" => ["ELEMENT"],
|
|
||||||
);
|
|
||||||
|
|
||||||
sub CheckTypedef($)
|
|
||||||
{
|
|
||||||
my ($td) = @_;
|
|
||||||
|
|
||||||
if (has_property($td, "nodiscriminant")) {
|
|
||||||
warning($td, "nodiscriminant property not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($td->{TYPE} eq "BITMAP") {
|
|
||||||
warning($td, "converting bitmap to scalar");
|
|
||||||
#FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($td, "gensize")) {
|
|
||||||
warning($td, "ignoring gensize() property. ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($td, "enum8bit") and has_property($td, "enum16bit")) {
|
|
||||||
warning($td, "8 and 16 bit enums not supported, converting to scalar");
|
|
||||||
#FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
StripProperties($td);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CheckElement($)
|
|
||||||
{
|
|
||||||
my $e = shift;
|
|
||||||
|
|
||||||
if (has_property($e, "noheader")) {
|
|
||||||
warning($e, "noheader property not supported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "subcontext")) {
|
|
||||||
warning($e, "converting subcontext to byte array");
|
|
||||||
#FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "compression")) {
|
|
||||||
warning($e, "compression() property not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "sptr")) {
|
|
||||||
warning($e, "sptr() pointer property not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "relative")) {
|
|
||||||
warning($e, "relative() pointer property not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "relative_short")) {
|
|
||||||
warning($e, "relative_short() pointer property not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "flag")) {
|
|
||||||
warning($e, "ignoring flag() property");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "value")) {
|
|
||||||
warning($e, "ignoring value() property");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CheckFunction($)
|
|
||||||
{
|
|
||||||
my $fn = shift;
|
|
||||||
|
|
||||||
if (has_property($fn, "noopnum")) {
|
|
||||||
warning($fn, "noopnum not converted. Opcodes will be out of sync.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CheckInterface($)
|
|
||||||
{
|
|
||||||
my $if = shift;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Check($)
|
|
||||||
{
|
|
||||||
my $pidl = shift;
|
|
||||||
my $nidl = [];
|
|
||||||
|
|
||||||
foreach (@{$pidl}) {
|
|
||||||
push (@$nidl, CheckInterface($_)) if ($_->{TYPE} eq "INTERFACE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,294 +0,0 @@
|
||||||
###################################################
|
|
||||||
# dump function for IDL structures
|
|
||||||
# Copyright tridge@samba.org 2000
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
Parse::Pidl::Dump - Dump support
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
This module provides functions that can generate IDL code from
|
|
||||||
internal pidl data structures.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
package Parse::Pidl::Dump;
|
|
||||||
|
|
||||||
use Exporter;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(DumpType DumpTypedef DumpStruct DumpEnum DumpBitmap DumpUnion DumpFunction);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a properties list
|
|
||||||
sub DumpProperties($)
|
|
||||||
{
|
|
||||||
my($props) = shift;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
foreach my $d ($props) {
|
|
||||||
foreach my $k (sort(keys %{$d})) {
|
|
||||||
if ($k eq "in") {
|
|
||||||
$res .= "[in] ";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if ($k eq "out") {
|
|
||||||
$res .= "[out] ";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if ($k eq "ref") {
|
|
||||||
$res .= "[ref] ";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
$res .= "[$k($d->{$k})] ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a structure element
|
|
||||||
sub DumpElement($)
|
|
||||||
{
|
|
||||||
my($element) = shift;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
(defined $element->{PROPERTIES}) &&
|
|
||||||
($res .= DumpProperties($element->{PROPERTIES}));
|
|
||||||
$res .= DumpType($element->{TYPE});
|
|
||||||
$res .= " ";
|
|
||||||
for my $i (1..$element->{POINTERS}) {
|
|
||||||
$res .= "*";
|
|
||||||
}
|
|
||||||
$res .= "$element->{NAME}";
|
|
||||||
foreach (@{$element->{ARRAY_LEN}}) {
|
|
||||||
$res .= "[$_]";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a struct
|
|
||||||
sub DumpStruct($)
|
|
||||||
{
|
|
||||||
my($struct) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= "struct ";
|
|
||||||
if ($struct->{NAME}) {
|
|
||||||
$res.="$struct->{NAME} ";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res.="{\n";
|
|
||||||
if (defined $struct->{ELEMENTS}) {
|
|
||||||
foreach (@{$struct->{ELEMENTS}}) {
|
|
||||||
$res .= "\t" . DumpElement($_) . ";\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$res .= "}";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a struct
|
|
||||||
sub DumpEnum($)
|
|
||||||
{
|
|
||||||
my($enum) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= "enum {\n";
|
|
||||||
|
|
||||||
foreach (@{$enum->{ELEMENTS}}) {
|
|
||||||
if (/^([A-Za-z0-9_]+)[ \t]*\((.*)\)$/) {
|
|
||||||
$res .= "\t$1 = $2,\n";
|
|
||||||
} else {
|
|
||||||
$res .= "\t$_,\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res.= "}";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a struct
|
|
||||||
sub DumpBitmap($)
|
|
||||||
{
|
|
||||||
my($bitmap) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= "bitmap {\n";
|
|
||||||
|
|
||||||
foreach (@{$bitmap->{ELEMENTS}}) {
|
|
||||||
if (/^([A-Za-z0-9_]+)[ \t]*\((.*)\)$/) {
|
|
||||||
$res .= "\t$1 = $2,\n";
|
|
||||||
} else {
|
|
||||||
die ("Bitmap $bitmap->{NAME} has field $_ without proper value");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res.= "}";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a union element
|
|
||||||
sub DumpUnionElement($)
|
|
||||||
{
|
|
||||||
my($element) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
if (has_property($element, "default")) {
|
|
||||||
$res .= "[default] ;\n";
|
|
||||||
} else {
|
|
||||||
$res .= "[case($element->{PROPERTIES}->{case})] ";
|
|
||||||
$res .= DumpElement($element), if defined($element);
|
|
||||||
$res .= ";\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a union
|
|
||||||
sub DumpUnion($)
|
|
||||||
{
|
|
||||||
my($union) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
(defined $union->{PROPERTIES}) &&
|
|
||||||
($res .= DumpProperties($union->{PROPERTIES}));
|
|
||||||
$res .= "union {\n";
|
|
||||||
foreach my $e (@{$union->{ELEMENTS}}) {
|
|
||||||
$res .= DumpUnionElement($e);
|
|
||||||
}
|
|
||||||
$res .= "}";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a type
|
|
||||||
sub DumpType($)
|
|
||||||
{
|
|
||||||
my($data) = shift;
|
|
||||||
|
|
||||||
if (ref($data) eq "HASH") {
|
|
||||||
return DumpStruct($data) if ($data->{TYPE} eq "STRUCT");
|
|
||||||
return DumpUnion($data) if ($data->{TYPE} eq "UNION");
|
|
||||||
return DumpEnum($data) if ($data->{TYPE} eq "ENUM");
|
|
||||||
return DumpBitmap($data) if ($data->{TYPE} eq "BITMAP");
|
|
||||||
} else {
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a typedef
|
|
||||||
sub DumpTypedef($)
|
|
||||||
{
|
|
||||||
my($typedef) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= "typedef ";
|
|
||||||
$res .= DumpType($typedef->{DATA});
|
|
||||||
$res .= " $typedef->{NAME};\n\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a typedef
|
|
||||||
sub DumpFunction($)
|
|
||||||
{
|
|
||||||
my($function) = shift;
|
|
||||||
my($first) = 1;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= DumpType($function->{RETURN_TYPE});
|
|
||||||
$res .= " $function->{NAME}(\n";
|
|
||||||
for my $d (@{$function->{ELEMENTS}}) {
|
|
||||||
unless ($first) { $res .= ",\n"; } $first = 0;
|
|
||||||
$res .= DumpElement($d);
|
|
||||||
}
|
|
||||||
$res .= "\n);\n\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a module header
|
|
||||||
sub DumpInterfaceProperties($)
|
|
||||||
{
|
|
||||||
my($header) = shift;
|
|
||||||
my($data) = $header->{DATA};
|
|
||||||
my($first) = 1;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= "[\n";
|
|
||||||
foreach my $k (sort(keys %{$data})) {
|
|
||||||
$first || ($res .= ",\n"); $first = 0;
|
|
||||||
$res .= "$k($data->{$k})";
|
|
||||||
}
|
|
||||||
$res .= "\n]\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump the interface definitions
|
|
||||||
sub DumpInterface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= DumpInterfaceProperties($interface->{PROPERTIES});
|
|
||||||
|
|
||||||
$res .= "interface $interface->{NAME}\n{\n";
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
($d->{TYPE} eq "TYPEDEF") &&
|
|
||||||
($res .= DumpTypedef($d));
|
|
||||||
($d->{TYPE} eq "FUNCTION") &&
|
|
||||||
($res .= DumpFunction($d));
|
|
||||||
}
|
|
||||||
$res .= "}\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a parsed IDL structure back into an IDL file
|
|
||||||
sub Dump($)
|
|
||||||
{
|
|
||||||
my($idl) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res = "/* Dumped by pidl */\n\n";
|
|
||||||
foreach my $x (@{$idl}) {
|
|
||||||
($x->{TYPE} eq "INTERFACE") &&
|
|
||||||
($res .= DumpInterface($x));
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,130 +0,0 @@
|
||||||
##########################################
|
|
||||||
# Converts ODL stuctures to IDL structures
|
|
||||||
# (C) 2004-2005, 2008 Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
|
|
||||||
package Parse::Pidl::ODL;
|
|
||||||
|
|
||||||
use Parse::Pidl qw(error);
|
|
||||||
use Parse::Pidl::IDL;
|
|
||||||
use Parse::Pidl::Util qw(has_property unmake_str);
|
|
||||||
use Parse::Pidl::Typelist qw(hasType getType);
|
|
||||||
use File::Basename;
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
sub FunctionAddObjArgs($)
|
|
||||||
{
|
|
||||||
my $e = shift;
|
|
||||||
|
|
||||||
unshift(@{$e->{ELEMENTS}}, {
|
|
||||||
'NAME' => 'ORPCthis',
|
|
||||||
'POINTERS' => 0,
|
|
||||||
'PROPERTIES' => { 'in' => '1' },
|
|
||||||
'TYPE' => 'ORPCTHIS',
|
|
||||||
'FILE' => $e->{FILE},
|
|
||||||
'LINE' => $e->{LINE}
|
|
||||||
});
|
|
||||||
unshift(@{$e->{ELEMENTS}}, {
|
|
||||||
'NAME' => 'ORPCthat',
|
|
||||||
'POINTERS' => 1,
|
|
||||||
'PROPERTIES' => { 'out' => '1', 'ref' => '1' },
|
|
||||||
'TYPE' => 'ORPCTHAT',
|
|
||||||
'FILE' => $e->{FILE},
|
|
||||||
'LINE' => $e->{LINE}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ReplaceInterfacePointers($)
|
|
||||||
{
|
|
||||||
my ($e) = @_;
|
|
||||||
foreach my $x (@{$e->{ELEMENTS}}) {
|
|
||||||
next unless (hasType($x->{TYPE}));
|
|
||||||
next unless getType($x->{TYPE})->{DATA}->{TYPE} eq "INTERFACE";
|
|
||||||
|
|
||||||
$x->{TYPE} = "MInterfacePointer";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add ORPC specific bits to an interface.
|
|
||||||
sub ODL2IDL
|
|
||||||
{
|
|
||||||
my ($odl, $basedir, $opt_incdirs) = (@_);
|
|
||||||
my $addedorpc = 0;
|
|
||||||
my $interfaces = {};
|
|
||||||
|
|
||||||
foreach my $x (@$odl) {
|
|
||||||
if ($x->{TYPE} eq "IMPORT") {
|
|
||||||
foreach my $idl_file (@{$x->{PATHS}}) {
|
|
||||||
$idl_file = unmake_str($idl_file);
|
|
||||||
my $idl_path = undef;
|
|
||||||
foreach ($basedir, @$opt_incdirs) {
|
|
||||||
if (-f "$_/$idl_file") {
|
|
||||||
$idl_path = "$_/$idl_file";
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unless ($idl_path) {
|
|
||||||
error($x, "Unable to open include file `$idl_file'");
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
my $podl = Parse::Pidl::IDL::parse_file($idl_path, $opt_incdirs);
|
|
||||||
if (defined($podl)) {
|
|
||||||
require Parse::Pidl::Typelist;
|
|
||||||
my $basename = basename($idl_path, ".idl");
|
|
||||||
|
|
||||||
Parse::Pidl::Typelist::LoadIdl($podl, $basename);
|
|
||||||
my $pidl = ODL2IDL($podl, $basedir, $opt_incdirs);
|
|
||||||
|
|
||||||
foreach my $y (@$pidl) {
|
|
||||||
if ($y->{TYPE} eq "INTERFACE") {
|
|
||||||
$interfaces->{$y->{NAME}} = $y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error($x, "Failed to parse $idl_path");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($x->{TYPE} eq "INTERFACE") {
|
|
||||||
$interfaces->{$x->{NAME}} = $x;
|
|
||||||
# Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
|
|
||||||
# and replace interfacepointers with MInterfacePointer
|
|
||||||
# for 'object' interfaces
|
|
||||||
if (has_property($x, "object")) {
|
|
||||||
foreach my $e (@{$x->{DATA}}) {
|
|
||||||
($e->{TYPE} eq "FUNCTION") && FunctionAddObjArgs($e);
|
|
||||||
ReplaceInterfacePointers($e);
|
|
||||||
}
|
|
||||||
$addedorpc = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($x->{BASE}) {
|
|
||||||
my $base = $interfaces->{$x->{BASE}};
|
|
||||||
|
|
||||||
unless (defined($base)) {
|
|
||||||
error($x, "Undefined base interface `$x->{BASE}'");
|
|
||||||
} else {
|
|
||||||
foreach my $fn (reverse @{$base->{DATA}}) {
|
|
||||||
next unless ($fn->{TYPE} eq "FUNCTION");
|
|
||||||
push (@{$x->{INHERITED_FUNCTIONS}}, $fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unshift (@$odl, {
|
|
||||||
TYPE => "IMPORT",
|
|
||||||
PATHS => [ "\"orpc.idl\"" ],
|
|
||||||
FILE => undef,
|
|
||||||
LINE => undef
|
|
||||||
}) if ($addedorpc);
|
|
||||||
|
|
||||||
|
|
||||||
return $odl;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,409 +0,0 @@
|
||||||
###################################################
|
|
||||||
# Samba3 client generator for IDL structures
|
|
||||||
# on top of Samba4 style NDR functions
|
|
||||||
# Copyright jelmer@samba.org 2005-2006
|
|
||||||
# Copyright gd@samba.org 2008
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba3::ClientNDR;
|
|
||||||
|
|
||||||
use Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(ParseFunction $res $res_hdr);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Parse::Pidl qw(fatal warning error);
|
|
||||||
use Parse::Pidl::Util qw(has_property ParseExpr genpad);
|
|
||||||
use Parse::Pidl::NDR qw(ContainsPipe);
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
|
||||||
use Parse::Pidl::Samba4 qw(DeclLong);
|
|
||||||
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; }
|
|
||||||
sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); }
|
|
||||||
sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; }
|
|
||||||
sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; }
|
|
||||||
sub fn_declare($$) { my ($self,$n) = @_; $self->pidl($n); $self->pidl_hdr("$n;"); }
|
|
||||||
|
|
||||||
sub new($)
|
|
||||||
{
|
|
||||||
my ($class) = shift;
|
|
||||||
my $self = { res => "", res_hdr => "", tabs => "" };
|
|
||||||
bless($self, $class);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ElementDirection($)
|
|
||||||
{
|
|
||||||
my ($e) = @_;
|
|
||||||
|
|
||||||
return "[in,out]" 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 "[in,out]";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub HeaderProperties($$)
|
|
||||||
{
|
|
||||||
my($props,$ignores) = @_;
|
|
||||||
my $ret = "";
|
|
||||||
|
|
||||||
foreach my $d (sort(keys %{$props})) {
|
|
||||||
next if (grep(/^$d$/, @$ignores));
|
|
||||||
if($props->{$d} ne "1") {
|
|
||||||
$ret.= "$d($props->{$d}),";
|
|
||||||
} else {
|
|
||||||
$ret.="$d,";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ret) {
|
|
||||||
return "[" . substr($ret, 0, -1) . "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseInvalidResponse($$)
|
|
||||||
{
|
|
||||||
my ($self, $type) = @_;
|
|
||||||
|
|
||||||
if ($type eq "sync") {
|
|
||||||
$self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;");
|
|
||||||
} elsif ($type eq "async") {
|
|
||||||
$self->pidl("tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);");
|
|
||||||
$self->pidl("return;");
|
|
||||||
} else {
|
|
||||||
die("ParseInvalidResponse($type)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionAsyncState($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
|
||||||
my $done_fn = "rpccli_$fn->{NAME}_done";
|
|
||||||
|
|
||||||
$self->pidl("$state_str {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl(mapTypeName($fn->{RETURN_TYPE}). " result;");
|
|
||||||
}
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("};");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("static void $done_fn(struct tevent_req *subreq);");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionAsyncSend($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
my $fn_args = "";
|
|
||||||
my $uif = uc($if);
|
|
||||||
my $ufn = "NDR_".uc($fn->{NAME});
|
|
||||||
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
|
||||||
my $done_fn = "rpccli_$fn->{NAME}_done";
|
|
||||||
my $out_mem_ctx = "rpccli_$fn->{NAME}_out_memory";
|
|
||||||
my $fn_str = "struct tevent_req *rpccli_$fn->{NAME}_send";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "TALLOC_CTX *mem_ctx";
|
|
||||||
$fn_args .= ",\n" . $pad . "struct tevent_context *ev";
|
|
||||||
$fn_args .= ",\n" . $pad . "struct rpc_pipe_client *cli";
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
my $dir = ElementDirection($_);
|
|
||||||
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
|
||||||
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct tevent_req *req;");
|
|
||||||
$self->pidl("$state_str *state;");
|
|
||||||
$self->pidl("struct tevent_req *subreq;");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
|
||||||
$self->pidl("\t\t\t$state_str);");
|
|
||||||
$self->pidl("if (req == NULL) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return NULL;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("state->out_mem_ctx = NULL;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
my $out_params = 0;
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
if (grep(/out/, @{$_->{DIRECTION}})) {
|
|
||||||
$out_params++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($out_params > 0) {
|
|
||||||
$self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,");
|
|
||||||
$self->pidl("\t\t \"$out_mem_ctx\");");
|
|
||||||
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$fn_str = "subreq = dcerpc_$fn->{NAME}_send";
|
|
||||||
$pad = "\t" . genpad($fn_str);
|
|
||||||
$fn_args = "state,\n" . $pad . "ev,\n" . $pad . "cli->binding_handle";
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
$fn_args .= ",\n" . $pad . "_". $_->{NAME};
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("$fn_str($fn_args);");
|
|
||||||
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("tevent_req_set_callback(subreq, $done_fn, req);");
|
|
||||||
$self->pidl("return req;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionAsyncDone($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
|
||||||
my $done_fn = "rpccli_$fn->{NAME}_done";
|
|
||||||
|
|
||||||
$self->pidl("static void $done_fn(struct tevent_req *subreq)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct tevent_req *req = tevent_req_callback_data(");
|
|
||||||
$self->pidl("\tsubreq, struct tevent_req);");
|
|
||||||
$self->pidl("$state_str *state = tevent_req_data(");
|
|
||||||
$self->pidl("\treq, $state_str);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("TALLOC_CTX *mem_ctx;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("if (state->out_mem_ctx) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("mem_ctx = state->out_mem_ctx;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("} else {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("mem_ctx = state;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
my $fn_str = "status = dcerpc_$fn->{NAME}_recv";
|
|
||||||
my $pad = "\t" . genpad($fn_str);
|
|
||||||
my $fn_args = "subreq,\n" . $pad . "mem_ctx";
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$fn_args .= ",\n" . $pad . "&state->result";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("$fn_str($fn_args);");
|
|
||||||
$self->pidl("TALLOC_FREE(subreq);");
|
|
||||||
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("tevent_req_nterror(req, status);");
|
|
||||||
$self->pidl("return;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_done(req);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionAsyncRecv($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
my $fn_args = "";
|
|
||||||
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
|
||||||
my $fn_str = "NTSTATUS rpccli_$fn->{NAME}_recv";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "struct tevent_req *req,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$fn_args .= ",\n" . $pad . "$fn->{RETURN_TYPE} *result";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("$state_str *state = tevent_req_data(");
|
|
||||||
$self->pidl("\treq, $state_str);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return status;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Steal possible out parameters to the callers context */");
|
|
||||||
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl("/* Return result */");
|
|
||||||
$self->pidl("*result = state->result;");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionSync($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
my $fn_args = "";
|
|
||||||
my $uif = uc($if);
|
|
||||||
my $ufn = "NDR_".uc($fn->{NAME});
|
|
||||||
my $fn_str = "NTSTATUS rpccli_$fn->{NAME}";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "struct rpc_pipe_client *cli,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
my $dir = ElementDirection($_);
|
|
||||||
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
|
||||||
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE}) && ($fn->{RETURN_TYPE} eq "WERROR")) {
|
|
||||||
$fn_args .= ",\n" . $pad . "WERROR *werror";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl(mapTypeName($fn->{RETURN_TYPE})." result;");
|
|
||||||
}
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$fn_str = "status = dcerpc_$fn->{NAME}";
|
|
||||||
$pad = "\t" . genpad($fn_str);
|
|
||||||
$fn_args = "cli->binding_handle,\n" . $pad . "mem_ctx";
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
$fn_args .= ",\n" . $pad . "_". $_->{NAME};
|
|
||||||
}
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$fn_args .= ",\n" . $pad . "&result";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("$fn_str($fn_args);");
|
|
||||||
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return status;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Return result */");
|
|
||||||
if (not $fn->{RETURN_TYPE}) {
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
} elsif ($fn->{RETURN_TYPE} eq "NTSTATUS") {
|
|
||||||
$self->pidl("return result;");
|
|
||||||
} elsif ($fn->{RETURN_TYPE} eq "WERROR") {
|
|
||||||
$self->pidl("if (werror) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("*werror = result;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("return werror_to_ntstatus(result);");
|
|
||||||
} else {
|
|
||||||
warning($fn->{ORIGINAL}, "Unable to convert $fn->{RETURN_TYPE} to NTSTATUS");
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
$self->ParseFunctionAsyncState($if, $fn);
|
|
||||||
$self->ParseFunctionAsyncSend($if, $fn);
|
|
||||||
$self->ParseFunctionAsyncDone($if, $fn);
|
|
||||||
$self->ParseFunctionAsyncRecv($if, $fn);
|
|
||||||
|
|
||||||
$self->ParseFunctionSync($if, $fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseInterface($$)
|
|
||||||
{
|
|
||||||
my ($self, $if) = @_;
|
|
||||||
|
|
||||||
my $uif = uc($if->{NAME});
|
|
||||||
|
|
||||||
$self->pidl_hdr("#ifndef __CLI_$uif\__");
|
|
||||||
$self->pidl_hdr("#define __CLI_$uif\__");
|
|
||||||
foreach my $fn (@{$if->{FUNCTIONS}}) {
|
|
||||||
next if has_property($fn, "noopnum");
|
|
||||||
next if has_property($fn, "todo");
|
|
||||||
|
|
||||||
my $skip = 0;
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
if (ContainsPipe($e, $e->{LEVELS}[0])) {
|
|
||||||
$skip = 1;
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
next if $skip;
|
|
||||||
|
|
||||||
$self->ParseFunction($if->{NAME}, $fn);
|
|
||||||
}
|
|
||||||
$self->pidl_hdr("#endif /* __CLI_$uif\__ */");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$$$)
|
|
||||||
{
|
|
||||||
my($self,$ndr,$header,$c_header) = @_;
|
|
||||||
|
|
||||||
$self->pidl("/*");
|
|
||||||
$self->pidl(" * Unix SMB/CIFS implementation.");
|
|
||||||
$self->pidl(" * client auto-generated by pidl. DO NOT MODIFY!");
|
|
||||||
$self->pidl(" */");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("#include \"includes.h\"");
|
|
||||||
$self->pidl("#include \"$header\"");
|
|
||||||
$self->pidl_hdr("#include \"$c_header\"");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
foreach (@$ndr) {
|
|
||||||
$self->ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($self->{res}, $self->{res_hdr});
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,322 +0,0 @@
|
||||||
###################################################
|
|
||||||
# Samba3 server generator for IDL structures
|
|
||||||
# on top of Samba4 style NDR functions
|
|
||||||
# Copyright jelmer@samba.org 2005-2006
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba3::ServerNDR;
|
|
||||||
|
|
||||||
use Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(DeclLevel);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Parse::Pidl qw(warning error fatal);
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
|
|
||||||
use Parse::Pidl::Util qw(ParseExpr has_property is_constant);
|
|
||||||
use Parse::Pidl::NDR qw(GetNextLevel ContainsPipe);
|
|
||||||
use Parse::Pidl::Samba4 qw(ElementStars DeclLong);
|
|
||||||
use Parse::Pidl::Samba4::Header qw(GenerateFunctionOutEnv);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
my $res;
|
|
||||||
my $res_hdr;
|
|
||||||
my $tabs = "";
|
|
||||||
sub pidl_reset() { $res=""; $res_hdr="", $tabs=""; }
|
|
||||||
sub pidl_return() { my $s = $res; my $h = $res_hdr; pidl_reset(); return ($s, $h) }
|
|
||||||
sub indent() { $tabs.="\t"; }
|
|
||||||
sub deindent() { $tabs = substr($tabs, 1); }
|
|
||||||
sub pidl($) { my ($txt) = @_; $res .= $txt?$tabs.(shift)."\n":"\n"; }
|
|
||||||
sub pidl_hdr($) { $res_hdr .= (shift)."\n"; }
|
|
||||||
sub fn_declare($) { my ($n) = @_; pidl $n; pidl_hdr "$n;"; }
|
|
||||||
|
|
||||||
sub DeclLevel($$)
|
|
||||||
{
|
|
||||||
my ($e, $l) = @_;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
$res .= "const char";
|
|
||||||
} else {
|
|
||||||
$res .= mapTypeName($e->{TYPE});
|
|
||||||
}
|
|
||||||
|
|
||||||
my $stars = ElementStars($e, $l);
|
|
||||||
|
|
||||||
$res .= " ".$stars unless ($stars eq "");
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub AllocOutVar($$$$$$$)
|
|
||||||
{
|
|
||||||
my ($e, $mem_ctx, $name, $env, $check, $cleanup, $return) = @_;
|
|
||||||
|
|
||||||
my $l = $e->{LEVELS}[0];
|
|
||||||
|
|
||||||
# we skip pointer to arrays
|
|
||||||
if ($l->{TYPE} eq "POINTER") {
|
|
||||||
my $nl = GetNextLevel($e, $l);
|
|
||||||
$l = $nl if ($nl->{TYPE} eq "ARRAY");
|
|
||||||
} elsif
|
|
||||||
|
|
||||||
# we don't support multi-dimentional arrays yet
|
|
||||||
($l->{TYPE} eq "ARRAY") {
|
|
||||||
my $nl = GetNextLevel($e, $l);
|
|
||||||
if ($nl->{TYPE} eq "ARRAY") {
|
|
||||||
fatal($e->{ORIGINAL},"multi-dimentional [out] arrays are not supported!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
# neither pointer nor array, no need to alloc something.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($l->{TYPE} eq "ARRAY") {
|
|
||||||
unless(defined($l->{SIZE_IS})) {
|
|
||||||
error($e->{ORIGINAL}, "No size known for array `$e->{NAME}'");
|
|
||||||
pidl "#error No size known for array `$e->{NAME}'";
|
|
||||||
} else {
|
|
||||||
my $size = ParseExpr($l->{SIZE_IS}, $env, $e);
|
|
||||||
pidl "$name = talloc_zero_array($mem_ctx, " . DeclLevel($e, 1) . ", $size);";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pidl "$name = talloc_zero($mem_ctx, " . DeclLevel($e, 1) . ");";
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "if (" . $check->($name) . ") {";
|
|
||||||
indent;
|
|
||||||
pidl $cleanup->($name) if defined($cleanup);
|
|
||||||
pidl $return->($name) if defined($return);
|
|
||||||
deindent;
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CallWithStruct($$$$$$)
|
|
||||||
{
|
|
||||||
my ($pipes_struct, $mem_ctx, $fn, $check, $cleanup, $return) = @_;
|
|
||||||
my $env = GenerateFunctionOutEnv($fn);
|
|
||||||
my $hasout = 0;
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
if (grep(/out/, @{$_->{DIRECTION}})) { $hasout = 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "ZERO_STRUCT(r->out);" if ($hasout);
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
my @dir = @{$_->{DIRECTION}};
|
|
||||||
if (grep(/in/, @dir) and grep(/out/, @dir)) {
|
|
||||||
pidl "r->out.$_->{NAME} = r->in.$_->{NAME};";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
next if ContainsPipe($_, $_->{LEVELS}[0]);
|
|
||||||
my @dir = @{$_->{DIRECTION}};
|
|
||||||
if (grep(/in/, @dir) and grep(/out/, @dir)) {
|
|
||||||
# noop
|
|
||||||
} elsif (grep(/out/, @dir) and not
|
|
||||||
has_property($_, "represent_as")) {
|
|
||||||
AllocOutVar($_, $mem_ctx, "r->out.$_->{NAME}", $env,
|
|
||||||
$check, $cleanup, $return);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
my $proto = "_$fn->{NAME}(struct pipes_struct *p, struct $fn->{NAME} *r)";
|
|
||||||
my $ret = "_$fn->{NAME}($pipes_struct, r)";
|
|
||||||
|
|
||||||
if ($fn->{RETURN_TYPE}) {
|
|
||||||
$ret = "r->out.result = $ret";
|
|
||||||
$proto = mapTypeName($fn->{RETURN_TYPE})." $proto";
|
|
||||||
} else {
|
|
||||||
$proto = "void $proto";
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl_hdr "$proto;";
|
|
||||||
pidl "$ret;";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction($$)
|
|
||||||
{
|
|
||||||
my ($if,$fn) = @_;
|
|
||||||
|
|
||||||
my $op = "NDR_".uc($fn->{NAME});
|
|
||||||
|
|
||||||
pidl "static bool api_$fn->{NAME}(struct pipes_struct *p)";
|
|
||||||
pidl "{";
|
|
||||||
indent;
|
|
||||||
pidl "const struct ndr_interface_call *call;";
|
|
||||||
pidl "struct ndr_pull *pull;";
|
|
||||||
pidl "struct ndr_push *push;";
|
|
||||||
pidl "enum ndr_err_code ndr_err;";
|
|
||||||
pidl "struct $fn->{NAME} *r;";
|
|
||||||
pidl "";
|
|
||||||
pidl "call = &ndr_table_$if->{NAME}.calls[$op];";
|
|
||||||
pidl "";
|
|
||||||
pidl "r = talloc(talloc_tos(), struct $fn->{NAME});";
|
|
||||||
pidl "if (r == NULL) {";
|
|
||||||
pidl "\treturn false;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "pull = ndr_pull_init_blob(&p->in_data.data, r);";
|
|
||||||
pidl "if (pull == NULL) {";
|
|
||||||
pidl "\ttalloc_free(r);";
|
|
||||||
pidl "\treturn false;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "pull->flags |= LIBNDR_FLAG_REF_ALLOC;";
|
|
||||||
pidl "if (p->endian) {";
|
|
||||||
pidl "\tpull->flags |= LIBNDR_FLAG_BIGENDIAN;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "ndr_err = call->ndr_pull(pull, NDR_IN, r);";
|
|
||||||
pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {";
|
|
||||||
pidl "\ttalloc_free(r);";
|
|
||||||
pidl "\treturn false;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "if (DEBUGLEVEL >= 10) {";
|
|
||||||
pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_IN, r);";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
|
|
||||||
CallWithStruct("p", "r", $fn,
|
|
||||||
sub ($) {
|
|
||||||
my ($name) = @_;
|
|
||||||
return "${name} == NULL";
|
|
||||||
},
|
|
||||||
sub ($) {
|
|
||||||
my ($name) = @_;
|
|
||||||
return "talloc_free(r);";
|
|
||||||
},
|
|
||||||
sub ($) {
|
|
||||||
my ($name) = @_;
|
|
||||||
return "return false;";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
pidl "";
|
|
||||||
pidl "if (p->fault_state) {";
|
|
||||||
pidl "\ttalloc_free(r);";
|
|
||||||
pidl "\t/* Return true here, srv_pipe_hnd.c will take care */";
|
|
||||||
pidl "\treturn true;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "if (DEBUGLEVEL >= 10) {";
|
|
||||||
pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r);";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "push = ndr_push_init_ctx(r);";
|
|
||||||
pidl "if (push == NULL) {";
|
|
||||||
pidl "\ttalloc_free(r);";
|
|
||||||
pidl "\treturn false;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "/*";
|
|
||||||
pidl " * carry over the pointer count to the reply in case we are";
|
|
||||||
pidl " * using full pointer. See NDR specification for full pointers";
|
|
||||||
pidl " */";
|
|
||||||
pidl "push->ptr_count = pull->ptr_count;";
|
|
||||||
pidl "";
|
|
||||||
pidl "ndr_err = call->ndr_push(push, NDR_OUT, r);";
|
|
||||||
pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {";
|
|
||||||
pidl "\ttalloc_free(r);";
|
|
||||||
pidl "\treturn false;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "p->out_data.rdata = ndr_push_blob(push);";
|
|
||||||
pidl "talloc_steal(p->mem_ctx, p->out_data.rdata.data);";
|
|
||||||
pidl "";
|
|
||||||
pidl "talloc_free(r);";
|
|
||||||
pidl "";
|
|
||||||
pidl "return true;";
|
|
||||||
deindent;
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseInterface($)
|
|
||||||
{
|
|
||||||
my $if = shift;
|
|
||||||
|
|
||||||
my $uif = uc($if->{NAME});
|
|
||||||
|
|
||||||
pidl_hdr "#ifndef __SRV_$uif\__";
|
|
||||||
pidl_hdr "#define __SRV_$uif\__";
|
|
||||||
|
|
||||||
foreach (@{$if->{FUNCTIONS}}) {
|
|
||||||
next if ($_->{PROPERTIES}{noopnum});
|
|
||||||
ParseFunction($if, $_);
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "";
|
|
||||||
pidl "/* Tables */";
|
|
||||||
pidl "static struct api_struct api_$if->{NAME}_cmds[] = ";
|
|
||||||
pidl "{";
|
|
||||||
indent;
|
|
||||||
|
|
||||||
foreach (@{$if->{FUNCTIONS}}) {
|
|
||||||
next if ($_->{PROPERTIES}{noopnum});
|
|
||||||
pidl "{\"" . uc($_->{NAME}) . "\", NDR_" . uc($_->{NAME}) . ", api_$_->{NAME}},";
|
|
||||||
}
|
|
||||||
|
|
||||||
deindent;
|
|
||||||
pidl "};";
|
|
||||||
|
|
||||||
pidl "";
|
|
||||||
|
|
||||||
pidl_hdr "void $if->{NAME}_get_pipe_fns(struct api_struct **fns, int *n_fns);";
|
|
||||||
pidl "void $if->{NAME}_get_pipe_fns(struct api_struct **fns, int *n_fns)";
|
|
||||||
pidl "{";
|
|
||||||
indent;
|
|
||||||
pidl "*fns = api_$if->{NAME}_cmds;";
|
|
||||||
pidl "*n_fns = sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct);";
|
|
||||||
deindent;
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
|
|
||||||
if (not has_property($if, "no_srv_register")) {
|
|
||||||
pidl_hdr "struct rpc_srv_callbacks;";
|
|
||||||
pidl_hdr "NTSTATUS rpc_$if->{NAME}_init(const struct rpc_srv_callbacks *rpc_srv_cb);";
|
|
||||||
pidl "NTSTATUS rpc_$if->{NAME}_init(const struct rpc_srv_callbacks *rpc_srv_cb)";
|
|
||||||
pidl "{";
|
|
||||||
pidl "\treturn rpc_srv_register(SMB_RPC_INTERFACE_VERSION, \"$if->{NAME}\", \"$if->{NAME}\", \&ndr_table_$if->{NAME}, api_$if->{NAME}_cmds, sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct), rpc_srv_cb);";
|
|
||||||
pidl "}";
|
|
||||||
|
|
||||||
pidl "";
|
|
||||||
|
|
||||||
pidl_hdr "NTSTATUS rpc_$if->{NAME}_shutdown(void);";
|
|
||||||
pidl "NTSTATUS rpc_$if->{NAME}_shutdown(void)";
|
|
||||||
pidl "{";
|
|
||||||
pidl "\treturn rpc_srv_unregister(\&ndr_table_$if->{NAME});";
|
|
||||||
pidl "}";
|
|
||||||
}
|
|
||||||
pidl_hdr "#endif /* __SRV_$uif\__ */";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$$)
|
|
||||||
{
|
|
||||||
my($ndr,$header,$ndr_header) = @_;
|
|
||||||
|
|
||||||
pidl_reset();
|
|
||||||
|
|
||||||
pidl "/*";
|
|
||||||
pidl " * Unix SMB/CIFS implementation.";
|
|
||||||
pidl " * server auto-generated by pidl. DO NOT MODIFY!";
|
|
||||||
pidl " */";
|
|
||||||
pidl "";
|
|
||||||
pidl "#include \"includes.h\"";
|
|
||||||
pidl "#include \"ntdomain.h\"";
|
|
||||||
pidl "#include \"$header\"";
|
|
||||||
pidl_hdr "#include \"$ndr_header\"";
|
|
||||||
pidl "";
|
|
||||||
|
|
||||||
foreach (@$ndr) {
|
|
||||||
ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");
|
|
||||||
}
|
|
||||||
|
|
||||||
return pidl_return();
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,98 +0,0 @@
|
||||||
###################################################
|
|
||||||
# server template function generator
|
|
||||||
# Copyright tridge@samba.org 2003
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba3::Template;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use Parse::Pidl::Util qw(genpad);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for a interface
|
|
||||||
sub Template($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
|
|
||||||
$res .=
|
|
||||||
"/*
|
|
||||||
Unix SMB/CIFS implementation.
|
|
||||||
|
|
||||||
endpoint server for the $name pipe
|
|
||||||
|
|
||||||
Copyright (C) YOUR NAME HERE YEAR
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include \"includes.h\"
|
|
||||||
#include \"ntdomain.h\"
|
|
||||||
#include \"../librpc/gen_ndr/srv_$name.h\"
|
|
||||||
|
|
||||||
";
|
|
||||||
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
if ($d->{TYPE} eq "FUNCTION") {
|
|
||||||
my $fname = $d->{NAME};
|
|
||||||
my $pad = genpad("$d->{RETURN_TYPE} _$fname");
|
|
||||||
$res .=
|
|
||||||
"
|
|
||||||
/****************************************************************
|
|
||||||
_$fname
|
|
||||||
****************************************************************/
|
|
||||||
|
|
||||||
$d->{RETURN_TYPE} _$fname(struct pipes_struct *p,
|
|
||||||
$pad"."struct $fname *r)
|
|
||||||
{
|
|
||||||
";
|
|
||||||
|
|
||||||
$res .= "\tp->fault_state = DCERPC_FAULT_OP_RNG_ERROR;\n";
|
|
||||||
if ($d->{RETURN_TYPE} eq "NTSTATUS") {
|
|
||||||
$res .= "\treturn NT_STATUS_NOT_IMPLEMENTED;\n";
|
|
||||||
} elsif ($d->{RETURN_TYPE} eq "WERROR") {
|
|
||||||
$res .= "\treturn WERR_NOT_SUPPORTED;\n";
|
|
||||||
} elsif ($d->{RETURN_TYPE} eq "HRESULT") {
|
|
||||||
$res .= "\treturn HRES_ERROR_NOT_SUPPORTED;\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= "}
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a parsed IDL structure back into an IDL file
|
|
||||||
sub Parse($)
|
|
||||||
{
|
|
||||||
my($idl) = shift;
|
|
||||||
$res = "";
|
|
||||||
foreach my $x (@{$idl}) {
|
|
||||||
($x->{TYPE} eq "INTERFACE") &&
|
|
||||||
Template($x);
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,133 +0,0 @@
|
||||||
###################################################
|
|
||||||
# Common Samba4 functions
|
|
||||||
# Copyright jelmer@samba.org 2006
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT = qw(is_intree choose_header NumStars ElementStars ArrayBrackets DeclLong ArrayDynamicallyAllocated);
|
|
||||||
|
|
||||||
use Parse::Pidl::Util qw(has_property is_constant);
|
|
||||||
use Parse::Pidl::NDR qw(GetNextLevel);
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
|
|
||||||
use Parse::Pidl qw(fatal error);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
|
|
||||||
# return true if we are using pidl within the samba source tree. This changes
|
|
||||||
# the names of include files, as some include files (such as ntstatus.h) have
|
|
||||||
# different paths when installed to the patch in the source tree
|
|
||||||
sub is_intree()
|
|
||||||
{
|
|
||||||
my $srcdir = $ENV{srcdir};
|
|
||||||
$srcdir = $srcdir ? "$srcdir/" : "";
|
|
||||||
return 1 if (-f "${srcdir}kdc/kdc.c");
|
|
||||||
return 1 if (-d "${srcdir}source4");
|
|
||||||
return 1 if (-f "${srcdir}include/smb.h");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Return an #include line depending on whether this build is an in-tree
|
|
||||||
# build or not.
|
|
||||||
sub choose_header($$)
|
|
||||||
{
|
|
||||||
my ($in,$out) = @_;
|
|
||||||
return "#include \"$in\"" if (is_intree());
|
|
||||||
return "#include <$out>";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ArrayDynamicallyAllocated($$)
|
|
||||||
{
|
|
||||||
my ($e, $l) = @_;
|
|
||||||
die("Not an array") unless ($l->{TYPE} eq "ARRAY");
|
|
||||||
return 0 if ($l->{IS_FIXED} and not has_property($e, "charset"));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub NumStars($;$)
|
|
||||||
{
|
|
||||||
my ($e, $d) = @_;
|
|
||||||
$d = 0 unless defined($d);
|
|
||||||
my $n = 0;
|
|
||||||
|
|
||||||
foreach my $l (@{$e->{LEVELS}}) {
|
|
||||||
next unless ($l->{TYPE} eq "POINTER");
|
|
||||||
|
|
||||||
my $nl = GetNextLevel($e, $l);
|
|
||||||
next if (defined($nl) and $nl->{TYPE} eq "ARRAY");
|
|
||||||
|
|
||||||
$n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($n >= 1) {
|
|
||||||
$n-- if (scalar_is_reference($e->{TYPE}));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $l (@{$e->{LEVELS}}) {
|
|
||||||
next unless ($l->{TYPE} eq "ARRAY");
|
|
||||||
next unless (ArrayDynamicallyAllocated($e, $l));
|
|
||||||
$n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
error($e->{ORIGINAL}, "Too few pointers $n < $d") if ($n < $d);
|
|
||||||
|
|
||||||
$n -= $d;
|
|
||||||
|
|
||||||
return $n;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ElementStars($;$)
|
|
||||||
{
|
|
||||||
my ($e, $d) = @_;
|
|
||||||
my $res = "";
|
|
||||||
my $n = 0;
|
|
||||||
|
|
||||||
$n = NumStars($e, $d);
|
|
||||||
$res .= "*" foreach (1..$n);
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ArrayBrackets($)
|
|
||||||
{
|
|
||||||
my ($e) = @_;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
foreach my $l (@{$e->{LEVELS}}) {
|
|
||||||
next unless ($l->{TYPE} eq "ARRAY");
|
|
||||||
next if ArrayDynamicallyAllocated($e, $l);
|
|
||||||
$res .= "[$l->{SIZE_IS}]";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub DeclLong($;$)
|
|
||||||
{
|
|
||||||
my ($e, $p) = @_;
|
|
||||||
my $res = "";
|
|
||||||
$p = "" unless defined($p);
|
|
||||||
|
|
||||||
if (has_property($e, "represent_as")) {
|
|
||||||
$res .= mapTypeName($e->{PROPERTIES}->{represent_as})." ";
|
|
||||||
} else {
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
$res .= "const char ";
|
|
||||||
} else {
|
|
||||||
$res .= mapTypeName($e->{TYPE})." ";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= ElementStars($e);
|
|
||||||
}
|
|
||||||
$res .= $p.$e->{NAME};
|
|
||||||
$res .= ArrayBrackets($e);
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,160 +0,0 @@
|
||||||
# COM Header generation
|
|
||||||
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::COM::Header;
|
|
||||||
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
|
||||||
use Parse::Pidl::Util qw(has_property is_constant);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
sub GetArgumentProtoList($)
|
|
||||||
{
|
|
||||||
my $f = shift;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
foreach my $a (@{$f->{ELEMENTS}}) {
|
|
||||||
|
|
||||||
$res .= ", " . mapTypeName($a->{TYPE}) . " ";
|
|
||||||
|
|
||||||
my $l = $a->{POINTERS};
|
|
||||||
$l-- if (Parse::Pidl::Typelist::scalar_is_reference($a->{TYPE}));
|
|
||||||
foreach my $i (1..$l) {
|
|
||||||
$res .= "*";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined $a->{ARRAY_LEN}[0] && !is_constant($a->{ARRAY_LEN}[0]) &&
|
|
||||||
!$a->{POINTERS}) {
|
|
||||||
$res .= "*";
|
|
||||||
}
|
|
||||||
$res .= $a->{NAME};
|
|
||||||
if (defined $a->{ARRAY_LEN}[0] && is_constant($a->{ARRAY_LEN}[0])) {
|
|
||||||
$res .= "[$a->{ARRAY_LEN}[0]]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub GetArgumentList($)
|
|
||||||
{
|
|
||||||
my $f = shift;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
foreach (@{$f->{ELEMENTS}}) { $res .= ", $_->{NAME}"; }
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# generate vtable structure for COM interface
|
|
||||||
sub HeaderVTable($)
|
|
||||||
{
|
|
||||||
my $interface = shift;
|
|
||||||
my $res;
|
|
||||||
$res .= "#define " . uc($interface->{NAME}) . "_METHODS \\\n";
|
|
||||||
if (defined($interface->{BASE})) {
|
|
||||||
$res .= "\t" . uc($interface->{BASE} . "_METHODS") . "\\\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $data = $interface->{DATA};
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
$res .= "\t" . mapTypeName($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n" if ($d->{TYPE} eq "FUNCTION");
|
|
||||||
}
|
|
||||||
$res .= "\n";
|
|
||||||
$res .= "struct $interface->{NAME}_vtable {\n";
|
|
||||||
$res .= "\tstruct GUID iid;\n";
|
|
||||||
$res .= "\t" . uc($interface->{NAME}) . "_METHODS\n";
|
|
||||||
$res .= "};\n\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseInterface($)
|
|
||||||
{
|
|
||||||
my $if = shift;
|
|
||||||
my $res;
|
|
||||||
|
|
||||||
$res .= "\n#ifndef _$if->{NAME}_\n";
|
|
||||||
$res .= "#define _$if->{NAME}_\n";
|
|
||||||
|
|
||||||
$res .="\n\n/* $if->{NAME} */\n";
|
|
||||||
|
|
||||||
$res .="#define COM_" . uc($if->{NAME}) . "_UUID $if->{PROPERTIES}->{uuid}\n\n";
|
|
||||||
|
|
||||||
$res .="struct $if->{NAME}_vtable;\n\n";
|
|
||||||
|
|
||||||
$res .="struct $if->{NAME} {
|
|
||||||
struct OBJREF obj;
|
|
||||||
struct com_context *ctx;
|
|
||||||
struct $if->{NAME}_vtable *vtable;
|
|
||||||
void *object_data;
|
|
||||||
};\n\n";
|
|
||||||
|
|
||||||
$res.=HeaderVTable($if);
|
|
||||||
|
|
||||||
foreach my $d (@{$if->{DATA}}) {
|
|
||||||
next if ($d->{TYPE} ne "FUNCTION");
|
|
||||||
|
|
||||||
$res .= "#define $if->{NAME}_$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . ") ";
|
|
||||||
|
|
||||||
$res .= "((interface)->vtable->$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . "))";
|
|
||||||
|
|
||||||
$res .="\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= "#endif\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseCoClass($)
|
|
||||||
{
|
|
||||||
my ($c) = @_;
|
|
||||||
my $res = "";
|
|
||||||
$res .= "#define CLSID_" . uc($c->{NAME}) . " $c->{PROPERTIES}->{uuid}\n";
|
|
||||||
if (has_property($c, "progid")) {
|
|
||||||
$res .= "#define PROGID_" . uc($c->{NAME}) . " $c->{PROPERTIES}->{progid}\n";
|
|
||||||
}
|
|
||||||
$res .= "\n";
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$)
|
|
||||||
{
|
|
||||||
my ($idl,$ndr_header) = @_;
|
|
||||||
my $res = "";
|
|
||||||
my $has_obj = 0;
|
|
||||||
|
|
||||||
$res .= "#include \"librpc/gen_ndr/orpc.h\"\n" .
|
|
||||||
"#include \"$ndr_header\"\n\n";
|
|
||||||
|
|
||||||
foreach (@{$idl})
|
|
||||||
{
|
|
||||||
if ($_->{TYPE} eq "INTERFACE" && has_property($_, "object")) {
|
|
||||||
$res .="struct $_->{NAME};\n";
|
|
||||||
$has_obj = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (@{$idl})
|
|
||||||
{
|
|
||||||
if ($_->{TYPE} eq "INTERFACE" && has_property($_, "object")) {
|
|
||||||
$res.=ParseInterface($_);
|
|
||||||
$has_obj = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($_->{TYPE} eq "COCLASS") {
|
|
||||||
$res.=ParseCoClass($_);
|
|
||||||
$has_obj = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res if ($has_obj);
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,225 +0,0 @@
|
||||||
###################################################
|
|
||||||
# DCOM parser for Samba
|
|
||||||
# Basically the glue between COM and DCE/RPC with NDR
|
|
||||||
# Copyright jelmer@samba.org 2003-2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::COM::Proxy;
|
|
||||||
|
|
||||||
use Parse::Pidl::Samba4::COM::Header;
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
sub ParseVTable($$)
|
|
||||||
{
|
|
||||||
my ($interface, $name) = @_;
|
|
||||||
|
|
||||||
# Generate the vtable
|
|
||||||
$res .="\tstruct $interface->{NAME}_vtable $name = {";
|
|
||||||
|
|
||||||
if (defined($interface->{BASE})) {
|
|
||||||
$res .= "\n\t\t{},";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $data = $interface->{DATA};
|
|
||||||
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
if ($d->{TYPE} eq "FUNCTION") {
|
|
||||||
$res .= "\n\t\tdcom_proxy_$interface->{NAME}_$d->{NAME}";
|
|
||||||
$res .= ",";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= "\n\t};\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseRegFunc($)
|
|
||||||
{
|
|
||||||
my $interface = shift;
|
|
||||||
|
|
||||||
$res .= "static NTSTATUS dcom_proxy_$interface->{NAME}_init(void)
|
|
||||||
{
|
|
||||||
struct $interface->{NAME}_vtable *proxy_vtable = talloc(talloc_autofree_context(), struct $interface->{NAME}_vtable);
|
|
||||||
";
|
|
||||||
|
|
||||||
if (defined($interface->{BASE})) {
|
|
||||||
$res.= "
|
|
||||||
struct GUID base_iid;
|
|
||||||
const void *base_vtable;
|
|
||||||
|
|
||||||
base_iid = ndr_table_$interface->{BASE}.syntax_id.uuid;
|
|
||||||
|
|
||||||
base_vtable = dcom_proxy_vtable_by_iid(&base_iid);
|
|
||||||
if (base_vtable == NULL) {
|
|
||||||
DEBUG(0, (\"No proxy registered for base interface '$interface->{BASE}'\\n\"));
|
|
||||||
return NT_STATUS_FOOBAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&proxy_vtable, base_vtable, sizeof(struct $interface->{BASE}_vtable));
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
foreach my $x (@{$interface->{DATA}}) {
|
|
||||||
next unless ($x->{TYPE} eq "FUNCTION");
|
|
||||||
|
|
||||||
$res .= "\tproxy_vtable->$x->{NAME} = dcom_proxy_$interface->{NAME}_$x->{NAME};\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res.= "
|
|
||||||
proxy_vtable->iid = ndr_table_$interface->{NAME}.syntax_id.uuid;
|
|
||||||
|
|
||||||
return dcom_register_proxy((struct IUnknown_vtable *)proxy_vtable);
|
|
||||||
}\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a function
|
|
||||||
sub ParseFunction($$)
|
|
||||||
{
|
|
||||||
my ($interface, $fn) = @_;
|
|
||||||
my $name = $fn->{NAME};
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
my $tn = mapTypeName($fn->{RETURN_TYPE});
|
|
||||||
|
|
||||||
$res.="
|
|
||||||
static $tn dcom_proxy_$interface->{NAME}_$name(struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . Parse::Pidl::Samba4::COM::Header::GetArgumentProtoList($fn) . ")
|
|
||||||
{
|
|
||||||
struct dcerpc_pipe *p;
|
|
||||||
NTSTATUS status = dcom_get_pipe(d, &p);
|
|
||||||
struct $name r;
|
|
||||||
struct rpc_request *req;
|
|
||||||
|
|
||||||
if (NT_STATUS_IS_ERR(status)) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZERO_STRUCT(r.in.ORPCthis);
|
|
||||||
r.in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION;
|
|
||||||
r.in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION;
|
|
||||||
";
|
|
||||||
|
|
||||||
# Put arguments into r
|
|
||||||
foreach my $a (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless (has_property($a, "in"));
|
|
||||||
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
|
||||||
$res .="\tNDR_CHECK(dcom_OBJREF_from_IUnknown(mem_ctx, &r.in.$a->{NAME}.obj, $a->{NAME}));\n";
|
|
||||||
} else {
|
|
||||||
$res .= "\tr.in.$a->{NAME} = $a->{NAME};\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .="
|
|
||||||
if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
|
|
||||||
NDR_PRINT_IN_DEBUG($name, &r);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = dcerpc_ndr_request(p, &d->ipid, &ndr_table_$interface->{NAME}, NDR_$uname, mem_ctx, &r);
|
|
||||||
|
|
||||||
if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) {
|
|
||||||
NDR_PRINT_OUT_DEBUG($name, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
";
|
|
||||||
|
|
||||||
# Put r info back into arguments
|
|
||||||
foreach my $a (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless (has_property($a, "out"));
|
|
||||||
|
|
||||||
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
|
||||||
$res .="\tNDR_CHECK(dcom_IUnknown_from_OBJREF(d->ctx, &$a->{NAME}, r.out.$a->{NAME}.obj));\n";
|
|
||||||
} else {
|
|
||||||
$res .= "\t*$a->{NAME} = r.out.$a->{NAME};\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($fn->{RETURN_TYPE} eq "NTSTATUS") {
|
|
||||||
$res .= "\tif (NT_STATUS_IS_OK(status)) status = r.out.result;\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .=
|
|
||||||
"
|
|
||||||
return r.out.result;
|
|
||||||
}\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse the interface definitions
|
|
||||||
sub ParseInterface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
$res = "/* DCOM proxy for $interface->{NAME} generated by pidl */\n\n";
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
($d->{TYPE} eq "FUNCTION") &&
|
|
||||||
ParseFunction($interface, $d);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParseRegFunc($interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub RegistrationFunction($$)
|
|
||||||
{
|
|
||||||
my $idl = shift;
|
|
||||||
my $basename = shift;
|
|
||||||
|
|
||||||
my $res = "\n\nNTSTATUS dcom_$basename\_init(void)\n";
|
|
||||||
$res .= "{\n";
|
|
||||||
$res .="\tNTSTATUS status = NT_STATUS_OK;\n";
|
|
||||||
foreach my $interface (@{$idl}) {
|
|
||||||
next if $interface->{TYPE} ne "INTERFACE";
|
|
||||||
next if not has_property($interface, "object");
|
|
||||||
|
|
||||||
my $data = $interface->{DATA};
|
|
||||||
my $count = 0;
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
if ($d->{TYPE} eq "FUNCTION") { $count++; }
|
|
||||||
}
|
|
||||||
|
|
||||||
next if ($count == 0);
|
|
||||||
|
|
||||||
$res .= "\tstatus = dcom_$interface->{NAME}_init();\n";
|
|
||||||
$res .= "\tif (NT_STATUS_IS_ERR(status)) {\n";
|
|
||||||
$res .= "\t\treturn status;\n";
|
|
||||||
$res .= "\t}\n\n";
|
|
||||||
}
|
|
||||||
$res .= "\treturn status;\n";
|
|
||||||
$res .= "}\n\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$)
|
|
||||||
{
|
|
||||||
my ($pidl,$comh_filename) = @_;
|
|
||||||
my $res = "";
|
|
||||||
my $has_obj = 0;
|
|
||||||
|
|
||||||
$res .= "#include \"includes.h\"\n" .
|
|
||||||
"#include \"lib/com/dcom/dcom.h\"\n" .
|
|
||||||
"#include \"$comh_filename\"\n" .
|
|
||||||
"#include \"librpc/rpc/dcerpc.h\"\n";
|
|
||||||
|
|
||||||
foreach (@{$pidl}) {
|
|
||||||
next if ($_->{TYPE} ne "INTERFACE");
|
|
||||||
next if has_property($_, "local");
|
|
||||||
next unless has_property($_, "object");
|
|
||||||
|
|
||||||
$res .= ParseInterface($_);
|
|
||||||
|
|
||||||
$has_obj = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res if ($has_obj);
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,327 +0,0 @@
|
||||||
###################################################
|
|
||||||
# DCOM stub boilerplate generator
|
|
||||||
# Copyright jelmer@samba.org 2004-2005
|
|
||||||
# Copyright tridge@samba.org 2003
|
|
||||||
# Copyright metze@samba.org 2004
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::COM::Stub;
|
|
||||||
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
sub pidl($)
|
|
||||||
{
|
|
||||||
$res .= shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################
|
|
||||||
# generate the switch statement for function dispatch
|
|
||||||
sub gen_dispatch_switch($)
|
|
||||||
{
|
|
||||||
my $data = shift;
|
|
||||||
|
|
||||||
my $count = 0;
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
next if ($d->{TYPE} ne "FUNCTION");
|
|
||||||
|
|
||||||
pidl "\tcase $count: {\n";
|
|
||||||
if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
|
|
||||||
pidl "\t\tNTSTATUS result;\n";
|
|
||||||
}
|
|
||||||
pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
|
|
||||||
pidl "\t\tif (DEBUGLEVEL > 10) {\n";
|
|
||||||
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_IN, r2);\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
|
|
||||||
pidl "\t\tresult = vtable->$d->{NAME}(iface, mem_ctx, r2);\n";
|
|
||||||
} else {
|
|
||||||
pidl "\t\tvtable->$d->{NAME}(iface, mem_ctx, r2);\n";
|
|
||||||
}
|
|
||||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} will reply async\\n\"));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tbreak;\n\t}\n";
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################
|
|
||||||
# generate the switch statement for function reply
|
|
||||||
sub gen_reply_switch($)
|
|
||||||
{
|
|
||||||
my $data = shift;
|
|
||||||
|
|
||||||
my $count = 0;
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
next if ($d->{TYPE} ne "FUNCTION");
|
|
||||||
|
|
||||||
pidl "\tcase $count: {\n";
|
|
||||||
pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
|
|
||||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} replied async\\n\"));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n";
|
|
||||||
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tif (dce_call->fault_code != 0) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $d->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tbreak;\n\t}\n";
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for a interface
|
|
||||||
sub Boilerplate_Iface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
my $uname = uc $name;
|
|
||||||
my $uuid = Parse::Pidl::Util::make_str($interface->{PROPERTIES}->{uuid});
|
|
||||||
my $if_version = $interface->{PROPERTIES}->{version};
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
|
|
||||||
{
|
|
||||||
#ifdef DCESRV_INTERFACE_$uname\_BIND
|
|
||||||
return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface);
|
|
||||||
#else
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
|
|
||||||
{
|
|
||||||
#ifdef DCESRV_INTERFACE_$uname\_UNBIND
|
|
||||||
DCESRV_INTERFACE_$uname\_UNBIND(context, iface);
|
|
||||||
#else
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
|
|
||||||
{
|
|
||||||
NTSTATUS status;
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
dce_call->fault_code = 0;
|
|
||||||
|
|
||||||
if (opnum >= dcerpc_table_$name.num_calls) {
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
*r = talloc_size(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size);
|
|
||||||
NT_STATUS_HAVE_NO_MEMORY(*r);
|
|
||||||
|
|
||||||
/* unravel the NDR for the packet */
|
|
||||||
status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
|
||||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
|
||||||
{
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
struct GUID ipid = dce_call->pkt.u.request.object.object;
|
|
||||||
struct dcom_interface_p *iface = dcom_get_local_iface_p(&ipid);
|
|
||||||
const struct dcom_$name\_vtable *vtable = iface->vtable;
|
|
||||||
|
|
||||||
switch (opnum) {
|
|
||||||
";
|
|
||||||
gen_dispatch_switch($data);
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
default:
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dce_call->fault_code != 0) {
|
|
||||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
|
||||||
{
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
switch (opnum) {
|
|
||||||
";
|
|
||||||
gen_reply_switch($data);
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
default:
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dce_call->fault_code != 0) {
|
|
||||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
|
|
||||||
{
|
|
||||||
NTSTATUS status;
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
status = dcerpc_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct dcesrv_interface $name\_interface = {
|
|
||||||
.name = \"$name\",
|
|
||||||
.uuid = $uuid,
|
|
||||||
.if_version = $if_version,
|
|
||||||
.bind = $name\__op_bind,
|
|
||||||
.unbind = $name\__op_unbind,
|
|
||||||
.ndr_pull = $name\__op_ndr_pull,
|
|
||||||
.dispatch = $name\__op_dispatch,
|
|
||||||
.reply = $name\__op_reply,
|
|
||||||
.ndr_push = $name\__op_ndr_push
|
|
||||||
};
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for an endpoint server
|
|
||||||
sub Boilerplate_Ep_Server($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0;i<dcerpc_table_$name.endpoints->count;i++) {
|
|
||||||
NTSTATUS ret;
|
|
||||||
const char *name = dcerpc_table_$name.endpoints->names[i];
|
|
||||||
|
|
||||||
ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL);
|
|
||||||
if (!NT_STATUS_IS_OK(ret)) {
|
|
||||||
DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32_t if_version)
|
|
||||||
{
|
|
||||||
if (dcerpc_table_$name.if_version == if_version &&
|
|
||||||
strcmp(dcerpc_table_$name.uuid, uuid)==0) {
|
|
||||||
memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
|
|
||||||
{
|
|
||||||
if (strcmp(dcerpc_table_$name.name, name)==0) {
|
|
||||||
memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS dcerpc_server_$name\_init(void)
|
|
||||||
{
|
|
||||||
NTSTATUS ret;
|
|
||||||
struct dcesrv_endpoint_server ep_server;
|
|
||||||
|
|
||||||
/* fill in our name */
|
|
||||||
ep_server.name = \"$name\";
|
|
||||||
|
|
||||||
/* fill in all the operations */
|
|
||||||
ep_server.init_server = $name\__op_init_server;
|
|
||||||
|
|
||||||
ep_server.interface_by_uuid = $name\__op_interface_by_uuid;
|
|
||||||
ep_server.interface_by_name = $name\__op_interface_by_name;
|
|
||||||
|
|
||||||
/* register ourselves with the DCERPC subsystem. */
|
|
||||||
ret = dcerpc_register_ep_server(&ep_server);
|
|
||||||
|
|
||||||
if (!NT_STATUS_IS_OK(ret)) {
|
|
||||||
DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dcom interface stub from a parsed IDL structure
|
|
||||||
sub ParseInterface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
|
|
||||||
return "" if has_property($interface, "local");
|
|
||||||
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
my $count = 0;
|
|
||||||
|
|
||||||
$res = "";
|
|
||||||
|
|
||||||
if (!defined $interface->{PROPERTIES}->{uuid}) {
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defined $interface->{PROPERTIES}->{version}) {
|
|
||||||
$interface->{PROPERTIES}->{version} = "0.0";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
if ($d->{TYPE} eq "FUNCTION") { $count++; }
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($count == 0) {
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
$res = "/* dcom interface stub generated by pidl */\n\n";
|
|
||||||
Boilerplate_Iface($interface);
|
|
||||||
Boilerplate_Ep_Server($interface);
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,537 +0,0 @@
|
||||||
###################################################
|
|
||||||
# create C header files for an IDL structure
|
|
||||||
# Copyright tridge@samba.org 2000
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::Header;
|
|
||||||
require Exporter;
|
|
||||||
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Parse::Pidl qw(fatal);
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
|
|
||||||
use Parse::Pidl::Util qw(has_property is_constant unmake_str ParseExpr);
|
|
||||||
use Parse::Pidl::Samba4 qw(is_intree ElementStars ArrayBrackets choose_header);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
my($tab_depth);
|
|
||||||
|
|
||||||
sub pidl($) { $res .= shift; }
|
|
||||||
|
|
||||||
sub tabs()
|
|
||||||
{
|
|
||||||
my $res = "";
|
|
||||||
$res .="\t" foreach (1..$tab_depth);
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a properties list
|
|
||||||
sub HeaderProperties($$)
|
|
||||||
{
|
|
||||||
my($props,$ignores) = @_;
|
|
||||||
my $ret = "";
|
|
||||||
|
|
||||||
foreach my $d (sort(keys %{$props})) {
|
|
||||||
next if (grep(/^$d$/, @$ignores));
|
|
||||||
if($props->{$d} ne "1") {
|
|
||||||
$ret.= "$d($props->{$d}),";
|
|
||||||
} else {
|
|
||||||
$ret.="$d,";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ret) {
|
|
||||||
pidl "/* [" . substr($ret, 0, -1) . "] */";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a structure element
|
|
||||||
sub HeaderElement($)
|
|
||||||
{
|
|
||||||
my($element) = shift;
|
|
||||||
|
|
||||||
pidl tabs();
|
|
||||||
if (has_property($element, "represent_as")) {
|
|
||||||
pidl mapTypeName($element->{PROPERTIES}->{represent_as})." ";
|
|
||||||
} else {
|
|
||||||
if (ref($element->{TYPE}) eq "HASH") {
|
|
||||||
HeaderType($element, $element->{TYPE}, $element->{TYPE}->{NAME});
|
|
||||||
} else {
|
|
||||||
HeaderType($element, $element->{TYPE}, "");
|
|
||||||
}
|
|
||||||
pidl " ".ElementStars($element);
|
|
||||||
}
|
|
||||||
pidl $element->{NAME};
|
|
||||||
pidl ArrayBrackets($element);
|
|
||||||
|
|
||||||
pidl ";";
|
|
||||||
if (defined $element->{PROPERTIES}) {
|
|
||||||
HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
|
|
||||||
}
|
|
||||||
pidl "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a struct
|
|
||||||
sub HeaderStruct($$;$)
|
|
||||||
{
|
|
||||||
my($struct,$name,$tail) = @_;
|
|
||||||
pidl "struct $name";
|
|
||||||
pidl $tail if defined($tail) and not defined($struct->{ELEMENTS});
|
|
||||||
return if (not defined($struct->{ELEMENTS}));
|
|
||||||
pidl " {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
my $el_count=0;
|
|
||||||
foreach (@{$struct->{ELEMENTS}}) {
|
|
||||||
HeaderElement($_);
|
|
||||||
$el_count++;
|
|
||||||
}
|
|
||||||
if ($el_count == 0) {
|
|
||||||
# some compilers can't handle empty structures
|
|
||||||
pidl tabs()."char _empty_;\n";
|
|
||||||
}
|
|
||||||
$tab_depth--;
|
|
||||||
pidl tabs()."}";
|
|
||||||
if (defined $struct->{PROPERTIES}) {
|
|
||||||
HeaderProperties($struct->{PROPERTIES}, []);
|
|
||||||
}
|
|
||||||
pidl $tail if defined($tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a enum
|
|
||||||
sub HeaderEnum($$;$)
|
|
||||||
{
|
|
||||||
my($enum,$name,$tail) = @_;
|
|
||||||
my $first = 1;
|
|
||||||
|
|
||||||
pidl "enum $name";
|
|
||||||
if (defined($enum->{ELEMENTS})) {
|
|
||||||
pidl "\n#ifndef USE_UINT_ENUMS\n";
|
|
||||||
pidl " {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
foreach my $e (@{$enum->{ELEMENTS}}) {
|
|
||||||
my @enum_els = ();
|
|
||||||
unless ($first) { pidl ",\n"; }
|
|
||||||
$first = 0;
|
|
||||||
pidl tabs();
|
|
||||||
@enum_els = split(/=/, $e);
|
|
||||||
if (@enum_els == 2) {
|
|
||||||
pidl $enum_els[0];
|
|
||||||
pidl "=(int)";
|
|
||||||
pidl "(";
|
|
||||||
pidl $enum_els[1];
|
|
||||||
pidl ")";
|
|
||||||
} else {
|
|
||||||
pidl $e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pidl "\n";
|
|
||||||
$tab_depth--;
|
|
||||||
pidl "}";
|
|
||||||
pidl "\n";
|
|
||||||
pidl "#else\n";
|
|
||||||
my $count = 0;
|
|
||||||
my $with_val = 0;
|
|
||||||
my $without_val = 0;
|
|
||||||
pidl " { __do_not_use_enum_$name=0x7FFFFFFF}\n";
|
|
||||||
foreach my $e (@{$enum->{ELEMENTS}}) {
|
|
||||||
my $t = "$e";
|
|
||||||
my $name;
|
|
||||||
my $value;
|
|
||||||
if ($t =~ /(.*)=(.*)/) {
|
|
||||||
$name = $1;
|
|
||||||
$value = $2;
|
|
||||||
$with_val = 1;
|
|
||||||
fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
|
|
||||||
unless ($without_val == 0);
|
|
||||||
} else {
|
|
||||||
$name = $t;
|
|
||||||
$value = $count++;
|
|
||||||
$without_val = 1;
|
|
||||||
fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
|
|
||||||
unless ($with_val == 0);
|
|
||||||
}
|
|
||||||
pidl "#define $name ( $value )\n";
|
|
||||||
}
|
|
||||||
pidl "#endif\n";
|
|
||||||
}
|
|
||||||
pidl $tail if defined($tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a bitmap
|
|
||||||
sub HeaderBitmap($$)
|
|
||||||
{
|
|
||||||
my($bitmap,$name) = @_;
|
|
||||||
|
|
||||||
return unless defined($bitmap->{ELEMENTS});
|
|
||||||
|
|
||||||
pidl "/* bitmap $name */\n";
|
|
||||||
pidl "#define $_\n" foreach (@{$bitmap->{ELEMENTS}});
|
|
||||||
pidl "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a union
|
|
||||||
sub HeaderUnion($$;$)
|
|
||||||
{
|
|
||||||
my($union,$name,$tail) = @_;
|
|
||||||
my %done = ();
|
|
||||||
|
|
||||||
pidl "union $name";
|
|
||||||
pidl $tail if defined($tail) and not defined($union->{ELEMENTS});
|
|
||||||
return if (not defined($union->{ELEMENTS}));
|
|
||||||
pidl " {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
my $needed = 0;
|
|
||||||
foreach my $e (@{$union->{ELEMENTS}}) {
|
|
||||||
if ($e->{TYPE} ne "EMPTY") {
|
|
||||||
if (! defined $done{$e->{NAME}}) {
|
|
||||||
HeaderElement($e);
|
|
||||||
}
|
|
||||||
$done{$e->{NAME}} = 1;
|
|
||||||
$needed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!$needed) {
|
|
||||||
# sigh - some compilers don't like empty structures
|
|
||||||
pidl tabs()."int _dummy_element;\n";
|
|
||||||
}
|
|
||||||
$tab_depth--;
|
|
||||||
pidl "}";
|
|
||||||
|
|
||||||
if (defined $union->{PROPERTIES}) {
|
|
||||||
HeaderProperties($union->{PROPERTIES}, []);
|
|
||||||
}
|
|
||||||
pidl $tail if defined($tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a pipe
|
|
||||||
sub HeaderPipe($$;$)
|
|
||||||
{
|
|
||||||
my($pipe,$name,$tail) = @_;
|
|
||||||
|
|
||||||
my $struct = $pipe->{DATA};
|
|
||||||
my $e = $struct->{ELEMENTS}[1];
|
|
||||||
|
|
||||||
pidl "struct $name;\n";
|
|
||||||
pidl "struct $struct->{NAME} {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
pidl tabs()."uint32_t count;\n";
|
|
||||||
pidl tabs().mapTypeName($e->{TYPE})." *array;\n";
|
|
||||||
$tab_depth--;
|
|
||||||
pidl "}";
|
|
||||||
|
|
||||||
if (defined $struct->{PROPERTIES}) {
|
|
||||||
HeaderProperties($struct->{PROPERTIES}, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl $tail if defined($tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a type
|
|
||||||
sub HeaderType($$$;$)
|
|
||||||
{
|
|
||||||
my($e,$data,$name,$tail) = @_;
|
|
||||||
if (ref($data) eq "HASH") {
|
|
||||||
($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name, $tail);
|
|
||||||
($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
|
|
||||||
($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail);
|
|
||||||
($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail);
|
|
||||||
($data->{TYPE} eq "PIPE") && HeaderPipe($data, $name, $tail);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
pidl "const char";
|
|
||||||
} else {
|
|
||||||
pidl mapTypeName($e->{TYPE});
|
|
||||||
}
|
|
||||||
pidl $tail if defined($tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a typedef
|
|
||||||
sub HeaderTypedef($;$)
|
|
||||||
{
|
|
||||||
my($typedef,$tail) = @_;
|
|
||||||
# Don't print empty "enum foo;", since some compilers don't like it.
|
|
||||||
return if ($typedef->{DATA}->{TYPE} eq "ENUM" and not defined($typedef->{DATA}->{ELEMENTS}));
|
|
||||||
HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME}, $tail) if defined ($typedef->{DATA});
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a const
|
|
||||||
sub HeaderConst($)
|
|
||||||
{
|
|
||||||
my($const) = shift;
|
|
||||||
if (!defined($const->{ARRAY_LEN}[0])) {
|
|
||||||
pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
|
|
||||||
} else {
|
|
||||||
pidl "#define $const->{NAME}\t $const->{VALUE}\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) = @_;
|
|
||||||
|
|
||||||
return unless defined($fn->{ELEMENTS});
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
HeaderElement($e) if (ElementDirection($e) eq $prop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# determine if we need an "in" or "out" section
|
|
||||||
sub HeaderFunctionInOut_needed($$)
|
|
||||||
{
|
|
||||||
my($fn,$prop) = @_;
|
|
||||||
|
|
||||||
return 1 if ($prop eq "out" && defined($fn->{RETURN_TYPE}));
|
|
||||||
|
|
||||||
return undef unless defined($fn->{ELEMENTS});
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
return 1 if (ElementDirection($e) eq $prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
my %headerstructs;
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a function
|
|
||||||
sub HeaderFunction($)
|
|
||||||
{
|
|
||||||
my($fn) = shift;
|
|
||||||
|
|
||||||
return if ($headerstructs{$fn->{NAME}});
|
|
||||||
|
|
||||||
$headerstructs{$fn->{NAME}} = 1;
|
|
||||||
|
|
||||||
pidl "\nstruct $fn->{NAME} {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
my $needed = 0;
|
|
||||||
|
|
||||||
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") or
|
|
||||||
HeaderFunctionInOut_needed($fn, "inout")) {
|
|
||||||
pidl tabs()."struct {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
HeaderFunctionInOut($fn, "out");
|
|
||||||
HeaderFunctionInOut($fn, "inout");
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
pidl tabs().mapTypeName($fn->{RETURN_TYPE}) . " result;\n";
|
|
||||||
}
|
|
||||||
$tab_depth--;
|
|
||||||
pidl tabs()."} out;\n\n";
|
|
||||||
$needed++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$needed) {
|
|
||||||
# sigh - some compilers don't like empty structures
|
|
||||||
pidl tabs()."int _dummy_element;\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$tab_depth--;
|
|
||||||
pidl "};\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub HeaderImport
|
|
||||||
{
|
|
||||||
my @imports = @_;
|
|
||||||
foreach my $import (@imports) {
|
|
||||||
$import = unmake_str($import);
|
|
||||||
$import =~ s/\.idl$//;
|
|
||||||
pidl choose_header("librpc/gen_ndr/$import\.h", "gen_ndr/$import.h") . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub HeaderInclude
|
|
||||||
{
|
|
||||||
my @includes = @_;
|
|
||||||
foreach (@includes) {
|
|
||||||
pidl "#include $_\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse the interface definitions
|
|
||||||
sub HeaderInterface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
|
|
||||||
pidl "#ifndef _HEADER_$interface->{NAME}\n";
|
|
||||||
pidl "#define _HEADER_$interface->{NAME}\n\n";
|
|
||||||
|
|
||||||
foreach my $c (@{$interface->{CONSTS}}) {
|
|
||||||
HeaderConst($c);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $t (@{$interface->{TYPES}}) {
|
|
||||||
HeaderTypedef($t, ";\n\n") if ($t->{TYPE} eq "TYPEDEF");
|
|
||||||
HeaderStruct($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "STRUCT");
|
|
||||||
HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION");
|
|
||||||
HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM");
|
|
||||||
HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
|
|
||||||
HeaderPipe($t, $t->{NAME}, "\n\n") if ($t->{TYPE} eq "PIPE");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
|
||||||
HeaderFunction($fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "#endif /* _HEADER_$interface->{NAME} */\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub HeaderQuote($)
|
|
||||||
{
|
|
||||||
my($quote) = shift;
|
|
||||||
|
|
||||||
pidl unmake_str($quote->{DATA}) . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a parsed IDL into a C header
|
|
||||||
sub Parse($)
|
|
||||||
{
|
|
||||||
my($ndr) = shift;
|
|
||||||
$tab_depth = 0;
|
|
||||||
|
|
||||||
$res = "";
|
|
||||||
%headerstructs = ();
|
|
||||||
pidl "/* header auto-generated by pidl */\n\n";
|
|
||||||
|
|
||||||
my $ifacename = "";
|
|
||||||
|
|
||||||
# work out a unique interface name
|
|
||||||
foreach (@{$ndr}) {
|
|
||||||
if ($_->{TYPE} eq "INTERFACE") {
|
|
||||||
$ifacename = $_->{NAME};
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "#ifndef _PIDL_HEADER_$ifacename\n";
|
|
||||||
pidl "#define _PIDL_HEADER_$ifacename\n\n";
|
|
||||||
|
|
||||||
if (!is_intree()) {
|
|
||||||
pidl "#include <util/data_blob.h>\n";
|
|
||||||
}
|
|
||||||
pidl "#include <stdint.h>\n";
|
|
||||||
pidl "\n";
|
|
||||||
# FIXME: Include this only if NTSTATUS was actually used
|
|
||||||
pidl choose_header("libcli/util/ntstatus.h", "core/ntstatus.h") . "\n";
|
|
||||||
pidl "\n";
|
|
||||||
|
|
||||||
foreach (@{$ndr}) {
|
|
||||||
($_->{TYPE} eq "CPP_QUOTE") && HeaderQuote($_);
|
|
||||||
($_->{TYPE} eq "INTERFACE") && HeaderInterface($_);
|
|
||||||
($_->{TYPE} eq "IMPORT") && HeaderImport(@{$_->{PATHS}});
|
|
||||||
($_->{TYPE} eq "INCLUDE") && HeaderInclude(@{$_->{PATHS}});
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "#endif /* _PIDL_HEADER_$ifacename */\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub GenerateStructEnv($$)
|
|
||||||
{
|
|
||||||
my ($x, $v) = @_;
|
|
||||||
my %env;
|
|
||||||
|
|
||||||
foreach my $e (@{$x->{ELEMENTS}}) {
|
|
||||||
$env{$e->{NAME}} = "$v->$e->{NAME}";
|
|
||||||
}
|
|
||||||
|
|
||||||
$env{"this"} = $v;
|
|
||||||
|
|
||||||
return \%env;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub EnvSubstituteValue($$)
|
|
||||||
{
|
|
||||||
my ($env,$s) = @_;
|
|
||||||
|
|
||||||
# Substitute the value() values in the env
|
|
||||||
foreach my $e (@{$s->{ELEMENTS}}) {
|
|
||||||
next unless (defined(my $v = has_property($e, "value")));
|
|
||||||
|
|
||||||
$env->{$e->{NAME}} = ParseExpr($v, $env, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $env;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub GenerateFunctionInEnv($;$)
|
|
||||||
{
|
|
||||||
my ($fn, $base) = @_;
|
|
||||||
my %env;
|
|
||||||
|
|
||||||
$base = "r->" unless defined($base);
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
if (grep (/in/, @{$e->{DIRECTION}})) {
|
|
||||||
$env{$e->{NAME}} = $base."in.$e->{NAME}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return \%env;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub GenerateFunctionOutEnv($;$)
|
|
||||||
{
|
|
||||||
my ($fn, $base) = @_;
|
|
||||||
my %env;
|
|
||||||
|
|
||||||
$base = "r->" unless defined($base);
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
if (grep (/out/, @{$e->{DIRECTION}})) {
|
|
||||||
$env{$e->{NAME}} = $base."out.$e->{NAME}";
|
|
||||||
} elsif (grep (/in/, @{$e->{DIRECTION}})) {
|
|
||||||
$env{$e->{NAME}} = $base."in.$e->{NAME}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return \%env;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,884 +0,0 @@
|
||||||
###################################################
|
|
||||||
# client calls generator
|
|
||||||
# Copyright tridge@samba.org 2003
|
|
||||||
# Copyright jelmer@samba.org 2005-2006
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::NDR::Client;
|
|
||||||
|
|
||||||
use Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(Parse);
|
|
||||||
|
|
||||||
use Parse::Pidl qw(fatal warning error);
|
|
||||||
use Parse::Pidl::Util qw(has_property ParseExpr genpad);
|
|
||||||
use Parse::Pidl::NDR qw(ContainsPipe);
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
|
||||||
use Parse::Pidl::Samba4 qw(choose_header is_intree DeclLong);
|
|
||||||
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; }
|
|
||||||
sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); }
|
|
||||||
sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; }
|
|
||||||
sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; }
|
|
||||||
sub pidl_both($$) { my ($self, $txt) = @_; $self->{hdr} .= "$txt\n"; $self->{res_hdr} .= "$txt\n"; }
|
|
||||||
sub fn_declare($$) { my ($self,$n) = @_; $self->pidl($n); $self->pidl_hdr("$n;"); }
|
|
||||||
|
|
||||||
sub new($)
|
|
||||||
{
|
|
||||||
my ($class) = shift;
|
|
||||||
my $self = { res => "", res_hdr => "", tabs => "" };
|
|
||||||
bless($self, $class);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionHasPipes($$)
|
|
||||||
{
|
|
||||||
my ($self, $fn) = @_;
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
return 1 if ContainsPipe($e, $e->{LEVELS}[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_r_State($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
$self->pidl("struct dcerpc_$name\_r_state {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("};");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("static void dcerpc_$name\_r_done(struct tevent_req *subreq);");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_r_Send($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
my $proto = "struct tevent_req *dcerpc_$name\_r_send(TALLOC_CTX *mem_ctx,\n";
|
|
||||||
$proto .= "\tstruct tevent_context *ev,\n",
|
|
||||||
$proto .= "\tstruct dcerpc_binding_handle *h,\n",
|
|
||||||
$proto .= "\tstruct $name *r)";
|
|
||||||
|
|
||||||
$self->fn_declare($proto);
|
|
||||||
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
|
|
||||||
$self->pidl("struct tevent_req *req;");
|
|
||||||
$self->pidl("struct dcerpc_$name\_r_state *state;");
|
|
||||||
$self->pidl("struct tevent_req *subreq;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
|
||||||
$self->pidl("\t\t\tstruct dcerpc_$name\_r_state);");
|
|
||||||
$self->pidl("if (req == NULL) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return NULL;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
my $out_params = 0;
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless grep(/out/, @{$e->{DIRECTION}});
|
|
||||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
|
||||||
$out_params++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
my $submem;
|
|
||||||
if ($out_params > 0) {
|
|
||||||
$self->pidl("state->out_mem_ctx = talloc_new(state);");
|
|
||||||
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$submem = "state->out_mem_ctx";
|
|
||||||
} else {
|
|
||||||
$self->pidl("state->out_mem_ctx = NULL;");
|
|
||||||
$submem = "state";
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("subreq = dcerpc_binding_handle_call_send(state, ev, h,");
|
|
||||||
$self->pidl("\t\tNULL, &ndr_table_$if->{NAME},");
|
|
||||||
$self->pidl("\t\tNDR_$uname, $submem, r);");
|
|
||||||
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("tevent_req_set_callback(subreq, dcerpc_$name\_r_done, req);");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("return req;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_r_Done($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
my $proto = "static void dcerpc_$name\_r_done(struct tevent_req *subreq)";
|
|
||||||
|
|
||||||
$self->pidl("$proto");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
|
|
||||||
$self->pidl("struct tevent_req *req =");
|
|
||||||
$self->pidl("\ttevent_req_callback_data(subreq,");
|
|
||||||
$self->pidl("\tstruct tevent_req);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("status = dcerpc_binding_handle_call_recv(subreq);");
|
|
||||||
$self->pidl("TALLOC_FREE(subreq);");
|
|
||||||
$self->pidl("if (tevent_req_nterror(req, status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_done(req);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_r_Recv($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
my $proto = "NTSTATUS dcerpc_$name\_r_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)";
|
|
||||||
|
|
||||||
$self->fn_declare($proto);
|
|
||||||
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
|
|
||||||
$self->pidl("struct dcerpc_$name\_r_state *state =");
|
|
||||||
$self->pidl("\ttevent_req_data(req,");
|
|
||||||
$self->pidl("\tstruct dcerpc_$name\_r_state);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return status;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_r_Sync($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
if ($self->ParseFunctionHasPipes($fn)) {
|
|
||||||
$self->pidl_both("/*");
|
|
||||||
$self->pidl_both(" * The following function is skipped because");
|
|
||||||
$self->pidl_both(" * it uses pipes:");
|
|
||||||
$self->pidl_both(" *");
|
|
||||||
$self->pidl_both(" * dcerpc_$name\_r()");
|
|
||||||
$self->pidl_both(" */");
|
|
||||||
$self->pidl_both("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $proto = "NTSTATUS dcerpc_$name\_r(struct dcerpc_binding_handle *h, TALLOC_CTX *mem_ctx, struct $name *r)";
|
|
||||||
|
|
||||||
$self->fn_declare($proto);
|
|
||||||
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("status = dcerpc_binding_handle_call(h,");
|
|
||||||
$self->pidl("\t\tNULL, &ndr_table_$if->{NAME},");
|
|
||||||
$self->pidl("\t\tNDR_$uname, mem_ctx, r);");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("return status;");
|
|
||||||
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ElementDirection($)
|
|
||||||
{
|
|
||||||
my ($e) = @_;
|
|
||||||
|
|
||||||
return "[in,out]" 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 "[in,out]";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub HeaderProperties($$)
|
|
||||||
{
|
|
||||||
my($props,$ignores) = @_;
|
|
||||||
my $ret = "";
|
|
||||||
|
|
||||||
foreach my $d (sort(keys %{$props})) {
|
|
||||||
next if (grep(/^$d$/, @$ignores));
|
|
||||||
if($props->{$d} ne "1") {
|
|
||||||
$ret.= "$d($props->{$d}),";
|
|
||||||
} else {
|
|
||||||
$ret.="$d,";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ret) {
|
|
||||||
return "[" . substr($ret, 0, -1) . "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseCopyArgument($$$$$)
|
|
||||||
{
|
|
||||||
my ($self, $fn, $e, $r, $i) = @_;
|
|
||||||
my $l = $e->{LEVELS}[0];
|
|
||||||
|
|
||||||
if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED} == 1) {
|
|
||||||
$self->pidl("memcpy(${r}$e->{NAME}, ${i}$e->{NAME}, sizeof(${r}$e->{NAME}));");
|
|
||||||
} else {
|
|
||||||
$self->pidl("${r}$e->{NAME} = ${i}$e->{NAME};");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseInvalidResponse($$)
|
|
||||||
{
|
|
||||||
my ($self, $type) = @_;
|
|
||||||
|
|
||||||
if ($type eq "sync") {
|
|
||||||
$self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;");
|
|
||||||
} elsif ($type eq "async") {
|
|
||||||
$self->pidl("tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);");
|
|
||||||
$self->pidl("return;");
|
|
||||||
} else {
|
|
||||||
die("ParseInvalidResponse($type)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseOutputArgument($$$$$$)
|
|
||||||
{
|
|
||||||
my ($self, $fn, $e, $r, $o, $invalid_response_type) = @_;
|
|
||||||
my $level = 0;
|
|
||||||
|
|
||||||
if ($e->{LEVELS}[0]->{TYPE} ne "POINTER" and $e->{LEVELS}[0]->{TYPE} ne "ARRAY") {
|
|
||||||
fatal($e->{ORIGINAL}, "[out] argument is not a pointer or array");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
|
||||||
$level = 1;
|
|
||||||
if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") {
|
|
||||||
$self->pidl("if ($o$e->{NAME} && ${r}out.$e->{NAME}) {");
|
|
||||||
$self->indent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($e->{LEVELS}[$level]->{TYPE} eq "ARRAY") {
|
|
||||||
# This is a call to GenerateFunctionInEnv intentionally.
|
|
||||||
# Since the data is being copied into a user-provided data
|
|
||||||
# structure, the user should be able to know the size beforehand
|
|
||||||
# to allocate a structure of the right size.
|
|
||||||
my $in_env = GenerateFunctionInEnv($fn, $r);
|
|
||||||
my $out_env = GenerateFunctionOutEnv($fn, $r);
|
|
||||||
my $l = $e->{LEVELS}[$level];
|
|
||||||
|
|
||||||
my $in_var = undef;
|
|
||||||
if (grep(/in/, @{$e->{DIRECTION}})) {
|
|
||||||
$in_var = ParseExpr($e->{NAME}, $in_env, $e->{ORIGINAL});
|
|
||||||
}
|
|
||||||
my $out_var = ParseExpr($e->{NAME}, $out_env, $e->{ORIGINAL});
|
|
||||||
|
|
||||||
my $in_size_is = undef;
|
|
||||||
my $out_size_is = undef;
|
|
||||||
my $out_length_is = undef;
|
|
||||||
|
|
||||||
my $avail_len = undef;
|
|
||||||
my $needed_len = undef;
|
|
||||||
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
my $copy_len_var = "_copy_len_$e->{NAME}";
|
|
||||||
$self->pidl("size_t $copy_len_var;");
|
|
||||||
|
|
||||||
if (not defined($l->{SIZE_IS})) {
|
|
||||||
if (not $l->{IS_ZERO_TERMINATED}) {
|
|
||||||
fatal($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'");
|
|
||||||
}
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
$avail_len = "ndr_charset_length($in_var, CH_UNIX)";
|
|
||||||
$needed_len = "ndr_charset_length($out_var, CH_UNIX)";
|
|
||||||
} else {
|
|
||||||
$avail_len = "ndr_string_length($in_var, sizeof(*$in_var))";
|
|
||||||
$needed_len = "ndr_string_length($out_var, sizeof(*$out_var))";
|
|
||||||
}
|
|
||||||
$in_size_is = "";
|
|
||||||
$out_size_is = "";
|
|
||||||
$out_length_is = "";
|
|
||||||
} else {
|
|
||||||
$in_size_is = ParseExpr($l->{SIZE_IS}, $in_env, $e->{ORIGINAL});
|
|
||||||
$out_size_is = ParseExpr($l->{SIZE_IS}, $out_env, $e->{ORIGINAL});
|
|
||||||
$out_length_is = $out_size_is;
|
|
||||||
if (defined($l->{LENGTH_IS})) {
|
|
||||||
$out_length_is = ParseExpr($l->{LENGTH_IS}, $out_env, $e->{ORIGINAL});
|
|
||||||
}
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
if (defined($in_var)) {
|
|
||||||
$avail_len = "ndr_charset_length($in_var, CH_UNIX)";
|
|
||||||
} else {
|
|
||||||
$avail_len = $out_length_is;
|
|
||||||
}
|
|
||||||
$needed_len = "ndr_charset_length($out_var, CH_UNIX)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($out_size_is ne $in_size_is) {
|
|
||||||
$self->pidl("if (($out_size_is) > ($in_size_is)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->ParseInvalidResponse($invalid_response_type);
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
}
|
|
||||||
if ($out_length_is ne $out_size_is) {
|
|
||||||
$self->pidl("if (($out_length_is) > ($out_size_is)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->ParseInvalidResponse($invalid_response_type);
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
}
|
|
||||||
if (defined($needed_len)) {
|
|
||||||
$self->pidl("$copy_len_var = $needed_len;");
|
|
||||||
$self->pidl("if ($copy_len_var > $avail_len) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->ParseInvalidResponse($invalid_response_type);
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
} else {
|
|
||||||
$self->pidl("$copy_len_var = $out_length_is;");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $dest_ptr = "$o$e->{NAME}";
|
|
||||||
my $elem_size = "sizeof(*$dest_ptr)";
|
|
||||||
$self->pidl("if ($dest_ptr != $out_var) {");
|
|
||||||
$self->indent;
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
$dest_ptr = "discard_const_p(uint8_t *, $dest_ptr)";
|
|
||||||
}
|
|
||||||
$self->pidl("memcpy($dest_ptr, $out_var, $copy_len_var * $elem_size);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
} else {
|
|
||||||
$self->pidl("*$o$e->{NAME} = *${r}out.$e->{NAME};");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
|
||||||
if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") {
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_State($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
|
|
||||||
my $state_str = "struct dcerpc_$name\_state";
|
|
||||||
my $done_fn = "dcerpc_$name\_done";
|
|
||||||
|
|
||||||
$self->pidl("$state_str {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct $name orig;");
|
|
||||||
$self->pidl("struct $name tmp;");
|
|
||||||
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("};");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("static void $done_fn(struct tevent_req *subreq);");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_Send($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
|
|
||||||
my $fn_args = "";
|
|
||||||
my $state_str = "struct dcerpc_$name\_state";
|
|
||||||
my $done_fn = "dcerpc_$name\_done";
|
|
||||||
my $out_mem_ctx = "dcerpc_$name\_out_memory";
|
|
||||||
my $fn_str = "struct tevent_req *dcerpc_$name\_send";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "TALLOC_CTX *mem_ctx";
|
|
||||||
$fn_args .= ",\n" . $pad . "struct tevent_context *ev";
|
|
||||||
$fn_args .= ",\n" . $pad . "struct dcerpc_binding_handle *h";
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
my $dir = ElementDirection($_);
|
|
||||||
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
|
||||||
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct tevent_req *req;");
|
|
||||||
$self->pidl("$state_str *state;");
|
|
||||||
$self->pidl("struct tevent_req *subreq;");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
|
||||||
$self->pidl("\t\t\t$state_str);");
|
|
||||||
$self->pidl("if (req == NULL) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return NULL;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("state->out_mem_ctx = NULL;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* In parameters */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless (grep(/in/, @{$e->{DIRECTION}}));
|
|
||||||
|
|
||||||
$self->ParseCopyArgument($fn, $e, "state->orig.in.", "_");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
my $out_params = 0;
|
|
||||||
$self->pidl("/* Out parameters */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless grep(/out/, @{$e->{DIRECTION}});
|
|
||||||
|
|
||||||
$self->ParseCopyArgument($fn, $e, "state->orig.out.", "_");
|
|
||||||
|
|
||||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
|
||||||
|
|
||||||
$out_params++;
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl("/* Result */");
|
|
||||||
$self->pidl("ZERO_STRUCT(state->orig.out.result);");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($out_params > 0) {
|
|
||||||
$self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,");
|
|
||||||
$self->pidl("\t\t \"$out_mem_ctx\");");
|
|
||||||
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("/* make a temporary copy, that we pass to the dispatch function */");
|
|
||||||
$self->pidl("state->tmp = state->orig;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("subreq = dcerpc_$name\_r_send(state, ev, h, &state->tmp);");
|
|
||||||
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("tevent_req_set_callback(subreq, $done_fn, req);");
|
|
||||||
$self->pidl("return req;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_Done($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
|
|
||||||
my $state_str = "struct dcerpc_$name\_state";
|
|
||||||
my $done_fn = "dcerpc_$name\_done";
|
|
||||||
|
|
||||||
$self->pidl("static void $done_fn(struct tevent_req *subreq)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct tevent_req *req = tevent_req_callback_data(");
|
|
||||||
$self->pidl("\tsubreq, struct tevent_req);");
|
|
||||||
$self->pidl("$state_str *state = tevent_req_data(");
|
|
||||||
$self->pidl("\treq, $state_str);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("TALLOC_CTX *mem_ctx;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("if (state->out_mem_ctx) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("mem_ctx = state->out_mem_ctx;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("} else {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("mem_ctx = state;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("status = dcerpc_$name\_r_recv(subreq, mem_ctx);");
|
|
||||||
$self->pidl("TALLOC_FREE(subreq);");
|
|
||||||
$self->pidl("if (tevent_req_nterror(req, status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Copy out parameters */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
|
||||||
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
|
||||||
|
|
||||||
$self->ParseOutputArgument($fn, $e,
|
|
||||||
"state->tmp.",
|
|
||||||
"state->orig.out.",
|
|
||||||
"async");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl("/* Copy result */");
|
|
||||||
$self->pidl("state->orig.out.result = state->tmp.out.result;");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("/* Reset temporary structure */");
|
|
||||||
$self->pidl("ZERO_STRUCT(state->tmp);");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_done(req);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_Recv($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
|
|
||||||
my $fn_args = "";
|
|
||||||
my $state_str = "struct dcerpc_$name\_state";
|
|
||||||
my $fn_str = "NTSTATUS dcerpc_$name\_recv";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "struct tevent_req *req,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("$state_str *state = tevent_req_data(");
|
|
||||||
$self->pidl("\treq, $state_str);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return status;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Steal possible out parameters to the callers context */");
|
|
||||||
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl("/* Return result */");
|
|
||||||
$self->pidl("*result = state->orig.out.result;");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_Sync($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
|
|
||||||
if ($self->ParseFunctionHasPipes($fn)) {
|
|
||||||
$self->pidl_both("/*");
|
|
||||||
$self->pidl_both(" * The following function is skipped because");
|
|
||||||
$self->pidl_both(" * it uses pipes:");
|
|
||||||
$self->pidl_both(" *");
|
|
||||||
$self->pidl_both(" * dcerpc_$name()");
|
|
||||||
$self->pidl_both(" */");
|
|
||||||
$self->pidl_both("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $uname = uc $name;
|
|
||||||
my $fn_args = "";
|
|
||||||
my $fn_str = "NTSTATUS dcerpc_$name";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "struct dcerpc_binding_handle *h,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
my $dir = ElementDirection($_);
|
|
||||||
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
|
||||||
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct $name r;");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* In parameters */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless (grep(/in/, @{$e->{DIRECTION}}));
|
|
||||||
|
|
||||||
$self->ParseCopyArgument($fn, $e, "r.in.", "_");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Out parameters */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless grep(/out/, @{$e->{DIRECTION}});
|
|
||||||
|
|
||||||
$self->ParseCopyArgument($fn, $e, "r.out.", "_");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl("/* Result */");
|
|
||||||
$self->pidl("ZERO_STRUCT(r.out.result);");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("status = dcerpc_$name\_r(h, mem_ctx, &r);");
|
|
||||||
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return status;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Return variables */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
|
||||||
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
|
||||||
|
|
||||||
$self->ParseOutputArgument($fn, $e, "r.", "_", "sync");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Return result */");
|
|
||||||
if ($fn->{RETURN_TYPE}) {
|
|
||||||
$self->pidl("*result = r.out.result;");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a function
|
|
||||||
sub ParseFunction($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
if ($self->ParseFunctionHasPipes($fn)) {
|
|
||||||
$self->pidl_both("/*");
|
|
||||||
$self->pidl_both(" * The following function is skipped because");
|
|
||||||
$self->pidl_both(" * it uses pipes:");
|
|
||||||
$self->pidl_both(" *");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_r_send()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_r_recv()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_r()");
|
|
||||||
$self->pidl_both(" *");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_send()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_recv()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}()");
|
|
||||||
$self->pidl_both(" */");
|
|
||||||
$self->pidl_both("");
|
|
||||||
warning($fn->{ORIGINAL}, "$fn->{NAME}: dcerpc client does not support pipe yet");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->ParseFunction_r_State($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_r_Send($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_r_Done($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_r_Recv($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_r_Sync($if, $fn, $fn->{NAME});
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
|
||||||
|
|
||||||
my $reason = "is not a pointer or array";
|
|
||||||
|
|
||||||
# TODO: make this fatal at NDR level
|
|
||||||
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
|
||||||
if ($e->{LEVELS}[1]->{TYPE} eq "DATA" and
|
|
||||||
$e->{LEVELS}[1]->{DATA_TYPE} eq "string") {
|
|
||||||
$reason = "is a pointer to type 'string'";
|
|
||||||
} elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and
|
|
||||||
$e->{LEVELS}[1]->{IS_ZERO_TERMINATED}) {
|
|
||||||
next;
|
|
||||||
} elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and
|
|
||||||
not defined($e->{LEVELS}[1]->{SIZE_IS})) {
|
|
||||||
$reason = "is a pointer to an unsized array";
|
|
||||||
} else {
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($e->{LEVELS}[0]->{TYPE} eq "ARRAY") {
|
|
||||||
if (not defined($e->{LEVELS}[0]->{SIZE_IS})) {
|
|
||||||
$reason = "is an unsized array";
|
|
||||||
} else {
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl_both("/*");
|
|
||||||
$self->pidl_both(" * The following functions are skipped because");
|
|
||||||
$self->pidl_both(" * an [out] argument $e->{NAME} $reason:");
|
|
||||||
$self->pidl_both(" *");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_send()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_recv()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}()");
|
|
||||||
$self->pidl_both(" */");
|
|
||||||
$self->pidl_both("");
|
|
||||||
|
|
||||||
error($e->{ORIGINAL}, "$fn->{NAME}: [out] argument '$e->{NAME}' $reason, skip client functions");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->ParseFunction_State($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_Send($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_Done($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_Recv($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_Sync($if, $fn, $fn->{NAME});
|
|
||||||
|
|
||||||
$self->pidl_hdr("");
|
|
||||||
}
|
|
||||||
|
|
||||||
my %done;
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse the interface definitions
|
|
||||||
sub ParseInterface($$)
|
|
||||||
{
|
|
||||||
my ($self, $if) = @_;
|
|
||||||
my $ifu = uc($if->{NAME});
|
|
||||||
|
|
||||||
$self->pidl_hdr("#ifndef _HEADER_RPC_$if->{NAME}");
|
|
||||||
$self->pidl_hdr("#define _HEADER_RPC_$if->{NAME}");
|
|
||||||
$self->pidl_hdr("");
|
|
||||||
|
|
||||||
if (defined $if->{PROPERTIES}->{uuid}) {
|
|
||||||
$self->pidl_hdr("extern const struct ndr_interface_table ndr_table_$if->{NAME};");
|
|
||||||
$self->pidl_hdr("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("/* $if->{NAME} - client functions generated by pidl */");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
foreach my $fn (@{$if->{FUNCTIONS}}) {
|
|
||||||
next if defined($done{$fn->{NAME}});
|
|
||||||
next if has_property($fn, "noopnum");
|
|
||||||
next if has_property($fn, "todo");
|
|
||||||
$self->ParseFunction($if, $fn);
|
|
||||||
$done{$fn->{NAME}} = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl_hdr("#endif /* _HEADER_RPC_$if->{NAME} */");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$$$$$)
|
|
||||||
{
|
|
||||||
my($self,$ndr,$header,$ndr_header,$client_header) = @_;
|
|
||||||
|
|
||||||
$self->pidl("/* client functions auto-generated by pidl */");
|
|
||||||
$self->pidl("");
|
|
||||||
if (is_intree()) {
|
|
||||||
$self->pidl("#include \"includes.h\"");
|
|
||||||
} else {
|
|
||||||
$self->pidl("#ifndef _GNU_SOURCE");
|
|
||||||
$self->pidl("#define _GNU_SOURCE");
|
|
||||||
$self->pidl("#endif");
|
|
||||||
$self->pidl("#include <stdio.h>");
|
|
||||||
$self->pidl("#include <stdbool.h>");
|
|
||||||
$self->pidl("#include <stdlib.h>");
|
|
||||||
$self->pidl("#include <stdint.h>");
|
|
||||||
$self->pidl("#include <stdarg.h>");
|
|
||||||
$self->pidl("#include <string.h>");
|
|
||||||
$self->pidl("#include <core/ntstatus.h>");
|
|
||||||
}
|
|
||||||
$self->pidl("#include <tevent.h>");
|
|
||||||
$self->pidl(choose_header("lib/util/tevent_ntstatus.h", "util/tevent_ntstatus.h")."");
|
|
||||||
$self->pidl("#include \"$ndr_header\"");
|
|
||||||
$self->pidl("#include \"$client_header\"");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl_hdr(choose_header("librpc/rpc/dcerpc.h", "dcerpc.h")."");
|
|
||||||
$self->pidl_hdr("#include \"$header\"");
|
|
||||||
|
|
||||||
foreach my $x (@{$ndr}) {
|
|
||||||
($x->{TYPE} eq "INTERFACE") && $self->ParseInterface($x);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($self->{res},$self->{res_hdr});
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,335 +0,0 @@
|
||||||
###################################################
|
|
||||||
# server boilerplate generator
|
|
||||||
# Copyright tridge@samba.org 2003
|
|
||||||
# Copyright metze@samba.org 2004
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::NDR::Server;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Parse::Pidl::Util;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
sub pidl($)
|
|
||||||
{
|
|
||||||
$res .= shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################
|
|
||||||
# generate the switch statement for function dispatch
|
|
||||||
sub gen_dispatch_switch($)
|
|
||||||
{
|
|
||||||
my $interface = shift;
|
|
||||||
|
|
||||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
|
||||||
next if not defined($fn->{OPNUM});
|
|
||||||
|
|
||||||
pidl "\tcase $fn->{OPNUM}: {\n";
|
|
||||||
pidl "\t\tstruct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;\n";
|
|
||||||
pidl "\t\tif (DEBUGLEVEL >= 10) {\n";
|
|
||||||
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_IN, r2);\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
|
|
||||||
pidl "\t\tr2->out.result = dcesrv_$fn->{NAME}(dce_call, mem_ctx, r2);\n";
|
|
||||||
} else {
|
|
||||||
pidl "\t\tdcesrv_$fn->{NAME}(dce_call, mem_ctx, r2);\n";
|
|
||||||
}
|
|
||||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(5,(\"function $fn->{NAME} will reply async\\n\"));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tbreak;\n\t}\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################
|
|
||||||
# generate the switch statement for function reply
|
|
||||||
sub gen_reply_switch($)
|
|
||||||
{
|
|
||||||
my $interface = shift;
|
|
||||||
|
|
||||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
|
||||||
next if not defined($fn->{OPNUM});
|
|
||||||
|
|
||||||
pidl "\tcase $fn->{OPNUM}: {\n";
|
|
||||||
pidl "\t\tstruct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;\n";
|
|
||||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(5,(\"function $fn->{NAME} replied async\\n\"));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tif (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {\n";
|
|
||||||
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tif (dce_call->fault_code != 0) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $fn->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tbreak;\n\t}\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for a interface
|
|
||||||
sub Boilerplate_Iface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
my $uname = uc $name;
|
|
||||||
my $uuid = lc($interface->{UUID});
|
|
||||||
my $if_version = $interface->{VERSION};
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
|
|
||||||
{
|
|
||||||
#ifdef DCESRV_INTERFACE_$uname\_BIND
|
|
||||||
return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface);
|
|
||||||
#else
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
|
|
||||||
{
|
|
||||||
#ifdef DCESRV_INTERFACE_$uname\_UNBIND
|
|
||||||
DCESRV_INTERFACE_$uname\_UNBIND(context, iface);
|
|
||||||
#else
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
|
|
||||||
{
|
|
||||||
enum ndr_err_code ndr_err;
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
dce_call->fault_code = 0;
|
|
||||||
|
|
||||||
if (opnum >= ndr_table_$name.num_calls) {
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
*r = talloc_named(mem_ctx,
|
|
||||||
ndr_table_$name.calls[opnum].struct_size,
|
|
||||||
\"struct %s\",
|
|
||||||
ndr_table_$name.calls[opnum].name);
|
|
||||||
NT_STATUS_HAVE_NO_MEMORY(*r);
|
|
||||||
|
|
||||||
/* unravel the NDR for the packet */
|
|
||||||
ndr_err = ndr_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|
||||||
dcerpc_log_packet(dce_call->conn->packet_log_dir,
|
|
||||||
&ndr_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
|
||||||
{
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
switch (opnum) {
|
|
||||||
";
|
|
||||||
gen_dispatch_switch($interface);
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
default:
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dce_call->fault_code != 0) {
|
|
||||||
dcerpc_log_packet(dce_call->conn->packet_log_dir,
|
|
||||||
&ndr_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
|
||||||
{
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
switch (opnum) {
|
|
||||||
";
|
|
||||||
gen_reply_switch($interface);
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
default:
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dce_call->fault_code != 0) {
|
|
||||||
dcerpc_log_packet(dce_call->conn->packet_log_dir,
|
|
||||||
&ndr_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
|
|
||||||
{
|
|
||||||
enum ndr_err_code ndr_err;
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
ndr_err = ndr_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct dcesrv_interface dcesrv\_$name\_interface = {
|
|
||||||
.name = \"$name\",
|
|
||||||
.syntax_id = {".print_uuid($uuid).",$if_version},
|
|
||||||
.bind = $name\__op_bind,
|
|
||||||
.unbind = $name\__op_unbind,
|
|
||||||
.ndr_pull = $name\__op_ndr_pull,
|
|
||||||
.dispatch = $name\__op_dispatch,
|
|
||||||
.reply = $name\__op_reply,
|
|
||||||
.ndr_push = $name\__op_ndr_push
|
|
||||||
};
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for an endpoint server
|
|
||||||
sub Boilerplate_Ep_Server($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0;i<ndr_table_$name.endpoints->count;i++) {
|
|
||||||
NTSTATUS ret;
|
|
||||||
const char *name = ndr_table_$name.endpoints->names[i];
|
|
||||||
|
|
||||||
ret = dcesrv_interface_register(dce_ctx, name, &dcesrv_$name\_interface, NULL);
|
|
||||||
if (!NT_STATUS_IS_OK(ret)) {
|
|
||||||
DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version)
|
|
||||||
{
|
|
||||||
if (dcesrv_$name\_interface.syntax_id.if_version == if_version &&
|
|
||||||
GUID_equal(\&dcesrv\_$name\_interface.syntax_id.uuid, uuid)) {
|
|
||||||
memcpy(iface,&dcesrv\_$name\_interface, sizeof(*iface));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
|
|
||||||
{
|
|
||||||
if (strcmp(dcesrv_$name\_interface.name, name)==0) {
|
|
||||||
memcpy(iface, &dcesrv_$name\_interface, sizeof(*iface));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS dcerpc_server_$name\_init(void)
|
|
||||||
{
|
|
||||||
NTSTATUS ret;
|
|
||||||
struct dcesrv_endpoint_server ep_server;
|
|
||||||
|
|
||||||
/* fill in our name */
|
|
||||||
ep_server.name = \"$name\";
|
|
||||||
|
|
||||||
/* fill in all the operations */
|
|
||||||
ep_server.init_server = $name\__op_init_server;
|
|
||||||
|
|
||||||
ep_server.interface_by_uuid = $name\__op_interface_by_uuid;
|
|
||||||
ep_server.interface_by_name = $name\__op_interface_by_name;
|
|
||||||
|
|
||||||
/* register ourselves with the DCERPC subsystem. */
|
|
||||||
ret = dcerpc_register_ep_server(&ep_server);
|
|
||||||
|
|
||||||
if (!NT_STATUS_IS_OK(ret)) {
|
|
||||||
DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dcerpc server boilerplate from a parsed IDL structure
|
|
||||||
sub ParseInterface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my $count = 0;
|
|
||||||
|
|
||||||
$res .= "NTSTATUS dcerpc_server_$interface->{NAME}\_init(void);\n";
|
|
||||||
$res .= "\n";
|
|
||||||
|
|
||||||
if (!defined $interface->{PROPERTIES}->{uuid}) {
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defined $interface->{PROPERTIES}->{version}) {
|
|
||||||
$interface->{PROPERTIES}->{version} = "0.0";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
|
||||||
if (defined($fn->{OPNUM})) { $count++; }
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($count == 0) {
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= "/* $interface->{NAME} - dcerpc server boilerplate generated by pidl */\n\n";
|
|
||||||
Boilerplate_Iface($interface);
|
|
||||||
Boilerplate_Ep_Server($interface);
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$)
|
|
||||||
{
|
|
||||||
my($ndr,$header) = @_;
|
|
||||||
|
|
||||||
$res = "";
|
|
||||||
$res .= "/* server functions auto-generated by pidl */\n";
|
|
||||||
$res .= "#include \"$header\"\n";
|
|
||||||
$res .= "#include <util/debug.h>\n";
|
|
||||||
$res .= "\n";
|
|
||||||
|
|
||||||
foreach my $x (@{$ndr}) {
|
|
||||||
ParseInterface($x) if ($x->{TYPE} eq "INTERFACE" and not defined($x->{PROPERTIES}{object}));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,283 +0,0 @@
|
||||||
###################################################
|
|
||||||
# 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 Parse::Pidl::Typelist qw(mapTypeName);
|
|
||||||
|
|
||||||
use Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(ParserType $ret $ret_hdr);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
sub new($) {
|
|
||||||
my ($class) = shift;
|
|
||||||
my $self = { ret => "", ret_hdr => "", tabs => "" };
|
|
||||||
bless($self, $class);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub indent($) { my $self = shift; $self->{tabs}.="\t"; }
|
|
||||||
sub deindent($) { my $self = shift; $self->{tabs} = substr($self->{tabs}, 1); }
|
|
||||||
sub pidl($$) { my $self = shift; $self->{ret} .= $self->{tabs}.(shift)."\n"; }
|
|
||||||
sub pidl_hdr($$) { my $self = shift; $self->{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 ($self, $p, $d) = @_;
|
|
||||||
if ($p) {
|
|
||||||
$self->pidl($d); $self->pidl_hdr("$d;");
|
|
||||||
} else {
|
|
||||||
$self->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 ($self, $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")) {
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("uint32_t saved_flags = tdr->flags;");
|
|
||||||
$self->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");
|
|
||||||
$self->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)) {
|
|
||||||
$self->pidl("TDR_ALLOC(mem_ctx, v->$e->{NAME}, $len);");
|
|
||||||
$mem_ctx = "v->$e->{NAME}";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("for (i = 0; i < $len; i++) {");
|
|
||||||
$self->indent;
|
|
||||||
$array = "[i]";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($t eq "pull") {
|
|
||||||
$name = ", $mem_ctx";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "value") && $t eq "push") {
|
|
||||||
$self->pidl("v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env, $e).";");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));");
|
|
||||||
|
|
||||||
if ($array) { $self->deindent; $self->pidl("}"); }
|
|
||||||
|
|
||||||
if (has_property($e, "flag")) {
|
|
||||||
$self->pidl("tdr->flags = saved_flags;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserStruct($$$$$)
|
|
||||||
{
|
|
||||||
my ($self, $e,$t,$p) = @_;
|
|
||||||
|
|
||||||
$self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", struct $e->{NAME} *v)");
|
|
||||||
$self->pidl("{"); $self->indent;
|
|
||||||
$self->pidl("int i;") if (ContainsArray($e));
|
|
||||||
|
|
||||||
if ($t eq "print") {
|
|
||||||
$self->pidl("tdr->print(tdr, \"\%-25s: struct $e->{NAME}\", name);");
|
|
||||||
$self->pidl("tdr->level++;");
|
|
||||||
}
|
|
||||||
|
|
||||||
my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}};
|
|
||||||
$env{"this"} = "v";
|
|
||||||
$self->ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}});
|
|
||||||
|
|
||||||
if ($t eq "print") {
|
|
||||||
$self->pidl("tdr->level--;");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
|
|
||||||
$self->deindent; $self->pidl("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserUnion($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $e,$t,$p) = @_;
|
|
||||||
|
|
||||||
$self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME}(struct tdr_$t *tdr".typearg($t).", int level, union $e->{NAME} *v)");
|
|
||||||
$self->pidl("{"); $self->indent;
|
|
||||||
$self->pidl("int i;") if (ContainsArray($e));
|
|
||||||
|
|
||||||
if ($t eq "print") {
|
|
||||||
$self->pidl("tdr->print(tdr, \"\%-25s: union $e->{NAME}\", name);");
|
|
||||||
$self->pidl("tdr->level++;");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("switch (level) {"); $self->indent;
|
|
||||||
foreach (@{$e->{ELEMENTS}}) {
|
|
||||||
if (has_property($_, "case")) {
|
|
||||||
$self->pidl("case " . $_->{PROPERTIES}->{case} . ":");
|
|
||||||
} elsif (has_property($_, "default")) {
|
|
||||||
$self->pidl("default:");
|
|
||||||
}
|
|
||||||
$self->indent; $self->ParserElement($_, $t, {}); $self->deindent;
|
|
||||||
$self->pidl("break;");
|
|
||||||
}
|
|
||||||
$self->deindent; $self->pidl("}");
|
|
||||||
|
|
||||||
if ($t eq "print") {
|
|
||||||
$self->pidl("tdr->level--;");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("return NT_STATUS_OK;\n");
|
|
||||||
$self->deindent; $self->pidl("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserBitmap($$$$)
|
|
||||||
{
|
|
||||||
my ($self,$e,$t,$p) = @_;
|
|
||||||
return if ($p);
|
|
||||||
$self->pidl("#define tdr_$t\_$e->{NAME} tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e));
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserEnum($$$$)
|
|
||||||
{
|
|
||||||
my ($self,$e,$t,$p) = @_;
|
|
||||||
my $bt = Parse::Pidl::Typelist::enum_type_fn($e);
|
|
||||||
my $mt = mapTypeName($bt);
|
|
||||||
|
|
||||||
$self->fn_declare($p, "NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", enum $e->{NAME} *v)");
|
|
||||||
$self->pidl("{");
|
|
||||||
if ($t eq "pull") {
|
|
||||||
$self->pidl("\t$mt r;");
|
|
||||||
$self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, mem_ctx, \&r));");
|
|
||||||
$self->pidl("\t*v = r;");
|
|
||||||
} elsif ($t eq "push") {
|
|
||||||
$self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, ($mt *)v));");
|
|
||||||
} elsif ($t eq "print") {
|
|
||||||
$self->pidl("\t/* FIXME */");
|
|
||||||
}
|
|
||||||
$self->pidl("\treturn NT_STATUS_OK;");
|
|
||||||
$self->pidl("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserTypedef($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $e,$t,$p) = @_;
|
|
||||||
|
|
||||||
$self->ParserType($e->{DATA},$t);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserType($$$)
|
|
||||||
{
|
|
||||||
my ($self, $e,$t) = @_;
|
|
||||||
|
|
||||||
return if (has_property($e, "no$t"));
|
|
||||||
|
|
||||||
my $handlers = {
|
|
||||||
STRUCT => \&ParserStruct, UNION => \&ParserUnion,
|
|
||||||
ENUM => \&ParserEnum, BITMAP => \&ParserBitmap,
|
|
||||||
TYPEDEF => \&ParserTypedef
|
|
||||||
};
|
|
||||||
|
|
||||||
$handlers->{$e->{TYPE}}->($self, $e, $t, has_property($e, "public"))
|
|
||||||
if (defined($handlers->{$e->{TYPE}}));
|
|
||||||
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserInterface($$)
|
|
||||||
{
|
|
||||||
my ($self,$x) = @_;
|
|
||||||
|
|
||||||
$self->pidl_hdr("#ifndef __TDR_$x->{NAME}_HEADER__");
|
|
||||||
$self->pidl_hdr("#define __TDR_$x->{NAME}_HEADER__");
|
|
||||||
|
|
||||||
foreach (@{$x->{DATA}}) {
|
|
||||||
$self->ParserType($_, "pull");
|
|
||||||
$self->ParserType($_, "push");
|
|
||||||
$self->ParserType($_, "print");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl_hdr("#endif /* __TDR_$x->{NAME}_HEADER__ */");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parser($$$$)
|
|
||||||
{
|
|
||||||
my ($self,$idl,$hdrname,$baseheader) = @_;
|
|
||||||
$self->pidl("/* autogenerated by pidl */");
|
|
||||||
if (is_intree()) {
|
|
||||||
$self->pidl("#include \"includes.h\"");
|
|
||||||
} else {
|
|
||||||
$self->pidl("#include <stdio.h>");
|
|
||||||
$self->pidl("#include <stdbool.h>");
|
|
||||||
$self->pidl("#include <stdlib.h>");
|
|
||||||
$self->pidl("#include <stdint.h>");
|
|
||||||
$self->pidl("#include <stdarg.h>");
|
|
||||||
$self->pidl("#include <string.h>");
|
|
||||||
$self->pidl("#include <core/ntstatus.h>");
|
|
||||||
}
|
|
||||||
$self->pidl("#include \"$hdrname\"");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl_hdr("/* autogenerated by pidl */");
|
|
||||||
$self->pidl_hdr("#include \"$baseheader\"");
|
|
||||||
$self->pidl_hdr(choose_header("lib/tdr/tdr.h", "tdr.h"));
|
|
||||||
$self->pidl_hdr("");
|
|
||||||
|
|
||||||
foreach (@$idl) { $self->ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); }
|
|
||||||
return ($self->{ret_hdr}, $self->{ret});
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,103 +0,0 @@
|
||||||
###################################################
|
|
||||||
# server template function generator
|
|
||||||
# Copyright tridge@samba.org 2003
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::Template;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use Parse::Pidl::Util qw(genpad);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for a interface
|
|
||||||
sub Template($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
|
|
||||||
$res .=
|
|
||||||
"/*
|
|
||||||
Unix SMB/CIFS implementation.
|
|
||||||
|
|
||||||
endpoint server for the $name pipe
|
|
||||||
|
|
||||||
Copyright (C) YOUR NAME HERE YEAR
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include \"includes.h\"
|
|
||||||
#include \"rpc_server/dcerpc_server.h\"
|
|
||||||
#include \"librpc/gen_ndr/ndr_$name.h\"
|
|
||||||
#include \"rpc_server/common/common.h\"
|
|
||||||
|
|
||||||
";
|
|
||||||
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
if ($d->{TYPE} eq "FUNCTION") {
|
|
||||||
my $fname = $d->{NAME};
|
|
||||||
my $pad = genpad("static $d->{RETURN_TYPE} dcesrv_$fname");
|
|
||||||
$res .=
|
|
||||||
"
|
|
||||||
/*
|
|
||||||
$fname
|
|
||||||
*/
|
|
||||||
|
|
||||||
static $d->{RETURN_TYPE} dcesrv_$fname(struct dcesrv_call_state *dce_call,
|
|
||||||
$pad"."TALLOC_CTX *mem_ctx,
|
|
||||||
$pad"."struct $fname *r)
|
|
||||||
{
|
|
||||||
";
|
|
||||||
|
|
||||||
if ($d->{RETURN_TYPE} eq "void") {
|
|
||||||
$res .= "\tDCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);\n";
|
|
||||||
} else {
|
|
||||||
$res .= "\tDCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= "}
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .=
|
|
||||||
"
|
|
||||||
/* include the generated boilerplate */
|
|
||||||
#include \"librpc/gen_ndr/ndr_$name\_s.c\"
|
|
||||||
"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a parsed IDL structure back into an IDL file
|
|
||||||
sub Parse($)
|
|
||||||
{
|
|
||||||
my($idl) = shift;
|
|
||||||
$res = "";
|
|
||||||
foreach my $x (@{$idl}) {
|
|
||||||
($x->{TYPE} eq "INTERFACE") &&
|
|
||||||
Template($x);
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,354 +0,0 @@
|
||||||
###################################################
|
|
||||||
# Samba4 parser generator for IDL structures
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Typelist;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(hasType getType resolveType mapTypeName scalar_is_reference expandAlias
|
|
||||||
mapScalarType addType typeIs is_signed is_scalar enum_type_fn
|
|
||||||
bitmap_type_fn mapType typeHasBody is_fixed_size_scalar
|
|
||||||
);
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
my %types = ();
|
|
||||||
|
|
||||||
my @reference_scalars = (
|
|
||||||
"string", "string_array", "nbt_string", "dns_string",
|
|
||||||
"wrepl_nbt_name", "dnsp_name", "dnsp_string",
|
|
||||||
"ipv4address", "ipv6address"
|
|
||||||
);
|
|
||||||
|
|
||||||
my @non_fixed_size_scalars = (
|
|
||||||
"string", "string_array", "nbt_string", "dns_string",
|
|
||||||
"wrepl_nbt_name", "dnsp_name", "dnsp_string"
|
|
||||||
);
|
|
||||||
|
|
||||||
# a list of known scalar types
|
|
||||||
my %scalars = (
|
|
||||||
"void" => "void",
|
|
||||||
"char" => "char",
|
|
||||||
"int8" => "int8_t",
|
|
||||||
"uint8" => "uint8_t",
|
|
||||||
"int16" => "int16_t",
|
|
||||||
"uint16" => "uint16_t",
|
|
||||||
"int1632" => "int16_t",
|
|
||||||
"uint1632" => "uint16_t",
|
|
||||||
"int32" => "int32_t",
|
|
||||||
"uint32" => "uint32_t",
|
|
||||||
"int3264" => "int32_t",
|
|
||||||
"uint3264" => "uint32_t",
|
|
||||||
"hyper" => "uint64_t",
|
|
||||||
"dlong" => "int64_t",
|
|
||||||
"udlong" => "uint64_t",
|
|
||||||
"udlongr" => "uint64_t",
|
|
||||||
"double" => "double",
|
|
||||||
"pointer" => "void*",
|
|
||||||
"DATA_BLOB" => "DATA_BLOB",
|
|
||||||
"string" => "const char *",
|
|
||||||
"string_array" => "const char **",
|
|
||||||
"time_t" => "time_t",
|
|
||||||
"uid_t" => "uid_t",
|
|
||||||
"gid_t" => "gid_t",
|
|
||||||
"NTTIME" => "NTTIME",
|
|
||||||
"NTTIME_1sec" => "NTTIME",
|
|
||||||
"NTTIME_hyper" => "NTTIME",
|
|
||||||
"WERROR" => "WERROR",
|
|
||||||
"HRESULT" => "HRESULT",
|
|
||||||
"NTSTATUS" => "NTSTATUS",
|
|
||||||
"COMRESULT" => "COMRESULT",
|
|
||||||
"dns_string" => "const char *",
|
|
||||||
"nbt_string" => "const char *",
|
|
||||||
"wrepl_nbt_name"=> "struct nbt_name *",
|
|
||||||
"ipv4address" => "const char *",
|
|
||||||
"ipv6address" => "const char *",
|
|
||||||
"dnsp_name" => "const char *",
|
|
||||||
"dnsp_string" => "const char *",
|
|
||||||
);
|
|
||||||
|
|
||||||
my %aliases = (
|
|
||||||
"error_status_t" => "uint32",
|
|
||||||
"boolean8" => "uint8",
|
|
||||||
"boolean32" => "uint32",
|
|
||||||
"DWORD" => "uint32",
|
|
||||||
"uint" => "uint32",
|
|
||||||
"int" => "int32",
|
|
||||||
"WORD" => "uint16",
|
|
||||||
"char" => "uint8",
|
|
||||||
"long" => "int32",
|
|
||||||
"short" => "int16",
|
|
||||||
"HYPER_T" => "hyper",
|
|
||||||
"mode_t" => "uint32",
|
|
||||||
);
|
|
||||||
|
|
||||||
sub expandAlias($)
|
|
||||||
{
|
|
||||||
my $name = shift;
|
|
||||||
|
|
||||||
return $aliases{$name} if defined($aliases{$name});
|
|
||||||
|
|
||||||
return $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
# map from a IDL type to a C header type
|
|
||||||
sub mapScalarType($)
|
|
||||||
{
|
|
||||||
my $name = shift;
|
|
||||||
|
|
||||||
# it's a bug when a type is not in the list
|
|
||||||
# of known scalars or has no mapping
|
|
||||||
return $scalars{$name} if defined($scalars{$name});
|
|
||||||
|
|
||||||
die("Unknown scalar type $name");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub addType($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
$types{$t->{NAME}} = $t;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub resolveType($)
|
|
||||||
{
|
|
||||||
my ($ctype) = @_;
|
|
||||||
|
|
||||||
if (not hasType($ctype)) {
|
|
||||||
# assume struct typedef
|
|
||||||
return { TYPE => "TYPEDEF", NAME => $ctype, DATA => { TYPE => "STRUCT" } };
|
|
||||||
} else {
|
|
||||||
return getType($ctype);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ctype;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub getType($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
return ($t) if (ref($t) eq "HASH" and not defined($t->{NAME}));
|
|
||||||
return undef if not hasType($t);
|
|
||||||
return $types{$t->{NAME}} if (ref($t) eq "HASH");
|
|
||||||
return $types{$t};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub typeIs($$);
|
|
||||||
sub typeIs($$)
|
|
||||||
{
|
|
||||||
my ($t,$tt) = @_;
|
|
||||||
|
|
||||||
if (ref($t) eq "HASH") {
|
|
||||||
return 1 if ($t->{TYPE} eq "TYPEDEF" and $t->{DATA}->{TYPE} eq $tt);
|
|
||||||
return 1 if ($t->{TYPE} eq $tt);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (hasType($t) and getType($t)->{TYPE} eq "TYPEDEF") {
|
|
||||||
return typeIs(getType($t)->{DATA}, $tt);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub hasType($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
if (ref($t) eq "HASH") {
|
|
||||||
return 1 if (not defined($t->{NAME}));
|
|
||||||
return 1 if (defined($types{$t->{NAME}}) and
|
|
||||||
$types{$t->{NAME}}->{TYPE} eq $t->{TYPE});
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1 if defined($types{$t});
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub is_signed($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
|
|
||||||
return ($t eq "int8"
|
|
||||||
or $t eq "int16"
|
|
||||||
or $t eq "int32"
|
|
||||||
or $t eq "dlong"
|
|
||||||
or $t eq "int"
|
|
||||||
or $t eq "long"
|
|
||||||
or $t eq "short");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub is_scalar($)
|
|
||||||
{
|
|
||||||
sub is_scalar($);
|
|
||||||
my $type = shift;
|
|
||||||
|
|
||||||
return 1 if (ref($type) eq "HASH" and
|
|
||||||
($type->{TYPE} eq "SCALAR" or $type->{TYPE} eq "ENUM" or
|
|
||||||
$type->{TYPE} eq "BITMAP"));
|
|
||||||
|
|
||||||
if (my $dt = getType($type)) {
|
|
||||||
return is_scalar($dt->{DATA}) if ($dt->{TYPE} eq "TYPEDEF");
|
|
||||||
return 1 if ($dt->{TYPE} eq "SCALAR" or $dt->{TYPE} eq "ENUM" or
|
|
||||||
$dt->{TYPE} eq "BITMAP");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub is_fixed_size_scalar($)
|
|
||||||
{
|
|
||||||
my $name = shift;
|
|
||||||
|
|
||||||
return 0 unless is_scalar($name);
|
|
||||||
return 0 if (grep(/^$name$/, @non_fixed_size_scalars));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub scalar_is_reference($)
|
|
||||||
{
|
|
||||||
my $name = shift;
|
|
||||||
|
|
||||||
return 1 if (grep(/^$name$/, @reference_scalars));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub RegisterScalars()
|
|
||||||
{
|
|
||||||
foreach (keys %scalars) {
|
|
||||||
addType({
|
|
||||||
NAME => $_,
|
|
||||||
TYPE => "TYPEDEF",
|
|
||||||
BASEFILE => "<builtin>",
|
|
||||||
DATA => {
|
|
||||||
TYPE => "SCALAR",
|
|
||||||
NAME => $_
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub enum_type_fn($)
|
|
||||||
{
|
|
||||||
my $enum = shift;
|
|
||||||
$enum->{TYPE} eq "ENUM" or die("not an enum");
|
|
||||||
|
|
||||||
# for typedef enum { } we need to check $enum->{PARENT}
|
|
||||||
if (has_property($enum, "enum8bit")) {
|
|
||||||
return "uint8";
|
|
||||||
} elsif (has_property($enum, "enum16bit")) {
|
|
||||||
return "uint16";
|
|
||||||
} elsif (has_property($enum, "v1_enum")) {
|
|
||||||
return "uint32";
|
|
||||||
} elsif (has_property($enum->{PARENT}, "enum8bit")) {
|
|
||||||
return "uint8";
|
|
||||||
} elsif (has_property($enum->{PARENT}, "enum16bit")) {
|
|
||||||
return "uint16";
|
|
||||||
} elsif (has_property($enum->{PARENT}, "v1_enum")) {
|
|
||||||
return "uint32";
|
|
||||||
}
|
|
||||||
return "uint1632";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub bitmap_type_fn($)
|
|
||||||
{
|
|
||||||
my $bitmap = shift;
|
|
||||||
|
|
||||||
$bitmap->{TYPE} eq "BITMAP" or die("not a bitmap");
|
|
||||||
|
|
||||||
if (has_property($bitmap, "bitmap8bit")) {
|
|
||||||
return "uint8";
|
|
||||||
} elsif (has_property($bitmap, "bitmap16bit")) {
|
|
||||||
return "uint16";
|
|
||||||
} elsif (has_property($bitmap, "bitmap64bit")) {
|
|
||||||
return "hyper";
|
|
||||||
}
|
|
||||||
return "uint32";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub typeHasBody($)
|
|
||||||
{
|
|
||||||
sub typeHasBody($);
|
|
||||||
my ($e) = @_;
|
|
||||||
|
|
||||||
if ($e->{TYPE} eq "TYPEDEF") {
|
|
||||||
return 0 unless(defined($e->{DATA}));
|
|
||||||
return typeHasBody($e->{DATA});
|
|
||||||
}
|
|
||||||
|
|
||||||
return defined($e->{ELEMENTS});
|
|
||||||
}
|
|
||||||
|
|
||||||
sub mapType($$)
|
|
||||||
{
|
|
||||||
sub mapType($$);
|
|
||||||
my ($t, $n) = @_;
|
|
||||||
|
|
||||||
return mapType($t->{DATA}, $n) if ($t->{TYPE} eq "TYPEDEF");
|
|
||||||
return mapScalarType($n) if ($t->{TYPE} eq "SCALAR");
|
|
||||||
return "enum $n" if ($t->{TYPE} eq "ENUM");
|
|
||||||
return "struct $n" if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "INTERFACE");
|
|
||||||
return "union $n" if ($t->{TYPE} eq "UNION");
|
|
||||||
return mapScalarType(bitmap_type_fn($t)) if ($t->{TYPE} eq "BITMAP");
|
|
||||||
return "struct $n" if ($t->{TYPE} eq "PIPE");
|
|
||||||
die("Unknown type $t->{TYPE}");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub mapTypeName($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
return "void" unless defined($t);
|
|
||||||
my $dt;
|
|
||||||
$t = expandAlias($t);
|
|
||||||
|
|
||||||
if ($dt = getType($t)) {
|
|
||||||
return mapType($dt, $dt->{NAME});
|
|
||||||
} elsif (ref($t) eq "HASH" and defined($t->{NAME})) {
|
|
||||||
return mapType($t, $t->{NAME});
|
|
||||||
} else {
|
|
||||||
# Best guess
|
|
||||||
return "struct $t";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sub LoadIdl($;$)
|
|
||||||
{
|
|
||||||
my $idl = shift;
|
|
||||||
my $basename = shift;
|
|
||||||
|
|
||||||
foreach my $x (@{$idl}) {
|
|
||||||
next if $x->{TYPE} ne "INTERFACE";
|
|
||||||
|
|
||||||
# DCOM interfaces can be types as well
|
|
||||||
addType({
|
|
||||||
NAME => $x->{NAME},
|
|
||||||
TYPE => "TYPEDEF",
|
|
||||||
DATA => $x,
|
|
||||||
BASEFILE => $basename,
|
|
||||||
}) if (has_property($x, "object"));
|
|
||||||
|
|
||||||
foreach my $y (@{$x->{DATA}}) {
|
|
||||||
if ($y->{TYPE} eq "TYPEDEF"
|
|
||||||
or $y->{TYPE} eq "UNION"
|
|
||||||
or $y->{TYPE} eq "STRUCT"
|
|
||||||
or $y->{TYPE} eq "ENUM"
|
|
||||||
or $y->{TYPE} eq "BITMAP"
|
|
||||||
or $y->{TYPE} eq "PIPE") {
|
|
||||||
$y->{BASEFILE} = $basename;
|
|
||||||
addType($y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub GenerateTypeLib()
|
|
||||||
{
|
|
||||||
return Parse::Pidl::Util::MyDumper(\%types);
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterScalars();
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,197 +0,0 @@
|
||||||
###################################################
|
|
||||||
# utility functions to support pidl
|
|
||||||
# Copyright tridge@samba.org 2000
|
|
||||||
# released under the GNU GPL
|
|
||||||
package Parse::Pidl::Util;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT = qw(has_property property_matches ParseExpr ParseExprExt is_constant make_str unmake_str print_uuid MyDumper genpad);
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Parse::Pidl::Expr;
|
|
||||||
use Parse::Pidl qw(error);
|
|
||||||
|
|
||||||
=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;
|
|
||||||
$Data::Dumper::Sortkeys = 1;
|
|
||||||
my $s = shift;
|
|
||||||
return Data::Dumper::Dumper($s);
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<has_property>
|
|
||||||
see if a pidl property list contains a given property
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub has_property($$)
|
|
||||||
{
|
|
||||||
my($e, $p) = @_;
|
|
||||||
|
|
||||||
return undef if (not defined($e->{PROPERTIES}));
|
|
||||||
|
|
||||||
return $e->{PROPERTIES}->{$p};
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<property_matches>
|
|
||||||
see if a pidl property matches a value
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub property_matches($$$)
|
|
||||||
{
|
|
||||||
my($e,$p,$v) = @_;
|
|
||||||
|
|
||||||
if (!defined has_property($e, $p)) {
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($e->{PROPERTIES}->{$p} =~ /$v/) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<is_constant>
|
|
||||||
return 1 if the string is a C constant
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub is_constant($)
|
|
||||||
{
|
|
||||||
my $s = shift;
|
|
||||||
return 1 if ($s =~ /^\d+$/);
|
|
||||||
return 1 if ($s =~ /^0x[0-9A-Fa-f]+$/);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<make_str>
|
|
||||||
return a "" quoted string, unless already quoted
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub make_str($)
|
|
||||||
{
|
|
||||||
my $str = shift;
|
|
||||||
if (substr($str, 0, 1) eq "\"") {
|
|
||||||
return $str;
|
|
||||||
}
|
|
||||||
return "\"$str\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<unmake_str>
|
|
||||||
unquote a "" quoted string
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub unmake_str($)
|
|
||||||
{
|
|
||||||
my $str = shift;
|
|
||||||
|
|
||||||
$str =~ s/^\"(.*)\"$/$1/;
|
|
||||||
|
|
||||||
return $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<print_uuid>
|
|
||||||
Print C representation of a UUID.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub print_uuid($)
|
|
||||||
{
|
|
||||||
my ($uuid) = @_;
|
|
||||||
$uuid =~ s/"//g;
|
|
||||||
my ($time_low,$time_mid,$time_hi,$clock_seq,$node) = split /-/, $uuid;
|
|
||||||
return undef if not defined($node);
|
|
||||||
|
|
||||||
my @clock_seq = $clock_seq =~ /(..)/g;
|
|
||||||
my @node = $node =~ /(..)/g;
|
|
||||||
|
|
||||||
return "{0x$time_low,0x$time_mid,0x$time_hi," .
|
|
||||||
"{".join(',', map {"0x$_"} @clock_seq)."}," .
|
|
||||||
"{".join(',', map {"0x$_"} @node)."}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<ParseExpr>
|
|
||||||
Interpret an IDL expression, substituting particular variables.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub ParseExpr($$$)
|
|
||||||
{
|
|
||||||
my($expr, $varlist, $e) = @_;
|
|
||||||
|
|
||||||
my $x = new Parse::Pidl::Expr();
|
|
||||||
|
|
||||||
return $x->Run($expr, sub { my $x = shift; error($e, $x); },
|
|
||||||
# Lookup fn
|
|
||||||
sub { my $x = shift;
|
|
||||||
return($varlist->{$x}) if (defined($varlist->{$x}));
|
|
||||||
return $x;
|
|
||||||
},
|
|
||||||
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) = @_;
|
|
||||||
|
|
||||||
my $x = new Parse::Pidl::Expr();
|
|
||||||
|
|
||||||
return $x->Run($expr, sub { my $x = shift; error($e, $x); },
|
|
||||||
# Lookup fn
|
|
||||||
sub { my $x = shift;
|
|
||||||
return($varlist->{$x}) if (defined($varlist->{$x}));
|
|
||||||
return $x;
|
|
||||||
},
|
|
||||||
$deref, $use);
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<genpad>
|
|
||||||
return an empty string consisting of tabs and spaces suitable for proper indent
|
|
||||||
of C-functions.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub genpad($)
|
|
||||||
{
|
|
||||||
my ($s) = @_;
|
|
||||||
my $nt = int((length($s)+1)/8);
|
|
||||||
my $lt = ($nt*8)-1;
|
|
||||||
my $ns = (length($s)-$lt);
|
|
||||||
return "\t"x($nt)." "x($ns);
|
|
||||||
}
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,509 +0,0 @@
|
||||||
###################################################
|
|
||||||
# parse an Wireshark conformance file
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
Parse::Pidl::Wireshark::Conformance - Conformance file parser for Wireshark
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
This module supports parsing Wireshark conformance files (*.cnf).
|
|
||||||
|
|
||||||
=head1 FILE FORMAT
|
|
||||||
|
|
||||||
Pidl needs additional data for Wireshark output. This data is read from
|
|
||||||
so-called conformance files. This section describes the format of these
|
|
||||||
files.
|
|
||||||
|
|
||||||
Conformance files are simple text files with a single command on each line.
|
|
||||||
Empty lines and lines starting with a '#' character are ignored.
|
|
||||||
Arguments to commands are separated by spaces.
|
|
||||||
|
|
||||||
The following commands are currently supported:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item I<TYPE> name dissector ft_type base_type mask valsstring alignment
|
|
||||||
|
|
||||||
Register new data type with specified name, what dissector function to call
|
|
||||||
and what properties to give header fields for elements of this type.
|
|
||||||
|
|
||||||
=item I<NOEMIT> type
|
|
||||||
|
|
||||||
Suppress emitting a dissect_type function for the specified type
|
|
||||||
|
|
||||||
=item I<PARAM_VALUE> type param
|
|
||||||
|
|
||||||
Set parameter to specify to dissector function for given type.
|
|
||||||
|
|
||||||
=item I<HF_FIELD> hf title filter ft_type base_type valsstring mask description
|
|
||||||
|
|
||||||
Generate a custom header field with specified properties.
|
|
||||||
|
|
||||||
=item I<HF_RENAME> old_hf_name new_hf_name
|
|
||||||
|
|
||||||
Force the use of new_hf_name when the parser generator was going to
|
|
||||||
use old_hf_name.
|
|
||||||
|
|
||||||
This can be used in conjunction with HF_FIELD in order to make more than
|
|
||||||
one element use the same filter name.
|
|
||||||
|
|
||||||
=item I<ETT_FIELD> ett
|
|
||||||
|
|
||||||
Register a custom ett field
|
|
||||||
|
|
||||||
=item I<STRIP_PREFIX> prefix
|
|
||||||
|
|
||||||
Remove the specified prefix from all function names (if present).
|
|
||||||
|
|
||||||
=item I<PROTOCOL> longname shortname filtername
|
|
||||||
|
|
||||||
Change the short-, long- and filter-name for the current interface in
|
|
||||||
Wireshark.
|
|
||||||
|
|
||||||
=item I<FIELD_DESCRIPTION> field desc
|
|
||||||
|
|
||||||
Change description for the specified header field. `field' is the hf name of the field.
|
|
||||||
|
|
||||||
=item I<IMPORT> dissector code...
|
|
||||||
|
|
||||||
Code to insert when generating the specified dissector. @HF@ and
|
|
||||||
@PARAM@ will be substituted.
|
|
||||||
|
|
||||||
=item I<INCLUDE> filename
|
|
||||||
|
|
||||||
Include conformance data from the specified filename in the dissector.
|
|
||||||
|
|
||||||
=item I<TFS> hf_name "true string" "false string"
|
|
||||||
|
|
||||||
Override the text shown when a bitmap boolean value is enabled or disabled.
|
|
||||||
|
|
||||||
=item I<MANUAL> fn_name
|
|
||||||
|
|
||||||
Force pidl to not generate a particular function but allow the user
|
|
||||||
to write a function manually. This can be used to remove the function
|
|
||||||
for only one level for a particular element rather than all the functions and
|
|
||||||
ett/hf variables for a particular element as the NOEMIT command does.
|
|
||||||
|
|
||||||
=item I<CODE START>/I<CODE END>
|
|
||||||
Begin and end a section of code to be put directly into the generated
|
|
||||||
source file for the dissector.
|
|
||||||
|
|
||||||
=item I<HEADER START>/I<HEADER END>
|
|
||||||
Begin and end a section of code to be put directly into the generated
|
|
||||||
header file for the dissector.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 EXAMPLE
|
|
||||||
|
|
||||||
INFO_KEY OpenKey.Ke
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
package Parse::Pidl::Wireshark::Conformance;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(ReadConformance ReadConformanceFH valid_ft_type valid_base_type);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Parse::Pidl qw(fatal warning error);
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
use Parse::Pidl::Typelist qw(addType);
|
|
||||||
|
|
||||||
sub handle_type($$$$$$$$$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$name,$dissectorname,$ft_type,$base_type,$mask,$valsstring,$alignment) = @_;
|
|
||||||
|
|
||||||
unless(defined($alignment)) {
|
|
||||||
error($pos, "incomplete TYPE command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unless ($dissectorname =~ /.*dissect_.*/) {
|
|
||||||
warning($pos, "dissector name does not contain `dissect'");
|
|
||||||
}
|
|
||||||
|
|
||||||
unless(valid_ft_type($ft_type)) {
|
|
||||||
warning($pos, "invalid FT_TYPE `$ft_type'");
|
|
||||||
}
|
|
||||||
|
|
||||||
unless (valid_base_type($base_type)) {
|
|
||||||
warning($pos, "invalid BASE_TYPE `$base_type'");
|
|
||||||
}
|
|
||||||
|
|
||||||
$dissectorname =~ s/^\"(.*)\"$/$1/g;
|
|
||||||
|
|
||||||
if (not ($dissectorname =~ /;$/)) {
|
|
||||||
warning($pos, "missing semicolon");
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{types}->{$name} = {
|
|
||||||
NAME => $name,
|
|
||||||
POS => $pos,
|
|
||||||
USED => 0,
|
|
||||||
DISSECTOR_NAME => $dissectorname,
|
|
||||||
FT_TYPE => $ft_type,
|
|
||||||
BASE_TYPE => $base_type,
|
|
||||||
MASK => $mask,
|
|
||||||
VALSSTRING => $valsstring,
|
|
||||||
ALIGNMENT => $alignment
|
|
||||||
};
|
|
||||||
|
|
||||||
addType({
|
|
||||||
NAME => $name,
|
|
||||||
TYPE => "CONFORMANCE",
|
|
||||||
BASEFILE => "conformance file",
|
|
||||||
DATA => {
|
|
||||||
NAME => $name,
|
|
||||||
TYPE => "CONFORMANCE",
|
|
||||||
ALIGN => $alignment
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_tfs($$$$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$hf,$trues,$falses) = @_;
|
|
||||||
|
|
||||||
unless(defined($falses)) {
|
|
||||||
error($pos, "incomplete TFS command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{tfs}->{$hf} = {
|
|
||||||
TRUE_STRING => $trues,
|
|
||||||
FALSE_STRING => $falses
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_hf_rename($$$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$old,$new) = @_;
|
|
||||||
|
|
||||||
unless(defined($new)) {
|
|
||||||
warning($pos, "incomplete HF_RENAME command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{hf_renames}->{$old} = {
|
|
||||||
OLDNAME => $old,
|
|
||||||
NEWNAME => $new,
|
|
||||||
POS => $pos,
|
|
||||||
USED => 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_param_value($$$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$dissector_name,$value) = @_;
|
|
||||||
|
|
||||||
unless(defined($value)) {
|
|
||||||
error($pos, "incomplete PARAM_VALUE command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{dissectorparams}->{$dissector_name} = {
|
|
||||||
DISSECTOR => $dissector_name,
|
|
||||||
PARAM => $value,
|
|
||||||
POS => $pos,
|
|
||||||
USED => 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub valid_base_type($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
return 0 unless($t =~ /^BASE_.*/);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub valid_ft_type($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
return 0 unless($t =~ /^FT_.*/);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_hf_field($$$$$$$$$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$index,$name,$filter,$ft_type,$base_type,$valsstring,$mask,$blurb) = @_;
|
|
||||||
|
|
||||||
unless(defined($blurb)) {
|
|
||||||
error($pos, "incomplete HF_FIELD command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unless(valid_ft_type($ft_type)) {
|
|
||||||
warning($pos, "invalid FT_TYPE `$ft_type'");
|
|
||||||
}
|
|
||||||
|
|
||||||
unless(valid_base_type($base_type)) {
|
|
||||||
warning($pos, "invalid BASE_TYPE `$base_type'");
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{header_fields}->{$index} = {
|
|
||||||
INDEX => $index,
|
|
||||||
POS => $pos,
|
|
||||||
USED => 0,
|
|
||||||
NAME => $name,
|
|
||||||
FILTER => $filter,
|
|
||||||
FT_TYPE => $ft_type,
|
|
||||||
BASE_TYPE => $base_type,
|
|
||||||
VALSSTRING => $valsstring,
|
|
||||||
MASK => $mask,
|
|
||||||
BLURB => $blurb
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_strip_prefix($$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$x) = @_;
|
|
||||||
|
|
||||||
push (@{$data->{strip_prefixes}}, $x);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_noemit($$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$type) = @_;
|
|
||||||
|
|
||||||
if (defined($type)) {
|
|
||||||
$data->{noemit}->{$type} = 1;
|
|
||||||
} else {
|
|
||||||
$data->{noemit_dissector} = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_manual($$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$fn) = @_;
|
|
||||||
|
|
||||||
unless(defined($fn)) {
|
|
||||||
warning($pos, "incomplete MANUAL command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{manual}->{$fn} = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_protocol($$$$$$)
|
|
||||||
{
|
|
||||||
my ($pos, $data, $name, $longname, $shortname, $filtername) = @_;
|
|
||||||
|
|
||||||
$data->{protocols}->{$name} = {
|
|
||||||
LONGNAME => $longname,
|
|
||||||
SHORTNAME => $shortname,
|
|
||||||
FILTERNAME => $filtername
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
USED => 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_import
|
|
||||||
{
|
|
||||||
my $pos = shift @_;
|
|
||||||
my $data = shift @_;
|
|
||||||
my $dissectorname = shift @_;
|
|
||||||
|
|
||||||
unless(defined($dissectorname)) {
|
|
||||||
error($pos, "no dissectorname specified");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{imports}->{$dissectorname} = {
|
|
||||||
NAME => $dissectorname,
|
|
||||||
DATA => join(' ', @_),
|
|
||||||
USED => 0,
|
|
||||||
POS => $pos
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_ett_field
|
|
||||||
{
|
|
||||||
my $pos = shift @_;
|
|
||||||
my $data = shift @_;
|
|
||||||
my $ett = shift @_;
|
|
||||||
|
|
||||||
unless(defined($ett)) {
|
|
||||||
error($pos, "incomplete ETT_FIELD command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
push (@{$data->{ett}}, $ett);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_include
|
|
||||||
{
|
|
||||||
my $pos = shift @_;
|
|
||||||
my $data = shift @_;
|
|
||||||
my $fn = shift @_;
|
|
||||||
|
|
||||||
unless(defined($fn)) {
|
|
||||||
error($pos, "incomplete INCLUDE command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadConformance($fn, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
my %field_handlers = (
|
|
||||||
TYPE => \&handle_type,
|
|
||||||
NOEMIT => \&handle_noemit,
|
|
||||||
MANUAL => \&handle_manual,
|
|
||||||
PARAM_VALUE => \&handle_param_value,
|
|
||||||
HF_FIELD => \&handle_hf_field,
|
|
||||||
HF_RENAME => \&handle_hf_rename,
|
|
||||||
ETT_FIELD => \&handle_ett_field,
|
|
||||||
TFS => \&handle_tfs,
|
|
||||||
STRIP_PREFIX => \&handle_strip_prefix,
|
|
||||||
PROTOCOL => \&handle_protocol,
|
|
||||||
FIELD_DESCRIPTION => \&handle_fielddescription,
|
|
||||||
IMPORT => \&handle_import,
|
|
||||||
INCLUDE => \&handle_include
|
|
||||||
);
|
|
||||||
|
|
||||||
sub ReadConformance($$)
|
|
||||||
{
|
|
||||||
my ($f,$data) = @_;
|
|
||||||
my $ret;
|
|
||||||
|
|
||||||
open(IN,"<$f") or return undef;
|
|
||||||
|
|
||||||
$ret = ReadConformanceFH(*IN, $data, $f);
|
|
||||||
|
|
||||||
close(IN);
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ReadConformanceFH($$$)
|
|
||||||
{
|
|
||||||
my ($fh,$data,$f) = @_;
|
|
||||||
|
|
||||||
my $incodeblock = 0;
|
|
||||||
my $inheaderblock = 0;
|
|
||||||
|
|
||||||
my $ln = 0;
|
|
||||||
|
|
||||||
foreach (<$fh>) {
|
|
||||||
$ln++;
|
|
||||||
next if (/^#.*$/);
|
|
||||||
next if (/^$/);
|
|
||||||
|
|
||||||
s/[\r\n]//g;
|
|
||||||
|
|
||||||
if ($_ eq "CODE START") {
|
|
||||||
if ($incodeblock) {
|
|
||||||
warning({ FILE => $f, LINE => $ln },
|
|
||||||
"CODE START inside CODE section");
|
|
||||||
}
|
|
||||||
if ($inheaderblock) {
|
|
||||||
error({ FILE => $f, LINE => $ln },
|
|
||||||
"CODE START inside HEADER section");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
$incodeblock = 1;
|
|
||||||
next;
|
|
||||||
} elsif ($_ eq "CODE END") {
|
|
||||||
if (!$incodeblock) {
|
|
||||||
warning({ FILE => $f, LINE => $ln },
|
|
||||||
"CODE END outside CODE section");
|
|
||||||
}
|
|
||||||
if ($inheaderblock) {
|
|
||||||
error({ FILE => $f, LINE => $ln },
|
|
||||||
"CODE END inside HEADER section");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
$incodeblock = 0;
|
|
||||||
next;
|
|
||||||
} elsif ($incodeblock) {
|
|
||||||
if (exists $data->{override}) {
|
|
||||||
$data->{override}.="$_\n";
|
|
||||||
} else {
|
|
||||||
$data->{override} = "$_\n";
|
|
||||||
}
|
|
||||||
next;
|
|
||||||
} elsif ($_ eq "HEADER START") {
|
|
||||||
if ($inheaderblock) {
|
|
||||||
warning({ FILE => $f, LINE => $ln },
|
|
||||||
"HEADER START inside HEADER section");
|
|
||||||
}
|
|
||||||
if ($incodeblock) {
|
|
||||||
error({ FILE => $f, LINE => $ln },
|
|
||||||
"HEADER START inside CODE section");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
$inheaderblock = 1;
|
|
||||||
next;
|
|
||||||
} elsif ($_ eq "HEADER END") {
|
|
||||||
if (!$inheaderblock) {
|
|
||||||
warning({ FILE => $f, LINE => $ln },
|
|
||||||
"HEADER END outside HEADER section");
|
|
||||||
}
|
|
||||||
if ($incodeblock) {
|
|
||||||
error({ FILE => $f, LINE => $ln },
|
|
||||||
"CODE END inside HEADER section");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
$inheaderblock = 0;
|
|
||||||
next;
|
|
||||||
} elsif ($inheaderblock) {
|
|
||||||
if (exists $data->{header}) {
|
|
||||||
$data->{header}.="$_\n";
|
|
||||||
} else {
|
|
||||||
$data->{header} = "$_\n";
|
|
||||||
}
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
my @fields = /([^ "]+|"[^"]+")/g;
|
|
||||||
|
|
||||||
my $cmd = $fields[0];
|
|
||||||
|
|
||||||
shift @fields;
|
|
||||||
|
|
||||||
my $pos = { FILE => $f, LINE => $ln };
|
|
||||||
|
|
||||||
next unless(defined($cmd));
|
|
||||||
|
|
||||||
if (not defined($field_handlers{$cmd})) {
|
|
||||||
warning($pos, "Unknown command `$cmd'");
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
$field_handlers{$cmd}($pos, $data, @fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($incodeblock) {
|
|
||||||
warning({ FILE => $f, LINE => $ln },
|
|
||||||
"Expecting CODE END");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,471 +0,0 @@
|
||||||
#
|
|
||||||
# Module Parse::Yapp::Driver
|
|
||||||
#
|
|
||||||
# This module is part of the Parse::Yapp package available on your
|
|
||||||
# nearest CPAN
|
|
||||||
#
|
|
||||||
# Any use of this module in a standalone parser make the included
|
|
||||||
# text under the same copyright as the Parse::Yapp module itself.
|
|
||||||
#
|
|
||||||
# This notice should remain unchanged.
|
|
||||||
#
|
|
||||||
# (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved.
|
|
||||||
# (see the pod text in Parse::Yapp module for use and distribution rights)
|
|
||||||
#
|
|
||||||
|
|
||||||
package Parse::Yapp::Driver;
|
|
||||||
|
|
||||||
require 5.004;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw ( $VERSION $COMPATIBLE $FILENAME );
|
|
||||||
|
|
||||||
$VERSION = '1.05';
|
|
||||||
$COMPATIBLE = '0.07';
|
|
||||||
$FILENAME=__FILE__;
|
|
||||||
|
|
||||||
use Carp;
|
|
||||||
|
|
||||||
#Known parameters, all starting with YY (leading YY will be discarded)
|
|
||||||
my(%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '',
|
|
||||||
YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => '');
|
|
||||||
#Mandatory parameters
|
|
||||||
my(@params)=('LEX','RULES','STATES');
|
|
||||||
|
|
||||||
sub new {
|
|
||||||
my($class)=shift;
|
|
||||||
my($errst,$nberr,$token,$value,$check,$dotpos);
|
|
||||||
my($self)={ ERROR => \&_Error,
|
|
||||||
ERRST => \$errst,
|
|
||||||
NBERR => \$nberr,
|
|
||||||
TOKEN => \$token,
|
|
||||||
VALUE => \$value,
|
|
||||||
DOTPOS => \$dotpos,
|
|
||||||
STACK => [],
|
|
||||||
DEBUG => 0,
|
|
||||||
CHECK => \$check };
|
|
||||||
|
|
||||||
_CheckParams( [], \%params, \@_, $self );
|
|
||||||
|
|
||||||
exists($$self{VERSION})
|
|
||||||
and $$self{VERSION} < $COMPATIBLE
|
|
||||||
and croak "Yapp driver version $VERSION ".
|
|
||||||
"incompatible with version $$self{VERSION}:\n".
|
|
||||||
"Please recompile parser module.";
|
|
||||||
|
|
||||||
ref($class)
|
|
||||||
and $class=ref($class);
|
|
||||||
|
|
||||||
bless($self,$class);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYParse {
|
|
||||||
my($self)=shift;
|
|
||||||
my($retval);
|
|
||||||
|
|
||||||
_CheckParams( \@params, \%params, \@_, $self );
|
|
||||||
|
|
||||||
if($$self{DEBUG}) {
|
|
||||||
_DBLoad();
|
|
||||||
$retval = eval '$self->_DBParse()';#Do not create stab entry on compile
|
|
||||||
$@ and die $@;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$retval = $self->_Parse();
|
|
||||||
}
|
|
||||||
$retval
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYData {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
exists($$self{USER})
|
|
||||||
or $$self{USER}={};
|
|
||||||
|
|
||||||
$$self{USER};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYErrok {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{ERRST}}=0;
|
|
||||||
undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYNberr {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{NBERR}};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYRecovering {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{ERRST}} != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYAbort {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{CHECK}}='ABORT';
|
|
||||||
undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYAccept {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{CHECK}}='ACCEPT';
|
|
||||||
undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYError {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{CHECK}}='ERROR';
|
|
||||||
undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYSemval {
|
|
||||||
my($self)=shift;
|
|
||||||
my($index)= $_[0] - ${$$self{DOTPOS}} - 1;
|
|
||||||
|
|
||||||
$index < 0
|
|
||||||
and -$index <= @{$$self{STACK}}
|
|
||||||
and return $$self{STACK}[$index][1];
|
|
||||||
|
|
||||||
undef; #Invalid index
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYCurtok {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
@_
|
|
||||||
and ${$$self{TOKEN}}=$_[0];
|
|
||||||
${$$self{TOKEN}};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYCurval {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
@_
|
|
||||||
and ${$$self{VALUE}}=$_[0];
|
|
||||||
${$$self{VALUE}};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYExpect {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
keys %{$self->{STATES}[$self->{STACK}[-1][0]]{ACTIONS}}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYLexer {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
$$self{LEX};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Private stuff #
|
|
||||||
#################
|
|
||||||
|
|
||||||
|
|
||||||
sub _CheckParams {
|
|
||||||
my($mandatory,$checklist,$inarray,$outhash)=@_;
|
|
||||||
my($prm,$value);
|
|
||||||
my($prmlst)={};
|
|
||||||
|
|
||||||
while(($prm,$value)=splice(@$inarray,0,2)) {
|
|
||||||
$prm=uc($prm);
|
|
||||||
exists($$checklist{$prm})
|
|
||||||
or croak("Unknow parameter '$prm'");
|
|
||||||
ref($value) eq $$checklist{$prm}
|
|
||||||
or croak("Invalid value for parameter '$prm'");
|
|
||||||
$prm=unpack('@2A*',$prm);
|
|
||||||
$$outhash{$prm}=$value;
|
|
||||||
}
|
|
||||||
for (@$mandatory) {
|
|
||||||
exists($$outhash{$_})
|
|
||||||
or croak("Missing mandatory parameter '".lc($_)."'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _Error {
|
|
||||||
print "Parse error.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _DBLoad {
|
|
||||||
{
|
|
||||||
no strict 'refs';
|
|
||||||
|
|
||||||
exists(${__PACKAGE__.'::'}{_DBParse})#Already loaded ?
|
|
||||||
and return;
|
|
||||||
}
|
|
||||||
my($fname)=__FILE__;
|
|
||||||
my(@drv);
|
|
||||||
open(DRV,"<$fname") or die "Report this as a BUG: Cannot open $fname";
|
|
||||||
while(<DRV>) {
|
|
||||||
/^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/
|
|
||||||
and do {
|
|
||||||
s/^#DBG>//;
|
|
||||||
push(@drv,$_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(DRV);
|
|
||||||
|
|
||||||
$drv[0]=~s/_P/_DBP/;
|
|
||||||
eval join('',@drv);
|
|
||||||
}
|
|
||||||
|
|
||||||
#Note that for loading debugging version of the driver,
|
|
||||||
#this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive.
|
|
||||||
#So, DO NOT remove comment at end of sub !!!
|
|
||||||
sub _Parse {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
my($rules,$states,$lex,$error)
|
|
||||||
= @$self{ 'RULES', 'STATES', 'LEX', 'ERROR' };
|
|
||||||
my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos)
|
|
||||||
= @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' };
|
|
||||||
|
|
||||||
#DBG> my($debug)=$$self{DEBUG};
|
|
||||||
#DBG> my($dbgerror)=0;
|
|
||||||
|
|
||||||
#DBG> my($ShowCurToken) = sub {
|
|
||||||
#DBG> my($tok)='>';
|
|
||||||
#DBG> for (split('',$$token)) {
|
|
||||||
#DBG> $tok.= (ord($_) < 32 or ord($_) > 126)
|
|
||||||
#DBG> ? sprintf('<%02X>',ord($_))
|
|
||||||
#DBG> : $_;
|
|
||||||
#DBG> }
|
|
||||||
#DBG> $tok.='<';
|
|
||||||
#DBG> };
|
|
||||||
|
|
||||||
$$errstatus=0;
|
|
||||||
$$nberror=0;
|
|
||||||
($$token,$$value)=(undef,undef);
|
|
||||||
@$stack=( [ 0, undef ] );
|
|
||||||
$$check='';
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
my($actions,$act,$stateno);
|
|
||||||
|
|
||||||
$stateno=$$stack[-1][0];
|
|
||||||
$actions=$$states[$stateno];
|
|
||||||
|
|
||||||
#DBG> print STDERR ('-' x 40),"\n";
|
|
||||||
#DBG> $debug & 0x2
|
|
||||||
#DBG> and print STDERR "In state $stateno:\n";
|
|
||||||
#DBG> $debug & 0x08
|
|
||||||
#DBG> and print STDERR "Stack:[".
|
|
||||||
#DBG> join(',',map { $$_[0] } @$stack).
|
|
||||||
#DBG> "]\n";
|
|
||||||
|
|
||||||
|
|
||||||
if (exists($$actions{ACTIONS})) {
|
|
||||||
|
|
||||||
defined($$token)
|
|
||||||
or do {
|
|
||||||
($$token,$$value)=&$lex($self);
|
|
||||||
#DBG> $debug & 0x01
|
|
||||||
#DBG> and print STDERR "Need token. Got ".&$ShowCurToken."\n";
|
|
||||||
};
|
|
||||||
|
|
||||||
$act= exists($$actions{ACTIONS}{$$token})
|
|
||||||
? $$actions{ACTIONS}{$$token}
|
|
||||||
: exists($$actions{DEFAULT})
|
|
||||||
? $$actions{DEFAULT}
|
|
||||||
: undef;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$act=$$actions{DEFAULT};
|
|
||||||
#DBG> $debug & 0x01
|
|
||||||
#DBG> and print STDERR "Don't need token.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
defined($act)
|
|
||||||
and do {
|
|
||||||
|
|
||||||
$act > 0
|
|
||||||
and do { #shift
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR "Shift and go to state $act.\n";
|
|
||||||
|
|
||||||
$$errstatus
|
|
||||||
and do {
|
|
||||||
--$$errstatus;
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and $dbgerror
|
|
||||||
#DBG> and $$errstatus == 0
|
|
||||||
#DBG> and do {
|
|
||||||
#DBG> print STDERR "**End of Error recovery.\n";
|
|
||||||
#DBG> $dbgerror=0;
|
|
||||||
#DBG> };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
push(@$stack,[ $act, $$value ]);
|
|
||||||
|
|
||||||
$$token ne '' #Don't eat the eof
|
|
||||||
and $$token=$$value=undef;
|
|
||||||
next;
|
|
||||||
};
|
|
||||||
|
|
||||||
#reduce
|
|
||||||
my($lhs,$len,$code,@sempar,$semval);
|
|
||||||
($lhs,$len,$code)=@{$$rules[-$act]};
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and $act
|
|
||||||
#DBG> and print STDERR "Reduce using rule ".-$act." ($lhs,$len): ";
|
|
||||||
|
|
||||||
$act
|
|
||||||
or $self->YYAccept();
|
|
||||||
|
|
||||||
$$dotpos=$len;
|
|
||||||
|
|
||||||
unpack('A1',$lhs) eq '@' #In line rule
|
|
||||||
and do {
|
|
||||||
$lhs =~ /^\@[0-9]+\-([0-9]+)$/
|
|
||||||
or die "In line rule name '$lhs' ill formed: ".
|
|
||||||
"report it as a BUG.\n";
|
|
||||||
$$dotpos = $1;
|
|
||||||
};
|
|
||||||
|
|
||||||
@sempar = $$dotpos
|
|
||||||
? map { $$_[1] } @$stack[ -$$dotpos .. -1 ]
|
|
||||||
: ();
|
|
||||||
|
|
||||||
$semval = $code ? &$code( $self, @sempar )
|
|
||||||
: @sempar ? $sempar[0] : undef;
|
|
||||||
|
|
||||||
splice(@$stack,-$len,$len);
|
|
||||||
|
|
||||||
$$check eq 'ACCEPT'
|
|
||||||
and do {
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR "Accept.\n";
|
|
||||||
|
|
||||||
return($semval);
|
|
||||||
};
|
|
||||||
|
|
||||||
$$check eq 'ABORT'
|
|
||||||
and do {
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR "Abort.\n";
|
|
||||||
|
|
||||||
return(undef);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR "Back to state $$stack[-1][0], then ";
|
|
||||||
|
|
||||||
$$check eq 'ERROR'
|
|
||||||
or do {
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR
|
|
||||||
#DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n";
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and $dbgerror
|
|
||||||
#DBG> and $$errstatus == 0
|
|
||||||
#DBG> and do {
|
|
||||||
#DBG> print STDERR "**End of Error recovery.\n";
|
|
||||||
#DBG> $dbgerror=0;
|
|
||||||
#DBG> };
|
|
||||||
|
|
||||||
push(@$stack,
|
|
||||||
[ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval ]);
|
|
||||||
$$check='';
|
|
||||||
next;
|
|
||||||
};
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR "Forced Error recovery.\n";
|
|
||||||
|
|
||||||
$$check='';
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#Error
|
|
||||||
$$errstatus
|
|
||||||
or do {
|
|
||||||
|
|
||||||
$$errstatus = 1;
|
|
||||||
&$error($self);
|
|
||||||
$$errstatus # if 0, then YYErrok has been called
|
|
||||||
or next; # so continue parsing
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and do {
|
|
||||||
#DBG> print STDERR "**Entering Error recovery.\n";
|
|
||||||
#DBG> ++$dbgerror;
|
|
||||||
#DBG> };
|
|
||||||
|
|
||||||
++$$nberror;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
$$errstatus == 3 #The next token is not valid: discard it
|
|
||||||
and do {
|
|
||||||
$$token eq '' # End of input: no hope
|
|
||||||
and do {
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and print STDERR "**At eof: aborting.\n";
|
|
||||||
return(undef);
|
|
||||||
};
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and print STDERR "**Dicard invalid token ".&$ShowCurToken.".\n";
|
|
||||||
|
|
||||||
$$token=$$value=undef;
|
|
||||||
};
|
|
||||||
|
|
||||||
$$errstatus=3;
|
|
||||||
|
|
||||||
while( @$stack
|
|
||||||
and ( not exists($$states[$$stack[-1][0]]{ACTIONS})
|
|
||||||
or not exists($$states[$$stack[-1][0]]{ACTIONS}{error})
|
|
||||||
or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) {
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and print STDERR "**Pop state $$stack[-1][0].\n";
|
|
||||||
|
|
||||||
pop(@$stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
@$stack
|
|
||||||
or do {
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and print STDERR "**No state left on stack: aborting.\n";
|
|
||||||
|
|
||||||
return(undef);
|
|
||||||
};
|
|
||||||
|
|
||||||
#shift the error token
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and print STDERR "**Shift \$error token and go to state ".
|
|
||||||
#DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}.
|
|
||||||
#DBG> ".\n";
|
|
||||||
|
|
||||||
push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef ]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#never reached
|
|
||||||
croak("Error in driver logic. Please, report it as a BUG");
|
|
||||||
|
|
||||||
}#_Parse
|
|
||||||
#DO NOT remove comment
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
# install the pidl modules
|
|
||||||
bld.INSTALL_FILES(bld.env.PERL_LIB_INSTALL_DIR,
|
|
||||||
'''
|
|
||||||
Parse/Pidl.pm
|
|
||||||
Parse/Pidl/Samba4.pm
|
|
||||||
Parse/Pidl/CUtil.pm
|
|
||||||
Parse/Pidl/Expr.pm
|
|
||||||
Parse/Pidl/Wireshark/Conformance.pm
|
|
||||||
Parse/Pidl/Wireshark/NDR.pm
|
|
||||||
Parse/Pidl/ODL.pm
|
|
||||||
Parse/Pidl/Dump.pm
|
|
||||||
Parse/Pidl/Util.pm
|
|
||||||
Parse/Pidl/Samba4/Header.pm
|
|
||||||
Parse/Pidl/Samba4/COM/Header.pm
|
|
||||||
Parse/Pidl/Samba4/COM/Proxy.pm
|
|
||||||
Parse/Pidl/Samba4/COM/Stub.pm
|
|
||||||
Parse/Pidl/Samba4/TDR.pm
|
|
||||||
Parse/Pidl/Samba4/NDR/Server.pm
|
|
||||||
Parse/Pidl/Samba4/NDR/Client.pm
|
|
||||||
Parse/Pidl/Samba4/NDR/Parser.pm
|
|
||||||
Parse/Pidl/Samba4/Python.pm
|
|
||||||
Parse/Pidl/Samba4/Template.pm
|
|
||||||
Parse/Pidl/IDL.pm
|
|
||||||
Parse/Pidl/Typelist.pm
|
|
||||||
Parse/Pidl/Samba3/ClientNDR.pm
|
|
||||||
Parse/Pidl/Samba3/ServerNDR.pm
|
|
||||||
Parse/Pidl/Compat.pm
|
|
||||||
Parse/Pidl/NDR.pm
|
|
||||||
''',
|
|
||||||
flat=False)
|
|
||||||
|
|
||||||
if not bld.CONFIG_SET('USING_SYSTEM_PARSE_YAPP_DRIVER'):
|
|
||||||
bld.INSTALL_FILES(bld.env.PERL_LIB_INSTALL_DIR,
|
|
||||||
'Parse/Yapp/Driver.pm',
|
|
||||||
flat=False)
|
|
|
@ -1,424 +0,0 @@
|
||||||
.\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32)
|
|
||||||
.\"
|
|
||||||
.\" Standard preamble:
|
|
||||||
.\" ========================================================================
|
|
||||||
.de Sp \" Vertical space (when we can't use .PP)
|
|
||||||
.if t .sp .5v
|
|
||||||
.if n .sp
|
|
||||||
..
|
|
||||||
.de Vb \" Begin verbatim text
|
|
||||||
.ft CW
|
|
||||||
.nf
|
|
||||||
.ne \\$1
|
|
||||||
..
|
|
||||||
.de Ve \" End verbatim text
|
|
||||||
.ft R
|
|
||||||
.fi
|
|
||||||
..
|
|
||||||
.\" Set up some character translations and predefined strings. \*(-- will
|
|
||||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
|
||||||
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
|
|
||||||
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
|
|
||||||
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
|
|
||||||
.\" nothing in troff, for use with C<>.
|
|
||||||
.tr \(*W-
|
|
||||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
|
||||||
.ie n \{\
|
|
||||||
. ds -- \(*W-
|
|
||||||
. ds PI pi
|
|
||||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
|
||||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
|
||||||
. ds L" ""
|
|
||||||
. ds R" ""
|
|
||||||
. ds C` ""
|
|
||||||
. ds C' ""
|
|
||||||
'br\}
|
|
||||||
.el\{\
|
|
||||||
. ds -- \|\(em\|
|
|
||||||
. ds PI \(*p
|
|
||||||
. ds L" ``
|
|
||||||
. ds R" ''
|
|
||||||
. ds C`
|
|
||||||
. ds C'
|
|
||||||
'br\}
|
|
||||||
.\"
|
|
||||||
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
|
||||||
.ie \n(.g .ds Aq \(aq
|
|
||||||
.el .ds Aq '
|
|
||||||
.\"
|
|
||||||
.\" If the F register is >0, we'll generate index entries on stderr for
|
|
||||||
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
|
||||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
|
||||||
.\" output yourself in some meaningful fashion.
|
|
||||||
.\"
|
|
||||||
.\" Avoid warning from groff about undefined register 'F'.
|
|
||||||
.de IX
|
|
||||||
..
|
|
||||||
.if !\nF .nr F 0
|
|
||||||
.if \nF>0 \{\
|
|
||||||
. de IX
|
|
||||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
|
||||||
..
|
|
||||||
. if !\nF==2 \{\
|
|
||||||
. nr % 0
|
|
||||||
. nr F 2
|
|
||||||
. \}
|
|
||||||
.\}
|
|
||||||
.\" ========================================================================
|
|
||||||
.\"
|
|
||||||
.IX Title "PIDL 1p"
|
|
||||||
.TH PIDL 1p "2016-11-15" "perl v5.24.1" "User Contributed Perl Documentation"
|
|
||||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
|
||||||
.\" way too many mistakes in technical documents.
|
|
||||||
.if n .ad l
|
|
||||||
.nh
|
|
||||||
.SH "NAME"
|
|
||||||
pidl \- An IDL compiler written in Perl
|
|
||||||
.SH "SYNOPSIS"
|
|
||||||
.IX Header "SYNOPSIS"
|
|
||||||
pidl \-\-help
|
|
||||||
.PP
|
|
||||||
pidl [\-\-outputdir[=OUTNAME]] [\-\-includedir \s-1DIR...\s0] [\-\-parse\-idl\-tree] [\-\-dump\-idl\-tree] [\-\-dump\-ndr\-tree] [\-\-header[=OUTPUT]] [\-\-python[=OUTPUT]] [\-\-ndr\-parser[=OUTPUT]] [\-\-client] [\-\-server] [\-\-warn\-compat] [\-\-quiet] [\-\-verbose] [\-\-template] [\-\-ws\-parser[=OUTPUT]] [\-\-diff] [\-\-dump\-idl] [\-\-tdr\-parser[=OUTPUT]] [\-\-samba3\-ndr\-client[=OUTPUT]] [\-\-samba3\-ndr\-server[=OUTPUT]] [\-\-typelib=[\s-1OUTPUT\s0]] [<idlfile>.idl]...
|
|
||||||
.SH "DESCRIPTION"
|
|
||||||
.IX Header "DESCRIPTION"
|
|
||||||
pidl is an \s-1IDL\s0 compiler written in Perl that aims to be somewhat
|
|
||||||
compatible with the midl compiler. \s-1IDL\s0 is short for
|
|
||||||
\&\*(L"Interface Definition Language\*(R".
|
|
||||||
.PP
|
|
||||||
pidl can generate stubs for \s-1DCE/RPC\s0 server code, \s-1DCE/RPC\s0
|
|
||||||
client code and Wireshark dissectors for \s-1DCE/RPC\s0 traffic.
|
|
||||||
.PP
|
|
||||||
\&\s-1IDL\s0 compilers like pidl take a description
|
|
||||||
of an interface as their input and use it to generate C
|
|
||||||
(though support for other languages may be added later) code that
|
|
||||||
can use these interfaces, pretty print data sent
|
|
||||||
using these interfaces, or even generate Wireshark
|
|
||||||
dissectors that can parse data sent over the
|
|
||||||
wire by these interfaces.
|
|
||||||
.PP
|
|
||||||
pidl takes \s-1IDL\s0 files in the same format as is used by midl,
|
|
||||||
converts it to a .pidl file (which contains pidl's internal representation of the interface) and can then generate whatever output you need.
|
|
||||||
\&.pidl files should be used for debugging purposes only. Write your
|
|
||||||
interface definitions in .idl format.
|
|
||||||
.PP
|
|
||||||
The goal of pidl is to implement a \s-1IDL\s0 compiler that can be used
|
|
||||||
while developing the \s-1RPC\s0 subsystem in Samba (for
|
|
||||||
both marshalling/unmarshalling and debugging purposes).
|
|
||||||
.SH "OPTIONS"
|
|
||||||
.IX Header "OPTIONS"
|
|
||||||
.IP "\fI\-\-help\fR" 4
|
|
||||||
.IX Item "--help"
|
|
||||||
Show list of available options.
|
|
||||||
.IP "\fI\-\-version\fR" 4
|
|
||||||
.IX Item "--version"
|
|
||||||
Show pidl version
|
|
||||||
.IP "\fI\-\-outputdir \s-1OUTNAME\s0\fR" 4
|
|
||||||
.IX Item "--outputdir OUTNAME"
|
|
||||||
Write output files to the specified directory. Defaults to the current
|
|
||||||
directory.
|
|
||||||
.IP "\fI\-\-includedir \s-1DIR\s0\fR" 4
|
|
||||||
.IX Item "--includedir DIR"
|
|
||||||
Add \s-1DIR\s0 to the search path used by the preprocessor. This option can be
|
|
||||||
specified multiple times.
|
|
||||||
.IP "\fI\-\-parse\-idl\-tree\fR" 4
|
|
||||||
.IX Item "--parse-idl-tree"
|
|
||||||
Read internal tree structure from input files rather
|
|
||||||
than assuming they contain \s-1IDL.\s0
|
|
||||||
.IP "\fI\-\-dump\-idl\fR" 4
|
|
||||||
.IX Item "--dump-idl"
|
|
||||||
Generate a new \s-1IDL\s0 file. File will be named \s-1OUTNAME\s0.idl.
|
|
||||||
.IP "\fI\-\-header\fR" 4
|
|
||||||
.IX Item "--header"
|
|
||||||
Generate a C header file for the specified interface. Filename defaults to \s-1OUTNAME\s0.h.
|
|
||||||
.IP "\fI\-\-ndr\-parser\fR" 4
|
|
||||||
.IX Item "--ndr-parser"
|
|
||||||
Generate a C file and C header containing \s-1NDR\s0 parsers. The filename for
|
|
||||||
the parser defaults to ndr_OUTNAME.c. The header filename will be the
|
|
||||||
parser filename with the extension changed from .c to .h.
|
|
||||||
.IP "\fI\-\-tdr\-parser\fR" 4
|
|
||||||
.IX Item "--tdr-parser"
|
|
||||||
Generate a C file and C header containing \s-1TDR\s0 parsers. The filename for
|
|
||||||
the parser defaults to tdr_OUTNAME.c. The header filename will be the
|
|
||||||
parser filename with the extension changed from .c to .h.
|
|
||||||
.IP "\fI\-\-typelib\fR" 4
|
|
||||||
.IX Item "--typelib"
|
|
||||||
Write type information to the specified file.
|
|
||||||
.IP "\fI\-\-server\fR" 4
|
|
||||||
.IX Item "--server"
|
|
||||||
Generate boilerplate for the \s-1RPC\s0 server that implements
|
|
||||||
the interface. Filename defaults to ndr_OUTNAME_s.c.
|
|
||||||
.IP "\fI\-\-template\fR" 4
|
|
||||||
.IX Item "--template"
|
|
||||||
Generate stubs for a \s-1RPC\s0 server that implements the interface. Output will
|
|
||||||
be written to stdout.
|
|
||||||
.IP "\fI\-\-ws\-parser\fR" 4
|
|
||||||
.IX Item "--ws-parser"
|
|
||||||
Generate an Wireshark dissector (in C) and header file. The dissector filename
|
|
||||||
defaults to packet\-dcerpc\-OUTNAME.c while the header filename defaults to
|
|
||||||
packet\-dcerpc\-OUTNAME.h.
|
|
||||||
.Sp
|
|
||||||
Pidl will read additional data from an Wireshark conformance file if present.
|
|
||||||
Such a file should have the same location as the \s-1IDL\s0 file but with the
|
|
||||||
extension \fIcnf\fR rather than \fIidl\fR. See Parse::Pidl::Wireshark::Conformance
|
|
||||||
for details on the format of this file.
|
|
||||||
.IP "\fI\-\-diff\fR" 4
|
|
||||||
.IX Item "--diff"
|
|
||||||
Parse an \s-1IDL\s0 file, generate a new \s-1IDL\s0 file based on the internal data
|
|
||||||
structures and see if there are any differences with the original \s-1IDL\s0 file.
|
|
||||||
Useful for debugging pidl.
|
|
||||||
.IP "\fI\-\-dump\-idl\-tree\fR" 4
|
|
||||||
.IX Item "--dump-idl-tree"
|
|
||||||
Tell pidl to dump the internal tree representation of an \s-1IDL\s0
|
|
||||||
file the to disk. Useful for debugging pidl.
|
|
||||||
.IP "\fI\-\-dump\-ndr\-tree\fR" 4
|
|
||||||
.IX Item "--dump-ndr-tree"
|
|
||||||
Tell pidl to dump the internal \s-1NDR\s0 information tree it generated
|
|
||||||
from the \s-1IDL\s0 file to disk. Useful for debugging pidl.
|
|
||||||
.IP "\fI\-\-samba3\-ndr\-client\fR" 4
|
|
||||||
.IX Item "--samba3-ndr-client"
|
|
||||||
Generate client calls for Samba3, to be placed in rpc_client/. Instead of
|
|
||||||
calling out to the code in Samba3's rpc_parse/, this will call out to
|
|
||||||
Samba4's \s-1NDR\s0 code instead.
|
|
||||||
.IP "\fI\-\-samba3\-ndr\-server\fR" 4
|
|
||||||
.IX Item "--samba3-ndr-server"
|
|
||||||
Generate server calls for Samba3, to be placed in rpc_server/. Instead of
|
|
||||||
calling out to the code in Samba3's rpc_parse/, this will call out to
|
|
||||||
Samba4's \s-1NDR\s0 code instead.
|
|
||||||
.SH "IDL SYNTAX"
|
|
||||||
.IX Header "IDL SYNTAX"
|
|
||||||
\&\s-1IDL\s0 files are always preprocessed using the C preprocessor.
|
|
||||||
.PP
|
|
||||||
Pretty much everything in an interface (the interface itself, functions,
|
|
||||||
parameters) can have attributes (or properties whatever name you give them).
|
|
||||||
Attributes always prepend the element they apply to and are surrounded
|
|
||||||
by square brackets ([]). Multiple attributes are separated by comma's;
|
|
||||||
arguments to attributes are specified between parentheses.
|
|
||||||
.PP
|
|
||||||
See the section \s-1COMPATIBILITY\s0 for the list of attributes that
|
|
||||||
pidl supports.
|
|
||||||
.PP
|
|
||||||
C\-style comments can be used.
|
|
||||||
.SS "\s-1CONFORMANT ARRAYS\s0"
|
|
||||||
.IX Subsection "CONFORMANT ARRAYS"
|
|
||||||
A conformant array is one with that ends in [*] or []. The strange
|
|
||||||
things about conformant arrays are that they can only appear as the last
|
|
||||||
element of a structure (unless there is a pointer to the conformant array,
|
|
||||||
of course) and the array size appears before the structure itself on the wire.
|
|
||||||
.PP
|
|
||||||
So, in this example:
|
|
||||||
.PP
|
|
||||||
.Vb 6
|
|
||||||
\& typedef struct {
|
|
||||||
\& long abc;
|
|
||||||
\& long count;
|
|
||||||
\& long foo;
|
|
||||||
\& [size_is(count)] long s[*];
|
|
||||||
\& } Struct1;
|
|
||||||
.Ve
|
|
||||||
.PP
|
|
||||||
it appears like this:
|
|
||||||
.PP
|
|
||||||
.Vb 1
|
|
||||||
\& [size_is] [abc] [count] [foo] [s...]
|
|
||||||
.Ve
|
|
||||||
.PP
|
|
||||||
the first [size_is] field is the allocation size of the array, and
|
|
||||||
occurs before the array elements and even before the structure
|
|
||||||
alignment.
|
|
||||||
.PP
|
|
||||||
Note that \fIsize_is()\fR can refer to a constant, but that doesn't change
|
|
||||||
the wire representation. It does not make the array a fixed array.
|
|
||||||
.PP
|
|
||||||
midl.exe would write the above array as the following C header:
|
|
||||||
.PP
|
|
||||||
.Vb 6
|
|
||||||
\& typedef struct {
|
|
||||||
\& long abc;
|
|
||||||
\& long count;
|
|
||||||
\& long foo;
|
|
||||||
\& long s[1];
|
|
||||||
\& } Struct1;
|
|
||||||
.Ve
|
|
||||||
.PP
|
|
||||||
pidl takes a different approach, and writes it like this:
|
|
||||||
.PP
|
|
||||||
.Vb 6
|
|
||||||
\& typedef struct {
|
|
||||||
\& long abc;
|
|
||||||
\& long count;
|
|
||||||
\& long foo;
|
|
||||||
\& long *s;
|
|
||||||
\& } Struct1;
|
|
||||||
.Ve
|
|
||||||
.SS "\s-1VARYING ARRAYS\s0"
|
|
||||||
.IX Subsection "VARYING ARRAYS"
|
|
||||||
A varying array looks like this:
|
|
||||||
.PP
|
|
||||||
.Vb 6
|
|
||||||
\& typedef struct {
|
|
||||||
\& long abc;
|
|
||||||
\& long count;
|
|
||||||
\& long foo;
|
|
||||||
\& [size_is(count)] long *s;
|
|
||||||
\& } Struct1;
|
|
||||||
.Ve
|
|
||||||
.PP
|
|
||||||
This will look like this on the wire:
|
|
||||||
.PP
|
|
||||||
.Vb 1
|
|
||||||
\& [abc] [count] [foo] [PTR_s] [count] [s...]
|
|
||||||
.Ve
|
|
||||||
.SS "\s-1FIXED ARRAYS\s0"
|
|
||||||
.IX Subsection "FIXED ARRAYS"
|
|
||||||
A fixed array looks like this:
|
|
||||||
.PP
|
|
||||||
.Vb 3
|
|
||||||
\& typedef struct {
|
|
||||||
\& long s[10];
|
|
||||||
\& } Struct1;
|
|
||||||
.Ve
|
|
||||||
.PP
|
|
||||||
The \s-1NDR\s0 representation looks just like 10 separate long
|
|
||||||
declarations. The array size is not encoded on the wire.
|
|
||||||
.PP
|
|
||||||
pidl also supports \*(L"inline\*(R" arrays, which are not part of the \s-1IDL/NDR\s0
|
|
||||||
standard. These are declared like this:
|
|
||||||
.PP
|
|
||||||
.Vb 6
|
|
||||||
\& typedef struct {
|
|
||||||
\& uint32 foo;
|
|
||||||
\& uint32 count;
|
|
||||||
\& uint32 bar;
|
|
||||||
\& long s[count];
|
|
||||||
\& } Struct1;
|
|
||||||
.Ve
|
|
||||||
.PP
|
|
||||||
This appears like this:
|
|
||||||
.PP
|
|
||||||
.Vb 1
|
|
||||||
\& [foo] [count] [bar] [s...]
|
|
||||||
.Ve
|
|
||||||
.PP
|
|
||||||
Fixed arrays are an extension added to support some of the strange
|
|
||||||
embedded structures in security descriptors and spoolss.
|
|
||||||
.PP
|
|
||||||
This section is by no means complete. See the OpenGroup and \s-1MSDN
|
|
||||||
\&\s0 documentation for additional information.
|
|
||||||
.SH "COMPATIBILITY WITH MIDL"
|
|
||||||
.IX Header "COMPATIBILITY WITH MIDL"
|
|
||||||
.SS "Missing features in pidl"
|
|
||||||
.IX Subsection "Missing features in pidl"
|
|
||||||
The following \s-1MIDL\s0 features are not (yet) implemented in pidl
|
|
||||||
or are implemented with an incompatible interface:
|
|
||||||
.IP "\(bu" 4
|
|
||||||
Asynchronous communication
|
|
||||||
.IP "\(bu" 4
|
|
||||||
Typelibs (.tlb files)
|
|
||||||
.IP "\(bu" 4
|
|
||||||
Datagram support (ncadg_*)
|
|
||||||
.SS "Supported attributes and statements"
|
|
||||||
.IX Subsection "Supported attributes and statements"
|
|
||||||
in, out, ref, length_is, switch_is, size_is, uuid, case, default, string,
|
|
||||||
unique, ptr, pointer_default, v1_enum, object, helpstring, range, local,
|
|
||||||
call_as, endpoint, switch_type, progid, coclass, iid_is, represent_as,
|
|
||||||
transmit_as, import, include, cpp_quote.
|
|
||||||
.SS "\s-1PIDL\s0 Specific properties"
|
|
||||||
.IX Subsection "PIDL Specific properties"
|
|
||||||
.IP "public" 4
|
|
||||||
.IX Item "public"
|
|
||||||
The [public] property on a structure or union is a pidl extension that
|
|
||||||
forces the generated pull/push functions to be non-static. This allows
|
|
||||||
you to declare types that can be used between modules. If you don't
|
|
||||||
specify [public] then pull/push functions for other than top-level
|
|
||||||
functions are declared static.
|
|
||||||
.IP "noprint" 4
|
|
||||||
.IX Item "noprint"
|
|
||||||
The [noprint] property is a pidl extension that allows you to specify
|
|
||||||
that pidl should not generate a ndr_print_*() function for that
|
|
||||||
structure or union. This is used when you wish to define your own
|
|
||||||
print function that prints a structure in a nicer manner. A good
|
|
||||||
example is the use of [noprint] on dom_sid, which allows the
|
|
||||||
pretty-printing of SIDs.
|
|
||||||
.IP "value" 4
|
|
||||||
.IX Item "value"
|
|
||||||
The [value(expression)] property is a pidl extension that allows you
|
|
||||||
to specify the value of a field when it is put on the wire. This
|
|
||||||
allows fields that always have a well-known value to be automatically
|
|
||||||
filled in, thus making the \s-1API\s0 more programmer friendly. The
|
|
||||||
expression can be any C expression.
|
|
||||||
.IP "relative" 4
|
|
||||||
.IX Item "relative"
|
|
||||||
The [relative] property can be supplied on a pointer. When it is used
|
|
||||||
it declares the pointer as a spoolss style \*(L"relative\*(R" pointer, which
|
|
||||||
means it appears on the wire as an offset within the current
|
|
||||||
encapsulating structure. This is not part of normal \s-1IDL/NDR,\s0 but it is
|
|
||||||
a very useful extension as it avoids the manual encoding of many
|
|
||||||
complex structures.
|
|
||||||
.IP "subcontext(length)" 4
|
|
||||||
.IX Item "subcontext(length)"
|
|
||||||
Specifies that a size of \fIlength\fR
|
|
||||||
bytes should be read, followed by a blob of that size,
|
|
||||||
which will be parsed as \s-1NDR.\s0
|
|
||||||
.Sp
|
|
||||||
\&\fIsubcontext()\fR is deprecated now, and should not be used in new code.
|
|
||||||
Instead, use \fIrepresent_as()\fR or \fItransmit_as()\fR.
|
|
||||||
.IP "flag" 4
|
|
||||||
.IX Item "flag"
|
|
||||||
Specify boolean options, mostly used for
|
|
||||||
low-level \s-1NDR\s0 options. Several options
|
|
||||||
can be specified using the | character.
|
|
||||||
Note that flags are inherited by substructures!
|
|
||||||
.IP "nodiscriminant" 4
|
|
||||||
.IX Item "nodiscriminant"
|
|
||||||
The [nodiscriminant] property on a union means that the usual uint16
|
|
||||||
discriminent field at the start of the union on the wire is
|
|
||||||
omitted. This is not normally allowed in \s-1IDL/NDR,\s0 but is used for some
|
|
||||||
spoolss structures.
|
|
||||||
.IP "charset(name)" 4
|
|
||||||
.IX Item "charset(name)"
|
|
||||||
Specify that the array or string uses the specified
|
|
||||||
charset. If this attribute is specified, pidl will
|
|
||||||
take care of converting the character data from this format
|
|
||||||
to the host format. Commonly used values are \s-1UCS2, DOS\s0 and \s-1UTF8.\s0
|
|
||||||
.SS "Unsupported \s-1MIDL\s0 properties or statements"
|
|
||||||
.IX Subsection "Unsupported MIDL properties or statements"
|
|
||||||
aggregatable, appobject, async_uuid, bindable, control,
|
|
||||||
defaultbind, defaultcollelem, defaultvalue, defaultvtable, dispinterface,
|
|
||||||
displaybind, dual, entry, first_is, helpcontext, helpfile, helpstringcontext,
|
|
||||||
helpstringdll, hidden, idl_module, idl_quote, id, immediatebind, importlib,
|
|
||||||
includelib, last_is, lcid, licensed, max_is, module,
|
|
||||||
ms_union, no_injected_text, nonbrowsable, noncreatable, nonextensible, odl,
|
|
||||||
oleautomation, optional, pragma, propget, propputref, propput, readonly,
|
|
||||||
requestedit, restricted, retval, source, uidefault,
|
|
||||||
usesgetlasterror, vararg, vi_progid, wire_marshal.
|
|
||||||
.SH "EXAMPLES"
|
|
||||||
.IX Header "EXAMPLES"
|
|
||||||
.Vb 2
|
|
||||||
\& # Generating an Wireshark parser
|
|
||||||
\& $ ./pidl \-\-ws\-parser \-\- atsvc.idl
|
|
||||||
\&
|
|
||||||
\& # Generating a TDR parser and header
|
|
||||||
\& $ ./pidl \-\-tdr\-parser \-\-header \-\- regf.idl
|
|
||||||
\&
|
|
||||||
\& # Generating a Samba3 client and server
|
|
||||||
\& $ ./pidl \-\-samba3\-ndr\-client \-\-samba3\-ndr\-server \-\- dfs.idl
|
|
||||||
\&
|
|
||||||
\& # Generating a Samba4 NDR parser, client and server
|
|
||||||
\& $ ./pidl \-\-ndr\-parser \-\-ndr\-client \-\-ndr\-server \-\- samr.idl
|
|
||||||
.Ve
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.IX Header "SEE ALSO"
|
|
||||||
<https://msdn.microsoft.com/en\-us/library/windows/desktop/aa373864%28v=vs.85%29.aspx>
|
|
||||||
<https://wiki.wireshark.org/DCE/RPC>,
|
|
||||||
<https://www.samba.org/>,
|
|
||||||
\&\fIyapp\fR\|(1)
|
|
||||||
.SH "LICENSE"
|
|
||||||
.IX Header "LICENSE"
|
|
||||||
pidl is licensed under the \s-1GNU\s0 General Public License <https://www.gnu.org/licenses/gpl.html>.
|
|
||||||
.SH "AUTHOR"
|
|
||||||
.IX Header "AUTHOR"
|
|
||||||
pidl was written by Andrew Tridgell, Stefan Metzmacher, Tim Potter and Jelmer
|
|
||||||
Vernooij. The current maintainer is Jelmer Vernooij.
|
|
||||||
.PP
|
|
||||||
This manpage was written by Jelmer Vernooij, partially based on the original
|
|
||||||
pidl \s-1README\s0 by Andrew Tridgell.
|
|
|
@ -1,80 +0,0 @@
|
||||||
.\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32)
|
|
||||||
.\"
|
|
||||||
.\" Standard preamble:
|
|
||||||
.\" ========================================================================
|
|
||||||
.de Sp \" Vertical space (when we can't use .PP)
|
|
||||||
.if t .sp .5v
|
|
||||||
.if n .sp
|
|
||||||
..
|
|
||||||
.de Vb \" Begin verbatim text
|
|
||||||
.ft CW
|
|
||||||
.nf
|
|
||||||
.ne \\$1
|
|
||||||
..
|
|
||||||
.de Ve \" End verbatim text
|
|
||||||
.ft R
|
|
||||||
.fi
|
|
||||||
..
|
|
||||||
.\" Set up some character translations and predefined strings. \*(-- will
|
|
||||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
|
||||||
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
|
|
||||||
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
|
|
||||||
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
|
|
||||||
.\" nothing in troff, for use with C<>.
|
|
||||||
.tr \(*W-
|
|
||||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
|
||||||
.ie n \{\
|
|
||||||
. ds -- \(*W-
|
|
||||||
. ds PI pi
|
|
||||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
|
||||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
|
||||||
. ds L" ""
|
|
||||||
. ds R" ""
|
|
||||||
. ds C` ""
|
|
||||||
. ds C' ""
|
|
||||||
'br\}
|
|
||||||
.el\{\
|
|
||||||
. ds -- \|\(em\|
|
|
||||||
. ds PI \(*p
|
|
||||||
. ds L" ``
|
|
||||||
. ds R" ''
|
|
||||||
. ds C`
|
|
||||||
. ds C'
|
|
||||||
'br\}
|
|
||||||
.\"
|
|
||||||
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
|
||||||
.ie \n(.g .ds Aq \(aq
|
|
||||||
.el .ds Aq '
|
|
||||||
.\"
|
|
||||||
.\" If the F register is >0, we'll generate index entries on stderr for
|
|
||||||
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
|
||||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
|
||||||
.\" output yourself in some meaningful fashion.
|
|
||||||
.\"
|
|
||||||
.\" Avoid warning from groff about undefined register 'F'.
|
|
||||||
.de IX
|
|
||||||
..
|
|
||||||
.if !\nF .nr F 0
|
|
||||||
.if \nF>0 \{\
|
|
||||||
. de IX
|
|
||||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
|
||||||
..
|
|
||||||
. if !\nF==2 \{\
|
|
||||||
. nr % 0
|
|
||||||
. nr F 2
|
|
||||||
. \}
|
|
||||||
.\}
|
|
||||||
.\" ========================================================================
|
|
||||||
.\"
|
|
||||||
.IX Title "Parse::Pidl::Dump 3pm"
|
|
||||||
.TH Parse::Pidl::Dump 3pm "2016-11-15" "perl v5.24.1" "User Contributed Perl Documentation"
|
|
||||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
|
||||||
.\" way too many mistakes in technical documents.
|
|
||||||
.if n .ad l
|
|
||||||
.nh
|
|
||||||
.SH "NAME"
|
|
||||||
Parse::Pidl::Dump \- Dump support
|
|
||||||
.SH "DESCRIPTION"
|
|
||||||
.IX Header "DESCRIPTION"
|
|
||||||
This module provides functions that can generate \s-1IDL\s0 code from
|
|
||||||
internal pidl data structures.
|
|
|
@ -1,89 +0,0 @@
|
||||||
.\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32)
|
|
||||||
.\"
|
|
||||||
.\" Standard preamble:
|
|
||||||
.\" ========================================================================
|
|
||||||
.de Sp \" Vertical space (when we can't use .PP)
|
|
||||||
.if t .sp .5v
|
|
||||||
.if n .sp
|
|
||||||
..
|
|
||||||
.de Vb \" Begin verbatim text
|
|
||||||
.ft CW
|
|
||||||
.nf
|
|
||||||
.ne \\$1
|
|
||||||
..
|
|
||||||
.de Ve \" End verbatim text
|
|
||||||
.ft R
|
|
||||||
.fi
|
|
||||||
..
|
|
||||||
.\" Set up some character translations and predefined strings. \*(-- will
|
|
||||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
|
||||||
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
|
|
||||||
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
|
|
||||||
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
|
|
||||||
.\" nothing in troff, for use with C<>.
|
|
||||||
.tr \(*W-
|
|
||||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
|
||||||
.ie n \{\
|
|
||||||
. ds -- \(*W-
|
|
||||||
. ds PI pi
|
|
||||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
|
||||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
|
||||||
. ds L" ""
|
|
||||||
. ds R" ""
|
|
||||||
. ds C` ""
|
|
||||||
. ds C' ""
|
|
||||||
'br\}
|
|
||||||
.el\{\
|
|
||||||
. ds -- \|\(em\|
|
|
||||||
. ds PI \(*p
|
|
||||||
. ds L" ``
|
|
||||||
. ds R" ''
|
|
||||||
. ds C`
|
|
||||||
. ds C'
|
|
||||||
'br\}
|
|
||||||
.\"
|
|
||||||
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
|
||||||
.ie \n(.g .ds Aq \(aq
|
|
||||||
.el .ds Aq '
|
|
||||||
.\"
|
|
||||||
.\" If the F register is >0, we'll generate index entries on stderr for
|
|
||||||
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
|
||||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
|
||||||
.\" output yourself in some meaningful fashion.
|
|
||||||
.\"
|
|
||||||
.\" Avoid warning from groff about undefined register 'F'.
|
|
||||||
.de IX
|
|
||||||
..
|
|
||||||
.if !\nF .nr F 0
|
|
||||||
.if \nF>0 \{\
|
|
||||||
. de IX
|
|
||||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
|
||||||
..
|
|
||||||
. if !\nF==2 \{\
|
|
||||||
. nr % 0
|
|
||||||
. nr F 2
|
|
||||||
. \}
|
|
||||||
.\}
|
|
||||||
.\" ========================================================================
|
|
||||||
.\"
|
|
||||||
.IX Title "Parse::Pidl::NDR 3pm"
|
|
||||||
.TH Parse::Pidl::NDR 3pm "2016-11-15" "perl v5.24.1" "User Contributed Perl Documentation"
|
|
||||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
|
||||||
.\" way too many mistakes in technical documents.
|
|
||||||
.if n .ad l
|
|
||||||
.nh
|
|
||||||
.SH "NAME"
|
|
||||||
Parse::Pidl::NDR \- NDR parsing information generator
|
|
||||||
.SH "DESCRIPTION"
|
|
||||||
.IX Header "DESCRIPTION"
|
|
||||||
Return a table describing the order in which the parts of an element
|
|
||||||
should be parsed
|
|
||||||
Possible level types:
|
|
||||||
\- \s-1POINTER
|
|
||||||
\- ARRAY
|
|
||||||
\- SUBCONTEXT
|
|
||||||
\- SWITCH
|
|
||||||
\- DATA\s0
|
|
||||||
.SH "AUTHOR"
|
|
||||||
.IX Header "AUTHOR"
|
|
||||||
Jelmer Vernooij <jelmer@samba.org>
|
|
|
@ -1,108 +0,0 @@
|
||||||
.\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32)
|
|
||||||
.\"
|
|
||||||
.\" Standard preamble:
|
|
||||||
.\" ========================================================================
|
|
||||||
.de Sp \" Vertical space (when we can't use .PP)
|
|
||||||
.if t .sp .5v
|
|
||||||
.if n .sp
|
|
||||||
..
|
|
||||||
.de Vb \" Begin verbatim text
|
|
||||||
.ft CW
|
|
||||||
.nf
|
|
||||||
.ne \\$1
|
|
||||||
..
|
|
||||||
.de Ve \" End verbatim text
|
|
||||||
.ft R
|
|
||||||
.fi
|
|
||||||
..
|
|
||||||
.\" Set up some character translations and predefined strings. \*(-- will
|
|
||||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
|
||||||
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
|
|
||||||
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
|
|
||||||
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
|
|
||||||
.\" nothing in troff, for use with C<>.
|
|
||||||
.tr \(*W-
|
|
||||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
|
||||||
.ie n \{\
|
|
||||||
. ds -- \(*W-
|
|
||||||
. ds PI pi
|
|
||||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
|
||||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
|
||||||
. ds L" ""
|
|
||||||
. ds R" ""
|
|
||||||
. ds C` ""
|
|
||||||
. ds C' ""
|
|
||||||
'br\}
|
|
||||||
.el\{\
|
|
||||||
. ds -- \|\(em\|
|
|
||||||
. ds PI \(*p
|
|
||||||
. ds L" ``
|
|
||||||
. ds R" ''
|
|
||||||
. ds C`
|
|
||||||
. ds C'
|
|
||||||
'br\}
|
|
||||||
.\"
|
|
||||||
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
|
||||||
.ie \n(.g .ds Aq \(aq
|
|
||||||
.el .ds Aq '
|
|
||||||
.\"
|
|
||||||
.\" If the F register is >0, we'll generate index entries on stderr for
|
|
||||||
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
|
||||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
|
||||||
.\" output yourself in some meaningful fashion.
|
|
||||||
.\"
|
|
||||||
.\" Avoid warning from groff about undefined register 'F'.
|
|
||||||
.de IX
|
|
||||||
..
|
|
||||||
.if !\nF .nr F 0
|
|
||||||
.if \nF>0 \{\
|
|
||||||
. de IX
|
|
||||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
|
||||||
..
|
|
||||||
. if !\nF==2 \{\
|
|
||||||
. nr % 0
|
|
||||||
. nr F 2
|
|
||||||
. \}
|
|
||||||
.\}
|
|
||||||
.\" ========================================================================
|
|
||||||
.\"
|
|
||||||
.IX Title "Parse::Pidl::Util 3pm"
|
|
||||||
.TH Parse::Pidl::Util 3pm "2016-11-15" "perl v5.24.1" "User Contributed Perl Documentation"
|
|
||||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
|
||||||
.\" way too many mistakes in technical documents.
|
|
||||||
.if n .ad l
|
|
||||||
.nh
|
|
||||||
.SH "NAME"
|
|
||||||
Parse::Pidl::Util \- Generic utility functions for pidl
|
|
||||||
.SH "SYNOPSIS"
|
|
||||||
.IX Header "SYNOPSIS"
|
|
||||||
use Parse::Pidl::Util;
|
|
||||||
.SH "DESCRIPTION"
|
|
||||||
.IX Header "DESCRIPTION"
|
|
||||||
Simple module that contains a couple of trivial helper functions
|
|
||||||
used throughout the various pidl modules.
|
|
||||||
.SH "FUNCTIONS"
|
|
||||||
.IX Header "FUNCTIONS"
|
|
||||||
.IP "\fBMyDumper\fR a dumper wrapper to prevent dependence on the Data::Dumper module unless we actually need it" 4
|
|
||||||
.IX Item "MyDumper a dumper wrapper to prevent dependence on the Data::Dumper module unless we actually need it"
|
|
||||||
.PD 0
|
|
||||||
.IP "\fBhas_property\fR see if a pidl property list contains a given property" 4
|
|
||||||
.IX Item "has_property see if a pidl property list contains a given property"
|
|
||||||
.IP "\fBproperty_matches\fR see if a pidl property matches a value" 4
|
|
||||||
.IX Item "property_matches see if a pidl property matches a value"
|
|
||||||
.IP "\fBis_constant\fR return 1 if the string is a C constant" 4
|
|
||||||
.IX Item "is_constant return 1 if the string is a C constant"
|
|
||||||
.ie n .IP "\fBmake_str\fR return a """" quoted string, unless already quoted" 4
|
|
||||||
.el .IP "\fBmake_str\fR return a ``'' quoted string, unless already quoted" 4
|
|
||||||
.IX Item "make_str return a """" quoted string, unless already quoted"
|
|
||||||
.ie n .IP "\fBunmake_str\fR unquote a """" quoted string" 4
|
|
||||||
.el .IP "\fBunmake_str\fR unquote a ``'' quoted string" 4
|
|
||||||
.IX Item "unmake_str unquote a """" quoted string"
|
|
||||||
.IP "\fBprint_uuid\fR Print C representation of a \s-1UUID.\s0" 4
|
|
||||||
.IX Item "print_uuid Print C representation of a UUID."
|
|
||||||
.IP "\fBParseExpr\fR Interpret an \s-1IDL\s0 expression, substituting particular variables." 4
|
|
||||||
.IX Item "ParseExpr Interpret an IDL expression, substituting particular variables."
|
|
||||||
.IP "\fBParseExprExt\fR Interpret an \s-1IDL\s0 expression, substituting particular variables. Can call callbacks when pointers are being dereferenced or variables are being used." 4
|
|
||||||
.IX Item "ParseExprExt Interpret an IDL expression, substituting particular variables. Can call callbacks when pointers are being dereferenced or variables are being used."
|
|
||||||
.IP "\fBgenpad\fR return an empty string consisting of tabs and spaces suitable for proper indent of C\-functions." 4
|
|
||||||
.IX Item "genpad return an empty string consisting of tabs and spaces suitable for proper indent of C-functions."
|
|
|
@ -1,151 +0,0 @@
|
||||||
.\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32)
|
|
||||||
.\"
|
|
||||||
.\" Standard preamble:
|
|
||||||
.\" ========================================================================
|
|
||||||
.de Sp \" Vertical space (when we can't use .PP)
|
|
||||||
.if t .sp .5v
|
|
||||||
.if n .sp
|
|
||||||
..
|
|
||||||
.de Vb \" Begin verbatim text
|
|
||||||
.ft CW
|
|
||||||
.nf
|
|
||||||
.ne \\$1
|
|
||||||
..
|
|
||||||
.de Ve \" End verbatim text
|
|
||||||
.ft R
|
|
||||||
.fi
|
|
||||||
..
|
|
||||||
.\" Set up some character translations and predefined strings. \*(-- will
|
|
||||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
|
||||||
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
|
|
||||||
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
|
|
||||||
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
|
|
||||||
.\" nothing in troff, for use with C<>.
|
|
||||||
.tr \(*W-
|
|
||||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
|
||||||
.ie n \{\
|
|
||||||
. ds -- \(*W-
|
|
||||||
. ds PI pi
|
|
||||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
|
||||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
|
||||||
. ds L" ""
|
|
||||||
. ds R" ""
|
|
||||||
. ds C` ""
|
|
||||||
. ds C' ""
|
|
||||||
'br\}
|
|
||||||
.el\{\
|
|
||||||
. ds -- \|\(em\|
|
|
||||||
. ds PI \(*p
|
|
||||||
. ds L" ``
|
|
||||||
. ds R" ''
|
|
||||||
. ds C`
|
|
||||||
. ds C'
|
|
||||||
'br\}
|
|
||||||
.\"
|
|
||||||
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
|
||||||
.ie \n(.g .ds Aq \(aq
|
|
||||||
.el .ds Aq '
|
|
||||||
.\"
|
|
||||||
.\" If the F register is >0, we'll generate index entries on stderr for
|
|
||||||
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
|
||||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
|
||||||
.\" output yourself in some meaningful fashion.
|
|
||||||
.\"
|
|
||||||
.\" Avoid warning from groff about undefined register 'F'.
|
|
||||||
.de IX
|
|
||||||
..
|
|
||||||
.if !\nF .nr F 0
|
|
||||||
.if \nF>0 \{\
|
|
||||||
. de IX
|
|
||||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
|
||||||
..
|
|
||||||
. if !\nF==2 \{\
|
|
||||||
. nr % 0
|
|
||||||
. nr F 2
|
|
||||||
. \}
|
|
||||||
.\}
|
|
||||||
.\" ========================================================================
|
|
||||||
.\"
|
|
||||||
.IX Title "Parse::Pidl::Wireshark::Conformance 3pm"
|
|
||||||
.TH Parse::Pidl::Wireshark::Conformance 3pm "2016-11-15" "perl v5.24.1" "User Contributed Perl Documentation"
|
|
||||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
|
||||||
.\" way too many mistakes in technical documents.
|
|
||||||
.if n .ad l
|
|
||||||
.nh
|
|
||||||
.SH "NAME"
|
|
||||||
Parse::Pidl::Wireshark::Conformance \- Conformance file parser for Wireshark
|
|
||||||
.SH "DESCRIPTION"
|
|
||||||
.IX Header "DESCRIPTION"
|
|
||||||
This module supports parsing Wireshark conformance files (*.cnf).
|
|
||||||
.SH "FILE FORMAT"
|
|
||||||
.IX Header "FILE FORMAT"
|
|
||||||
Pidl needs additional data for Wireshark output. This data is read from
|
|
||||||
so-called conformance files. This section describes the format of these
|
|
||||||
files.
|
|
||||||
.PP
|
|
||||||
Conformance files are simple text files with a single command on each line.
|
|
||||||
Empty lines and lines starting with a '#' character are ignored.
|
|
||||||
Arguments to commands are separated by spaces.
|
|
||||||
.PP
|
|
||||||
The following commands are currently supported:
|
|
||||||
.IP "\fI\s-1TYPE\s0\fR name dissector ft_type base_type mask valsstring alignment" 4
|
|
||||||
.IX Item "TYPE name dissector ft_type base_type mask valsstring alignment"
|
|
||||||
Register new data type with specified name, what dissector function to call
|
|
||||||
and what properties to give header fields for elements of this type.
|
|
||||||
.IP "\fI\s-1NOEMIT\s0\fR type" 4
|
|
||||||
.IX Item "NOEMIT type"
|
|
||||||
Suppress emitting a dissect_type function for the specified type
|
|
||||||
.IP "\fI\s-1PARAM_VALUE\s0\fR type param" 4
|
|
||||||
.IX Item "PARAM_VALUE type param"
|
|
||||||
Set parameter to specify to dissector function for given type.
|
|
||||||
.IP "\fI\s-1HF_FIELD\s0\fR hf title filter ft_type base_type valsstring mask description" 4
|
|
||||||
.IX Item "HF_FIELD hf title filter ft_type base_type valsstring mask description"
|
|
||||||
Generate a custom header field with specified properties.
|
|
||||||
.IP "\fI\s-1HF_RENAME\s0\fR old_hf_name new_hf_name" 4
|
|
||||||
.IX Item "HF_RENAME old_hf_name new_hf_name"
|
|
||||||
Force the use of new_hf_name when the parser generator was going to
|
|
||||||
use old_hf_name.
|
|
||||||
.Sp
|
|
||||||
This can be used in conjunction with \s-1HF_FIELD\s0 in order to make more than
|
|
||||||
one element use the same filter name.
|
|
||||||
.IP "\fI\s-1ETT_FIELD\s0\fR ett" 4
|
|
||||||
.IX Item "ETT_FIELD ett"
|
|
||||||
Register a custom ett field
|
|
||||||
.IP "\fI\s-1STRIP_PREFIX\s0\fR prefix" 4
|
|
||||||
.IX Item "STRIP_PREFIX prefix"
|
|
||||||
Remove the specified prefix from all function names (if present).
|
|
||||||
.IP "\fI\s-1PROTOCOL\s0\fR longname shortname filtername" 4
|
|
||||||
.IX Item "PROTOCOL longname shortname filtername"
|
|
||||||
Change the short\-, long\- and filter-name for the current interface in
|
|
||||||
Wireshark.
|
|
||||||
.IP "\fI\s-1FIELD_DESCRIPTION\s0\fR field desc" 4
|
|
||||||
.IX Item "FIELD_DESCRIPTION field desc"
|
|
||||||
Change description for the specified header field. `field' is the hf name of the field.
|
|
||||||
.IP "\fI\s-1IMPORT\s0\fR dissector code..." 4
|
|
||||||
.IX Item "IMPORT dissector code..."
|
|
||||||
Code to insert when generating the specified dissector. \f(CW@HF\fR@ and
|
|
||||||
\&\f(CW@PARAM\fR@ will be substituted.
|
|
||||||
.IP "\fI\s-1INCLUDE\s0\fR filename" 4
|
|
||||||
.IX Item "INCLUDE filename"
|
|
||||||
Include conformance data from the specified filename in the dissector.
|
|
||||||
.ie n .IP "\fI\s-1TFS\s0\fR hf_name ""true string"" ""false string""" 4
|
|
||||||
.el .IP "\fI\s-1TFS\s0\fR hf_name ``true string'' ``false string''" 4
|
|
||||||
.IX Item "TFS hf_name true string false string"
|
|
||||||
Override the text shown when a bitmap boolean value is enabled or disabled.
|
|
||||||
.IP "\fI\s-1MANUAL\s0\fR fn_name" 4
|
|
||||||
.IX Item "MANUAL fn_name"
|
|
||||||
Force pidl to not generate a particular function but allow the user
|
|
||||||
to write a function manually. This can be used to remove the function
|
|
||||||
for only one level for a particular element rather than all the functions and
|
|
||||||
ett/hf variables for a particular element as the \s-1NOEMIT\s0 command does.
|
|
||||||
.IP "\fI\s-1CODE START\s0\fR/\fI\s-1CODE END\s0\fR Begin and end a section of code to be put directly into the generated source file for the dissector." 4
|
|
||||||
.IX Item "CODE START/CODE END Begin and end a section of code to be put directly into the generated source file for the dissector."
|
|
||||||
.PD 0
|
|
||||||
.IP "\fI\s-1HEADER START\s0\fR/\fI\s-1HEADER END\s0\fR Begin and end a section of code to be put directly into the generated header file for the dissector." 4
|
|
||||||
.IX Item "HEADER START/HEADER END Begin and end a section of code to be put directly into the generated header file for the dissector."
|
|
||||||
.PD
|
|
||||||
.SH "EXAMPLE"
|
|
||||||
.IX Header "EXAMPLE"
|
|
||||||
.Vb 1
|
|
||||||
\& INFO_KEY OpenKey.Ke
|
|
||||||
.Ve
|
|
|
@ -1,76 +0,0 @@
|
||||||
.\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32)
|
|
||||||
.\"
|
|
||||||
.\" Standard preamble:
|
|
||||||
.\" ========================================================================
|
|
||||||
.de Sp \" Vertical space (when we can't use .PP)
|
|
||||||
.if t .sp .5v
|
|
||||||
.if n .sp
|
|
||||||
..
|
|
||||||
.de Vb \" Begin verbatim text
|
|
||||||
.ft CW
|
|
||||||
.nf
|
|
||||||
.ne \\$1
|
|
||||||
..
|
|
||||||
.de Ve \" End verbatim text
|
|
||||||
.ft R
|
|
||||||
.fi
|
|
||||||
..
|
|
||||||
.\" Set up some character translations and predefined strings. \*(-- will
|
|
||||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
|
||||||
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
|
|
||||||
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
|
|
||||||
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
|
|
||||||
.\" nothing in troff, for use with C<>.
|
|
||||||
.tr \(*W-
|
|
||||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
|
||||||
.ie n \{\
|
|
||||||
. ds -- \(*W-
|
|
||||||
. ds PI pi
|
|
||||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
|
||||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
|
||||||
. ds L" ""
|
|
||||||
. ds R" ""
|
|
||||||
. ds C` ""
|
|
||||||
. ds C' ""
|
|
||||||
'br\}
|
|
||||||
.el\{\
|
|
||||||
. ds -- \|\(em\|
|
|
||||||
. ds PI \(*p
|
|
||||||
. ds L" ``
|
|
||||||
. ds R" ''
|
|
||||||
. ds C`
|
|
||||||
. ds C'
|
|
||||||
'br\}
|
|
||||||
.\"
|
|
||||||
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
|
||||||
.ie \n(.g .ds Aq \(aq
|
|
||||||
.el .ds Aq '
|
|
||||||
.\"
|
|
||||||
.\" If the F register is >0, we'll generate index entries on stderr for
|
|
||||||
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
|
||||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
|
||||||
.\" output yourself in some meaningful fashion.
|
|
||||||
.\"
|
|
||||||
.\" Avoid warning from groff about undefined register 'F'.
|
|
||||||
.de IX
|
|
||||||
..
|
|
||||||
.if !\nF .nr F 0
|
|
||||||
.if \nF>0 \{\
|
|
||||||
. de IX
|
|
||||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
|
||||||
..
|
|
||||||
. if !\nF==2 \{\
|
|
||||||
. nr % 0
|
|
||||||
. nr F 2
|
|
||||||
. \}
|
|
||||||
.\}
|
|
||||||
.\" ========================================================================
|
|
||||||
.\"
|
|
||||||
.IX Title "Parse::Pidl::Wireshark::NDR 3pm"
|
|
||||||
.TH Parse::Pidl::Wireshark::NDR 3pm "2016-11-15" "perl v5.24.1" "User Contributed Perl Documentation"
|
|
||||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
|
||||||
.\" way too many mistakes in technical documents.
|
|
||||||
.if n .ad l
|
|
||||||
.nh
|
|
||||||
.SH "NAME"
|
|
||||||
Parse::Pidl::Wireshark::NDR \- Parser generator for Wireshark
|
|
|
@ -1,804 +0,0 @@
|
||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
###################################################
|
|
||||||
# package to parse IDL files and generate code for
|
|
||||||
# rpc functions in Samba
|
|
||||||
# Copyright tridge@samba.org 2000-2003
|
|
||||||
# Copyright jelmer@samba.org 2005-2007
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
pidl - An IDL compiler written in Perl
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
pidl --help
|
|
||||||
|
|
||||||
pidl [--outputdir[=OUTNAME]] [--includedir DIR...] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--header[=OUTPUT]] [--python[=OUTPUT]] [--ndr-parser[=OUTPUT]] [--client] [--server] [--warn-compat] [--quiet] [--verbose] [--template] [--ws-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-parser[=OUTPUT]] [--samba3-ndr-client[=OUTPUT]] [--samba3-ndr-server[=OUTPUT]] [--typelib=[OUTPUT]] [<idlfile>.idl]...
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
pidl is an IDL compiler written in Perl that aims to be somewhat
|
|
||||||
compatible with the midl compiler. IDL is short for
|
|
||||||
"Interface Definition Language".
|
|
||||||
|
|
||||||
pidl can generate stubs for DCE/RPC server code, DCE/RPC
|
|
||||||
client code and Wireshark dissectors for DCE/RPC traffic.
|
|
||||||
|
|
||||||
IDL compilers like pidl take a description
|
|
||||||
of an interface as their input and use it to generate C
|
|
||||||
(though support for other languages may be added later) code that
|
|
||||||
can use these interfaces, pretty print data sent
|
|
||||||
using these interfaces, or even generate Wireshark
|
|
||||||
dissectors that can parse data sent over the
|
|
||||||
wire by these interfaces.
|
|
||||||
|
|
||||||
pidl takes IDL files in the same format as is used by midl,
|
|
||||||
converts it to a .pidl file (which contains pidl's internal representation of the interface) and can then generate whatever output you need.
|
|
||||||
.pidl files should be used for debugging purposes only. Write your
|
|
||||||
interface definitions in .idl format.
|
|
||||||
|
|
||||||
The goal of pidl is to implement a IDL compiler that can be used
|
|
||||||
while developing the RPC subsystem in Samba (for
|
|
||||||
both marshalling/unmarshalling and debugging purposes).
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item I<--help>
|
|
||||||
|
|
||||||
Show list of available options.
|
|
||||||
|
|
||||||
=item I<--version>
|
|
||||||
|
|
||||||
Show pidl version
|
|
||||||
|
|
||||||
=item I<--outputdir OUTNAME>
|
|
||||||
|
|
||||||
Write output files to the specified directory. Defaults to the current
|
|
||||||
directory.
|
|
||||||
|
|
||||||
=item I<--includedir DIR>
|
|
||||||
|
|
||||||
Add DIR to the search path used by the preprocessor. This option can be
|
|
||||||
specified multiple times.
|
|
||||||
|
|
||||||
=item I<--parse-idl-tree>
|
|
||||||
|
|
||||||
Read internal tree structure from input files rather
|
|
||||||
than assuming they contain IDL.
|
|
||||||
|
|
||||||
=item I<--dump-idl>
|
|
||||||
|
|
||||||
Generate a new IDL file. File will be named OUTNAME.idl.
|
|
||||||
|
|
||||||
=item I<--header>
|
|
||||||
|
|
||||||
Generate a C header file for the specified interface. Filename defaults to OUTNAME.h.
|
|
||||||
|
|
||||||
=item I<--ndr-parser>
|
|
||||||
|
|
||||||
Generate a C file and C header containing NDR parsers. The filename for
|
|
||||||
the parser defaults to ndr_OUTNAME.c. The header filename will be the
|
|
||||||
parser filename with the extension changed from .c to .h.
|
|
||||||
|
|
||||||
=item I<--tdr-parser>
|
|
||||||
|
|
||||||
Generate a C file and C header containing TDR parsers. The filename for
|
|
||||||
the parser defaults to tdr_OUTNAME.c. The header filename will be the
|
|
||||||
parser filename with the extension changed from .c to .h.
|
|
||||||
|
|
||||||
=item I<--typelib>
|
|
||||||
|
|
||||||
Write type information to the specified file.
|
|
||||||
|
|
||||||
=item I<--server>
|
|
||||||
|
|
||||||
Generate boilerplate for the RPC server that implements
|
|
||||||
the interface. Filename defaults to ndr_OUTNAME_s.c.
|
|
||||||
|
|
||||||
=item I<--template>
|
|
||||||
|
|
||||||
Generate stubs for a RPC server that implements the interface. Output will
|
|
||||||
be written to stdout.
|
|
||||||
|
|
||||||
=item I<--ws-parser>
|
|
||||||
|
|
||||||
Generate an Wireshark dissector (in C) and header file. The dissector filename
|
|
||||||
defaults to packet-dcerpc-OUTNAME.c while the header filename defaults to
|
|
||||||
packet-dcerpc-OUTNAME.h.
|
|
||||||
|
|
||||||
Pidl will read additional data from an Wireshark conformance file if present.
|
|
||||||
Such a file should have the same location as the IDL file but with the
|
|
||||||
extension I<cnf> rather than I<idl>. See L<Parse::Pidl::Wireshark::Conformance>
|
|
||||||
for details on the format of this file.
|
|
||||||
|
|
||||||
=item I<--diff>
|
|
||||||
|
|
||||||
Parse an IDL file, generate a new IDL file based on the internal data
|
|
||||||
structures and see if there are any differences with the original IDL file.
|
|
||||||
Useful for debugging pidl.
|
|
||||||
|
|
||||||
=item I<--dump-idl-tree>
|
|
||||||
|
|
||||||
Tell pidl to dump the internal tree representation of an IDL
|
|
||||||
file the to disk. Useful for debugging pidl.
|
|
||||||
|
|
||||||
=item I<--dump-ndr-tree>
|
|
||||||
|
|
||||||
Tell pidl to dump the internal NDR information tree it generated
|
|
||||||
from the IDL file to disk. Useful for debugging pidl.
|
|
||||||
|
|
||||||
=item I<--samba3-ndr-client>
|
|
||||||
|
|
||||||
Generate client calls for Samba3, to be placed in rpc_client/. Instead of
|
|
||||||
calling out to the code in Samba3's rpc_parse/, this will call out to
|
|
||||||
Samba4's NDR code instead.
|
|
||||||
|
|
||||||
=item I<--samba3-ndr-server>
|
|
||||||
|
|
||||||
Generate server calls for Samba3, to be placed in rpc_server/. Instead of
|
|
||||||
calling out to the code in Samba3's rpc_parse/, this will call out to
|
|
||||||
Samba4's NDR code instead.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 IDL SYNTAX
|
|
||||||
|
|
||||||
IDL files are always preprocessed using the C preprocessor.
|
|
||||||
|
|
||||||
Pretty much everything in an interface (the interface itself, functions,
|
|
||||||
parameters) can have attributes (or properties whatever name you give them).
|
|
||||||
Attributes always prepend the element they apply to and are surrounded
|
|
||||||
by square brackets ([]). Multiple attributes are separated by comma's;
|
|
||||||
arguments to attributes are specified between parentheses.
|
|
||||||
|
|
||||||
See the section COMPATIBILITY for the list of attributes that
|
|
||||||
pidl supports.
|
|
||||||
|
|
||||||
C-style comments can be used.
|
|
||||||
|
|
||||||
=head2 CONFORMANT ARRAYS
|
|
||||||
|
|
||||||
A conformant array is one with that ends in [*] or []. The strange
|
|
||||||
things about conformant arrays are that they can only appear as the last
|
|
||||||
element of a structure (unless there is a pointer to the conformant array,
|
|
||||||
of course) and the array size appears before the structure itself on the wire.
|
|
||||||
|
|
||||||
So, in this example:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long abc;
|
|
||||||
long count;
|
|
||||||
long foo;
|
|
||||||
[size_is(count)] long s[*];
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
it appears like this:
|
|
||||||
|
|
||||||
[size_is] [abc] [count] [foo] [s...]
|
|
||||||
|
|
||||||
the first [size_is] field is the allocation size of the array, and
|
|
||||||
occurs before the array elements and even before the structure
|
|
||||||
alignment.
|
|
||||||
|
|
||||||
Note that size_is() can refer to a constant, but that doesn't change
|
|
||||||
the wire representation. It does not make the array a fixed array.
|
|
||||||
|
|
||||||
midl.exe would write the above array as the following C header:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long abc;
|
|
||||||
long count;
|
|
||||||
long foo;
|
|
||||||
long s[1];
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
pidl takes a different approach, and writes it like this:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long abc;
|
|
||||||
long count;
|
|
||||||
long foo;
|
|
||||||
long *s;
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
=head2 VARYING ARRAYS
|
|
||||||
|
|
||||||
A varying array looks like this:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long abc;
|
|
||||||
long count;
|
|
||||||
long foo;
|
|
||||||
[size_is(count)] long *s;
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
This will look like this on the wire:
|
|
||||||
|
|
||||||
[abc] [count] [foo] [PTR_s] [count] [s...]
|
|
||||||
|
|
||||||
=head2 FIXED ARRAYS
|
|
||||||
|
|
||||||
A fixed array looks like this:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long s[10];
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
The NDR representation looks just like 10 separate long
|
|
||||||
declarations. The array size is not encoded on the wire.
|
|
||||||
|
|
||||||
pidl also supports "inline" arrays, which are not part of the IDL/NDR
|
|
||||||
standard. These are declared like this:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32 foo;
|
|
||||||
uint32 count;
|
|
||||||
uint32 bar;
|
|
||||||
long s[count];
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
This appears like this:
|
|
||||||
|
|
||||||
[foo] [count] [bar] [s...]
|
|
||||||
|
|
||||||
Fixed arrays are an extension added to support some of the strange
|
|
||||||
embedded structures in security descriptors and spoolss.
|
|
||||||
|
|
||||||
This section is by no means complete. See the OpenGroup and MSDN
|
|
||||||
documentation for additional information.
|
|
||||||
|
|
||||||
=head1 COMPATIBILITY WITH MIDL
|
|
||||||
|
|
||||||
=head2 Missing features in pidl
|
|
||||||
|
|
||||||
The following MIDL features are not (yet) implemented in pidl
|
|
||||||
or are implemented with an incompatible interface:
|
|
||||||
|
|
||||||
=over
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Asynchronous communication
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Typelibs (.tlb files)
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Datagram support (ncadg_*)
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head2 Supported attributes and statements
|
|
||||||
|
|
||||||
in, out, ref, length_is, switch_is, size_is, uuid, case, default, string,
|
|
||||||
unique, ptr, pointer_default, v1_enum, object, helpstring, range, local,
|
|
||||||
call_as, endpoint, switch_type, progid, coclass, iid_is, represent_as,
|
|
||||||
transmit_as, import, include, cpp_quote.
|
|
||||||
|
|
||||||
=head2 PIDL Specific properties
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item public
|
|
||||||
|
|
||||||
The [public] property on a structure or union is a pidl extension that
|
|
||||||
forces the generated pull/push functions to be non-static. This allows
|
|
||||||
you to declare types that can be used between modules. If you don't
|
|
||||||
specify [public] then pull/push functions for other than top-level
|
|
||||||
functions are declared static.
|
|
||||||
|
|
||||||
=item noprint
|
|
||||||
|
|
||||||
The [noprint] property is a pidl extension that allows you to specify
|
|
||||||
that pidl should not generate a ndr_print_*() function for that
|
|
||||||
structure or union. This is used when you wish to define your own
|
|
||||||
print function that prints a structure in a nicer manner. A good
|
|
||||||
example is the use of [noprint] on dom_sid, which allows the
|
|
||||||
pretty-printing of SIDs.
|
|
||||||
|
|
||||||
=item value
|
|
||||||
|
|
||||||
The [value(expression)] property is a pidl extension that allows you
|
|
||||||
to specify the value of a field when it is put on the wire. This
|
|
||||||
allows fields that always have a well-known value to be automatically
|
|
||||||
filled in, thus making the API more programmer friendly. The
|
|
||||||
expression can be any C expression.
|
|
||||||
|
|
||||||
=item relative
|
|
||||||
|
|
||||||
The [relative] property can be supplied on a pointer. When it is used
|
|
||||||
it declares the pointer as a spoolss style "relative" pointer, which
|
|
||||||
means it appears on the wire as an offset within the current
|
|
||||||
encapsulating structure. This is not part of normal IDL/NDR, but it is
|
|
||||||
a very useful extension as it avoids the manual encoding of many
|
|
||||||
complex structures.
|
|
||||||
|
|
||||||
=item subcontext(length)
|
|
||||||
|
|
||||||
Specifies that a size of I<length>
|
|
||||||
bytes should be read, followed by a blob of that size,
|
|
||||||
which will be parsed as NDR.
|
|
||||||
|
|
||||||
subcontext() is deprecated now, and should not be used in new code.
|
|
||||||
Instead, use represent_as() or transmit_as().
|
|
||||||
|
|
||||||
=item flag
|
|
||||||
|
|
||||||
Specify boolean options, mostly used for
|
|
||||||
low-level NDR options. Several options
|
|
||||||
can be specified using the | character.
|
|
||||||
Note that flags are inherited by substructures!
|
|
||||||
|
|
||||||
=item nodiscriminant
|
|
||||||
|
|
||||||
The [nodiscriminant] property on a union means that the usual uint16
|
|
||||||
discriminent field at the start of the union on the wire is
|
|
||||||
omitted. This is not normally allowed in IDL/NDR, but is used for some
|
|
||||||
spoolss structures.
|
|
||||||
|
|
||||||
=item charset(name)
|
|
||||||
|
|
||||||
Specify that the array or string uses the specified
|
|
||||||
charset. If this attribute is specified, pidl will
|
|
||||||
take care of converting the character data from this format
|
|
||||||
to the host format. Commonly used values are UCS2, DOS and UTF8.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head2 Unsupported MIDL properties or statements
|
|
||||||
|
|
||||||
aggregatable, appobject, async_uuid, bindable, control,
|
|
||||||
defaultbind, defaultcollelem, defaultvalue, defaultvtable, dispinterface,
|
|
||||||
displaybind, dual, entry, first_is, helpcontext, helpfile, helpstringcontext,
|
|
||||||
helpstringdll, hidden, idl_module, idl_quote, id, immediatebind, importlib,
|
|
||||||
includelib, last_is, lcid, licensed, max_is, module,
|
|
||||||
ms_union, no_injected_text, nonbrowsable, noncreatable, nonextensible, odl,
|
|
||||||
oleautomation, optional, pragma, propget, propputref, propput, readonly,
|
|
||||||
requestedit, restricted, retval, source, uidefault,
|
|
||||||
usesgetlasterror, vararg, vi_progid, wire_marshal.
|
|
||||||
|
|
||||||
=head1 EXAMPLES
|
|
||||||
|
|
||||||
# Generating an Wireshark parser
|
|
||||||
$ ./pidl --ws-parser -- atsvc.idl
|
|
||||||
|
|
||||||
# Generating a TDR parser and header
|
|
||||||
$ ./pidl --tdr-parser --header -- regf.idl
|
|
||||||
|
|
||||||
# Generating a Samba3 client and server
|
|
||||||
$ ./pidl --samba3-ndr-client --samba3-ndr-server -- dfs.idl
|
|
||||||
|
|
||||||
# Generating a Samba4 NDR parser, client and server
|
|
||||||
$ ./pidl --ndr-parser --ndr-client --ndr-server -- samr.idl
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
L<https://msdn.microsoft.com/en-us/library/windows/desktop/aa373864%28v=vs.85%29.aspx>
|
|
||||||
L<https://wiki.wireshark.org/DCE/RPC>,
|
|
||||||
L<https://www.samba.org/>,
|
|
||||||
L<yapp(1)>
|
|
||||||
|
|
||||||
=head1 LICENSE
|
|
||||||
|
|
||||||
pidl is licensed under the GNU General Public License L<https://www.gnu.org/licenses/gpl.html>.
|
|
||||||
|
|
||||||
=head1 AUTHOR
|
|
||||||
|
|
||||||
pidl was written by Andrew Tridgell, Stefan Metzmacher, Tim Potter and Jelmer
|
|
||||||
Vernooij. The current maintainer is Jelmer Vernooij.
|
|
||||||
|
|
||||||
This manpage was written by Jelmer Vernooij, partially based on the original
|
|
||||||
pidl README by Andrew Tridgell.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use FindBin qw($RealBin $Script);
|
|
||||||
use lib "$RealBin/lib";
|
|
||||||
use Getopt::Long;
|
|
||||||
use File::Basename;
|
|
||||||
use Parse::Pidl qw ( $VERSION );
|
|
||||||
use Parse::Pidl::Util;
|
|
||||||
use Parse::Pidl::ODL;
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# save a data structure into a file
|
|
||||||
sub SaveStructure($$)
|
|
||||||
{
|
|
||||||
my($filename,$v) = @_;
|
|
||||||
FileSave($filename, Parse::Pidl::Util::MyDumper($v));
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# load a data structure from a file (as saved with SaveStructure)
|
|
||||||
sub LoadStructure($)
|
|
||||||
{
|
|
||||||
my $f = shift;
|
|
||||||
my $contents = FileLoad($f);
|
|
||||||
defined $contents || return undef;
|
|
||||||
return eval "$contents";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# read a file into a string
|
|
||||||
sub FileLoad($)
|
|
||||||
{
|
|
||||||
my($filename) = shift;
|
|
||||||
local(*INPUTFILE);
|
|
||||||
open(INPUTFILE, $filename) || return undef;
|
|
||||||
my($saved_delim) = $/;
|
|
||||||
undef $/;
|
|
||||||
my($data) = <INPUTFILE>;
|
|
||||||
close(INPUTFILE);
|
|
||||||
$/ = $saved_delim;
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# write a string into a file
|
|
||||||
sub FileSave($$)
|
|
||||||
{
|
|
||||||
my($filename) = shift;
|
|
||||||
my($v) = shift;
|
|
||||||
local(*FILE);
|
|
||||||
open(FILE, ">$filename") || die "can't open $filename";
|
|
||||||
print FILE $v;
|
|
||||||
close(FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
my(@opt_incdirs) = ();
|
|
||||||
my($opt_help) = 0;
|
|
||||||
my($opt_version) = 0;
|
|
||||||
my($opt_parse_idl_tree) = 0;
|
|
||||||
my($opt_dump_idl_tree);
|
|
||||||
my($opt_dump_ndr_tree);
|
|
||||||
my($opt_dump_idl) = 0;
|
|
||||||
my($opt_diff) = 0;
|
|
||||||
my($opt_header);
|
|
||||||
my($opt_samba3_header);
|
|
||||||
my($opt_samba3_parser);
|
|
||||||
my($opt_samba3_server);
|
|
||||||
my($opt_samba3_ndr_client);
|
|
||||||
my($opt_samba3_ndr_server);
|
|
||||||
my($opt_samba3_template) = 0;
|
|
||||||
my($opt_template) = 0;
|
|
||||||
my($opt_client);
|
|
||||||
my($opt_typelib);
|
|
||||||
my($opt_server);
|
|
||||||
my($opt_ndr_parser);
|
|
||||||
my($opt_tdr_parser);
|
|
||||||
my($opt_ws_parser);
|
|
||||||
my($opt_python);
|
|
||||||
my($opt_quiet) = 0;
|
|
||||||
my($opt_outputdir) = '.';
|
|
||||||
my($opt_verbose) = 0;
|
|
||||||
my($opt_warn_compat) = 0;
|
|
||||||
my($opt_dcom_proxy);
|
|
||||||
my($opt_com_header);
|
|
||||||
|
|
||||||
#########################################
|
|
||||||
# display help text
|
|
||||||
sub ShowHelp()
|
|
||||||
{
|
|
||||||
print "perl IDL parser and code generator\n";
|
|
||||||
ShowVersion();
|
|
||||||
print"
|
|
||||||
Copyright (C) Andrew Tridgell <tridge\@samba.org>
|
|
||||||
Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
|
|
||||||
|
|
||||||
Usage: $Script [options] [--] <idlfile> [<idlfile>...]
|
|
||||||
|
|
||||||
Generic Options:
|
|
||||||
--help this help page
|
|
||||||
--version show pidl version
|
|
||||||
--outputdir=OUTDIR put output in OUTDIR/ [.]
|
|
||||||
--warn-compat warn about incompatibility with other compilers
|
|
||||||
--quiet be quiet
|
|
||||||
--verbose be verbose
|
|
||||||
--includedir DIR search DIR for included files
|
|
||||||
|
|
||||||
Debugging:
|
|
||||||
--dump-idl-tree[=FILE] dump internal representation to file [BASENAME.pidl]
|
|
||||||
--parse-idl-tree read internal representation instead of IDL
|
|
||||||
--dump-ndr-tree[=FILE] dump internal NDR data tree to file [BASENAME.ndr]
|
|
||||||
--dump-idl regenerate IDL file
|
|
||||||
--diff run diff on original IDL and dumped output
|
|
||||||
--typelib print type information
|
|
||||||
|
|
||||||
Samba 4 output:
|
|
||||||
--header[=OUTFILE] create generic header file [BASENAME.h]
|
|
||||||
--ndr-parser[=OUTFILE] create a C NDR parser [ndr_BASENAME.c]
|
|
||||||
--client[=OUTFILE] create a C NDR client [ndr_BASENAME_c.c]
|
|
||||||
--tdr-parser[=OUTFILE] create a C TDR parser [tdr_BASENAME.c]
|
|
||||||
--python[=OUTFILE] create python wrapper file [py_BASENAME.c]
|
|
||||||
--server[=OUTFILE] create server boilerplate [ndr_BASENAME_s.c]
|
|
||||||
--template print a template for a pipe
|
|
||||||
--dcom-proxy[=OUTFILE] create DCOM proxy [ndr_BASENAME_p.c]
|
|
||||||
--com-header[=OUTFILE] create header for COM [com_BASENAME.h]
|
|
||||||
|
|
||||||
Samba 3 output:
|
|
||||||
--samba3-ndr-client[=OUTF] create client calls for Samba3
|
|
||||||
using Samba4's NDR code [cli_BASENAME.c]
|
|
||||||
--samba3-ndr-server[=OUTF] create server call wrapper for Samba3
|
|
||||||
using Samba4's NDR code [srv_BASENAME.c]
|
|
||||||
--samba3-template print a template for a pipe
|
|
||||||
|
|
||||||
Wireshark parsers:
|
|
||||||
--ws-parser[=OUTFILE] create Wireshark parser and header
|
|
||||||
\n";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#########################################
|
|
||||||
# Display version
|
|
||||||
sub ShowVersion()
|
|
||||||
{
|
|
||||||
print "perl IDL version $VERSION\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
# main program
|
|
||||||
my $result = GetOptions (
|
|
||||||
'help|h|?' => \$opt_help,
|
|
||||||
'version' => \$opt_version,
|
|
||||||
'outputdir=s' => \$opt_outputdir,
|
|
||||||
'dump-idl' => \$opt_dump_idl,
|
|
||||||
'dump-idl-tree:s' => \$opt_dump_idl_tree,
|
|
||||||
'parse-idl-tree' => \$opt_parse_idl_tree,
|
|
||||||
'dump-ndr-tree:s' => \$opt_dump_ndr_tree,
|
|
||||||
'samba3-ndr-client:s' => \$opt_samba3_ndr_client,
|
|
||||||
'samba3-ndr-server:s' => \$opt_samba3_ndr_server,
|
|
||||||
'samba3-template' => \$opt_samba3_template,
|
|
||||||
'header:s' => \$opt_header,
|
|
||||||
'server:s' => \$opt_server,
|
|
||||||
'typelib:s' => \$opt_typelib,
|
|
||||||
'tdr-parser:s' => \$opt_tdr_parser,
|
|
||||||
'template' => \$opt_template,
|
|
||||||
'ndr-parser:s' => \$opt_ndr_parser,
|
|
||||||
'client:s' => \$opt_client,
|
|
||||||
'ws-parser:s' => \$opt_ws_parser,
|
|
||||||
'python' => \$opt_python,
|
|
||||||
'diff' => \$opt_diff,
|
|
||||||
'dcom-proxy:s' => \$opt_dcom_proxy,
|
|
||||||
'com-header:s' => \$opt_com_header,
|
|
||||||
'quiet' => \$opt_quiet,
|
|
||||||
'verbose' => \$opt_verbose,
|
|
||||||
'warn-compat' => \$opt_warn_compat,
|
|
||||||
'includedir=s@' => \@opt_incdirs
|
|
||||||
);
|
|
||||||
|
|
||||||
if (not $result) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_help) {
|
|
||||||
ShowHelp();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_version) {
|
|
||||||
ShowVersion();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub process_file($)
|
|
||||||
{
|
|
||||||
my $idl_file = shift;
|
|
||||||
my $outputdir = $opt_outputdir;
|
|
||||||
my $pidl;
|
|
||||||
my $ndr;
|
|
||||||
|
|
||||||
my $basename = basename($idl_file, ".idl");
|
|
||||||
|
|
||||||
unless ($opt_quiet) { print "Compiling $idl_file\n"; }
|
|
||||||
|
|
||||||
if ($opt_parse_idl_tree) {
|
|
||||||
$pidl = LoadStructure($idl_file);
|
|
||||||
defined $pidl || die "Failed to load $idl_file";
|
|
||||||
} else {
|
|
||||||
require Parse::Pidl::IDL;
|
|
||||||
|
|
||||||
$pidl = Parse::Pidl::IDL::parse_file($idl_file, \@opt_incdirs);
|
|
||||||
defined $pidl || die "Failed to parse $idl_file";
|
|
||||||
}
|
|
||||||
|
|
||||||
require Parse::Pidl::Typelist;
|
|
||||||
Parse::Pidl::Typelist::LoadIdl($pidl, $basename);
|
|
||||||
|
|
||||||
if (defined($opt_dump_idl_tree)) {
|
|
||||||
my($pidl_file) = ($opt_dump_idl_tree or "$outputdir/$basename.pidl");
|
|
||||||
SaveStructure($pidl_file, $pidl) or die "Failed to save $pidl_file\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_dump_idl) {
|
|
||||||
require Parse::Pidl::Dump;
|
|
||||||
print Parse::Pidl::Dump($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_diff) {
|
|
||||||
my($tempfile) = "$outputdir/$basename.tmp";
|
|
||||||
FileSave($tempfile, IdlDump::Dump($pidl));
|
|
||||||
system("diff -wu $idl_file $tempfile");
|
|
||||||
unlink($tempfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
|
|
||||||
if (defined($opt_com_header)) {
|
|
||||||
require Parse::Pidl::Samba4::COM::Header;
|
|
||||||
my $res = Parse::Pidl::Samba4::COM::Header::Parse($pidl,"$outputdir/ndr_$basename.h");
|
|
||||||
if ($res) {
|
|
||||||
FileSave($comh_filename, $res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_dcom_proxy)) {
|
|
||||||
require Parse::Pidl::Samba4::COM::Proxy;
|
|
||||||
my $res = Parse::Pidl::Samba4::COM::Proxy::Parse($pidl,$comh_filename);
|
|
||||||
if ($res) {
|
|
||||||
my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
|
|
||||||
FileSave($client, $res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_warn_compat) {
|
|
||||||
require Parse::Pidl::Compat;
|
|
||||||
Parse::Pidl::Compat::Check($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
$pidl = Parse::Pidl::ODL::ODL2IDL($pidl, dirname($idl_file), \@opt_incdirs);
|
|
||||||
|
|
||||||
if (defined($opt_ws_parser)) {
|
|
||||||
require Parse::Pidl::Wireshark::NDR;
|
|
||||||
|
|
||||||
my $cnffile = $idl_file;
|
|
||||||
$cnffile =~ s/\.idl$/\.cnf/;
|
|
||||||
|
|
||||||
my $generator = new Parse::Pidl::Wireshark::NDR();
|
|
||||||
$generator->Initialize($cnffile);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (defined($opt_ws_parser) or
|
|
||||||
defined($opt_client) or
|
|
||||||
defined($opt_server) or
|
|
||||||
defined($opt_header) or
|
|
||||||
defined($opt_ndr_parser) or
|
|
||||||
defined($opt_python) or
|
|
||||||
defined($opt_dump_ndr_tree) or
|
|
||||||
defined($opt_samba3_header) or
|
|
||||||
defined($opt_samba3_parser) or
|
|
||||||
defined($opt_samba3_server) or
|
|
||||||
defined($opt_samba3_ndr_client) or
|
|
||||||
defined($opt_samba3_ndr_server)) {
|
|
||||||
require Parse::Pidl::NDR;
|
|
||||||
$ndr = Parse::Pidl::NDR::Parse($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_dump_ndr_tree)) {
|
|
||||||
my($ndr_file) = ($opt_dump_ndr_tree or "$outputdir/$basename.ndr");
|
|
||||||
SaveStructure($ndr_file, $ndr) or die "Failed to save $ndr_file\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $gen_header = ($opt_header or "$outputdir/$basename.h");
|
|
||||||
if (defined($opt_header)) {
|
|
||||||
require Parse::Pidl::Samba4::Header;
|
|
||||||
FileSave($gen_header, Parse::Pidl::Samba4::Header::Parse($ndr));
|
|
||||||
}
|
|
||||||
|
|
||||||
my $h_filename = "$outputdir/ndr_$basename.h";
|
|
||||||
my $c_header = "$outputdir/ndr_$basename\_c.h";
|
|
||||||
if (defined($opt_client) or defined($opt_samba3_ndr_client)) {
|
|
||||||
require Parse::Pidl::Samba4::NDR::Client;
|
|
||||||
my ($c_client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
|
|
||||||
$c_header = $c_client;
|
|
||||||
$c_header =~ s/\.c$/.h/;
|
|
||||||
|
|
||||||
my $generator = new Parse::Pidl::Samba4::NDR::Client();
|
|
||||||
my ($srcd,$hdrd) = $generator->Parse(
|
|
||||||
$ndr,$gen_header,$h_filename,$c_header);
|
|
||||||
|
|
||||||
FileSave($c_client, $srcd);
|
|
||||||
FileSave($c_header, $hdrd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_python)) {
|
|
||||||
require Parse::Pidl::Samba4::Python;
|
|
||||||
my $generator = new Parse::Pidl::Samba4::Python();
|
|
||||||
my ($prsr) = $generator->Parse($basename, $ndr,
|
|
||||||
"$outputdir/ndr_$basename\_c.h", $h_filename);
|
|
||||||
FileSave("$outputdir/py_$basename.c", $prsr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_server)) {
|
|
||||||
require Parse::Pidl::Samba4::NDR::Server;
|
|
||||||
|
|
||||||
FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba4::NDR::Server::Parse($ndr,$h_filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_ndr_parser)) {
|
|
||||||
my $parser_fname = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
|
|
||||||
require Parse::Pidl::Samba4::NDR::Parser;
|
|
||||||
my $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
|
||||||
my ($header,$parser) = $generator->Parse($ndr, $gen_header, $h_filename);
|
|
||||||
|
|
||||||
FileSave($parser_fname, $parser);
|
|
||||||
FileSave($h_filename, $header);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_ws_parser)) {
|
|
||||||
require Parse::Pidl::Wireshark::NDR;
|
|
||||||
my($eparser) = ($opt_ws_parser or "$outputdir/packet-dcerpc-$basename.c");
|
|
||||||
my $eheader = $eparser;
|
|
||||||
$eheader =~ s/\.c$/\.h/;
|
|
||||||
my $cnffile = $idl_file;
|
|
||||||
$cnffile =~ s/\.idl$/\.cnf/;
|
|
||||||
|
|
||||||
my $generator = new Parse::Pidl::Wireshark::NDR();
|
|
||||||
my ($dp, $dh) = $generator->Parse($ndr, $idl_file, $eheader, $cnffile);
|
|
||||||
FileSave($eparser, $dp) if defined($dp);
|
|
||||||
FileSave($eheader, $dh) if defined($dh);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_tdr_parser)) {
|
|
||||||
my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
|
|
||||||
my $tdr_header = $tdr_parser;
|
|
||||||
$tdr_header =~ s/\.c$/\.h/;
|
|
||||||
require Parse::Pidl::Samba4::TDR;
|
|
||||||
my $generator = new Parse::Pidl::Samba4::TDR();
|
|
||||||
my ($hdr,$prsr) = $generator->Parser($pidl, $tdr_header, $gen_header);
|
|
||||||
FileSave($tdr_parser, $prsr);
|
|
||||||
FileSave($tdr_header, $hdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_typelib)) {
|
|
||||||
my $typelib = ($opt_typelib or "$outputdir/$basename.tlb");
|
|
||||||
require Parse::Pidl::Typelist;
|
|
||||||
FileSave($typelib, Parse::Pidl::Typelist::GenerateTypeLib());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_template) {
|
|
||||||
require Parse::Pidl::Samba4::Template;
|
|
||||||
print Parse::Pidl::Samba4::Template::Parse($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_samba3_template) {
|
|
||||||
require Parse::Pidl::Samba3::Template;
|
|
||||||
print Parse::Pidl::Samba3::Template::Parse($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_samba3_ndr_client)) {
|
|
||||||
my $client = ($opt_samba3_ndr_client or "$outputdir/cli_$basename.c");
|
|
||||||
my $header = $client; $header =~ s/\.c$/\.h/;
|
|
||||||
require Parse::Pidl::Samba3::ClientNDR;
|
|
||||||
my $generator = new Parse::Pidl::Samba3::ClientNDR();
|
|
||||||
my ($c_code,$h_code) = $generator->Parse($ndr, $header, $c_header);
|
|
||||||
FileSave($client, $c_code);
|
|
||||||
FileSave($header, $h_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_samba3_ndr_server)) {
|
|
||||||
my $server = ($opt_samba3_ndr_server or "$outputdir/srv_$basename.c");
|
|
||||||
my $header = $server; $header =~ s/\.c$/\.h/;
|
|
||||||
require Parse::Pidl::Samba3::ServerNDR;
|
|
||||||
my ($c_code,$h_code) = Parse::Pidl::Samba3::ServerNDR::Parse($ndr, $header, $h_filename);
|
|
||||||
FileSave($server, $c_code);
|
|
||||||
FileSave($header, $h_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scalar(@ARGV) == 0) {
|
|
||||||
print "$Script: no input files\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
process_file($_) foreach (@ARGV);
|
|
202
bin/pidl/expr.yp
202
bin/pidl/expr.yp
|
@ -1,202 +0,0 @@
|
||||||
# expr.yp
|
|
||||||
# Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
# Published under the GNU GPL
|
|
||||||
#
|
|
||||||
%left '->'
|
|
||||||
%right '!' '~'
|
|
||||||
%left '*' '/' '%'
|
|
||||||
%left '+' '-'
|
|
||||||
%left '<<' '>>'
|
|
||||||
%left '>' '<'
|
|
||||||
%left '==' '!='
|
|
||||||
%left '&'
|
|
||||||
%left '|'
|
|
||||||
%left '&&'
|
|
||||||
%left '||'
|
|
||||||
%left '?' ':'
|
|
||||||
%left NEG DEREF ADDROF INV
|
|
||||||
%left '.'
|
|
||||||
|
|
||||||
%%
|
|
||||||
exp:
|
|
||||||
NUM
|
|
||||||
|
|
|
||||||
TEXT { "\"$_[1]\"" }
|
|
||||||
|
|
|
||||||
func
|
|
||||||
|
|
|
||||||
var
|
|
||||||
|
|
|
||||||
'~' exp %prec INV { "~$_[2]" }
|
|
||||||
|
|
|
||||||
exp '+' exp { "$_[1] + $_[3]" }
|
|
||||||
|
|
|
||||||
exp '-' exp { "$_[1] - $_[3]" }
|
|
||||||
|
|
|
||||||
exp '*' exp { "$_[1] * $_[3]" }
|
|
||||||
|
|
|
||||||
exp '%' exp { "$_[1] % $_[3]" }
|
|
||||||
|
|
|
||||||
exp '<' exp { "$_[1] < $_[3]" }
|
|
||||||
|
|
|
||||||
exp '>' exp { "$_[1] > $_[3]" }
|
|
||||||
|
|
|
||||||
exp '|' exp { "$_[1] | $_[3]" }
|
|
||||||
|
|
|
||||||
exp '==' exp { "$_[1] == $_[3]" }
|
|
||||||
|
|
|
||||||
exp '<=' exp { "$_[1] <= $_[3]" }
|
|
||||||
|
|
|
||||||
exp '=>' exp { "$_[1] => $_[3]" }
|
|
||||||
|
|
|
||||||
exp '<<' exp { "$_[1] << $_[3]" }
|
|
||||||
|
|
|
||||||
exp '>>' exp { "$_[1] >> $_[3]" }
|
|
||||||
|
|
|
||||||
exp '!=' exp { "$_[1] != $_[3]" }
|
|
||||||
|
|
|
||||||
exp '||' exp { "$_[1] || $_[3]" }
|
|
||||||
|
|
|
||||||
exp '&&' exp { "$_[1] && $_[3]" }
|
|
||||||
|
|
|
||||||
exp '&' exp { "$_[1] & $_[3]" }
|
|
||||||
|
|
|
||||||
exp '?' exp ':' exp { "$_[1]?$_[3]:$_[5]" }
|
|
||||||
|
|
|
||||||
'~' exp { "~$_[1]" }
|
|
||||||
|
|
|
||||||
'!' exp { "not $_[1]" }
|
|
||||||
|
|
|
||||||
exp '/' exp { "$_[1] / $_[3]" }
|
|
||||||
|
|
|
||||||
'-' exp %prec NEG { "-$_[2]" }
|
|
||||||
|
|
|
||||||
'&' exp %prec ADDROF { "&$_[2]" }
|
|
||||||
|
|
|
||||||
exp '^' exp { "$_[1]^$_[3]" }
|
|
||||||
|
|
|
||||||
'(' exp ')' { "($_[2])" }
|
|
||||||
;
|
|
||||||
|
|
||||||
possible_pointer:
|
|
||||||
VAR { $_[0]->_Lookup($_[1]) }
|
|
||||||
|
|
|
||||||
'*' possible_pointer %prec DEREF { $_[0]->_Dereference($_[2]); "*$_[2]" }
|
|
||||||
;
|
|
||||||
|
|
||||||
var:
|
|
||||||
possible_pointer { $_[0]->_Use($_[1]) }
|
|
||||||
|
|
|
||||||
var '.' VAR { $_[0]->_Use("$_[1].$_[3]") }
|
|
||||||
|
|
|
||||||
'(' var ')' { "($_[2])" }
|
|
||||||
|
|
|
||||||
var '->' VAR { $_[0]->_Use("*$_[1]"); $_[1]."->".$_[3] }
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
func:
|
|
||||||
VAR '(' opt_args ')' { "$_[1]($_[3])" }
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_args:
|
|
||||||
#empty
|
|
||||||
{ "" }
|
|
||||||
|
|
|
||||||
args
|
|
||||||
;
|
|
||||||
|
|
||||||
exp_or_possible_pointer:
|
|
||||||
exp
|
|
||||||
|
|
|
||||||
possible_pointer
|
|
||||||
;
|
|
||||||
|
|
||||||
args:
|
|
||||||
exp_or_possible_pointer
|
|
||||||
|
|
|
||||||
exp_or_possible_pointer ',' args { "$_[1], $_[3]" }
|
|
||||||
;
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
|
||||||
package Parse::Pidl::Expr;
|
|
||||||
|
|
||||||
sub _Lexer {
|
|
||||||
my($parser)=shift;
|
|
||||||
|
|
||||||
$parser->YYData->{INPUT}=~s/^[ \t]//;
|
|
||||||
|
|
||||||
for ($parser->YYData->{INPUT}) {
|
|
||||||
if (s/^(0x[0-9A-Fa-f]+)//) {
|
|
||||||
$parser->YYData->{LAST_TOKEN} = $1;
|
|
||||||
return('NUM',$1);
|
|
||||||
}
|
|
||||||
if (s/^([0-9]+(?:\.[0-9]+)?)//) {
|
|
||||||
$parser->YYData->{LAST_TOKEN} = $1;
|
|
||||||
return('NUM',$1);
|
|
||||||
}
|
|
||||||
if (s/^([A-Za-z_][A-Za-z0-9_]*)//) {
|
|
||||||
$parser->YYData->{LAST_TOKEN} = $1;
|
|
||||||
return('VAR',$1);
|
|
||||||
}
|
|
||||||
if (s/^\"(.*?)\"//) {
|
|
||||||
$parser->YYData->{LAST_TOKEN} = $1;
|
|
||||||
return('TEXT',$1);
|
|
||||||
}
|
|
||||||
if (s/^(==|!=|<=|>=|->|\|\||<<|>>|&&)//s) {
|
|
||||||
$parser->YYData->{LAST_TOKEN} = $1;
|
|
||||||
return($1,$1);
|
|
||||||
}
|
|
||||||
if (s/^(.)//s) {
|
|
||||||
$parser->YYData->{LAST_TOKEN} = $1;
|
|
||||||
return($1,$1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _Use($$)
|
|
||||||
{
|
|
||||||
my ($self, $x) = @_;
|
|
||||||
if (defined($self->YYData->{USE})) {
|
|
||||||
return $self->YYData->{USE}->($x);
|
|
||||||
}
|
|
||||||
return $x;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _Lookup($$)
|
|
||||||
{
|
|
||||||
my ($self, $x) = @_;
|
|
||||||
return $self->YYData->{LOOKUP}->($x);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _Dereference($$)
|
|
||||||
{
|
|
||||||
my ($self, $x) = @_;
|
|
||||||
if (defined($self->YYData->{DEREFERENCE})) {
|
|
||||||
$self->YYData->{DEREFERENCE}->($x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _Error($)
|
|
||||||
{
|
|
||||||
my ($self) = @_;
|
|
||||||
if (defined($self->YYData->{LAST_TOKEN})) {
|
|
||||||
$self->YYData->{ERROR}->("Parse error in `".$self->YYData->{FULL_INPUT}."' near `". $self->YYData->{LAST_TOKEN} . "'");
|
|
||||||
} else {
|
|
||||||
$self->YYData->{ERROR}->("Parse error in `".$self->YYData->{FULL_INPUT}."'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Run {
|
|
||||||
my($self, $data, $error, $lookup, $deref, $use) = @_;
|
|
||||||
|
|
||||||
$self->YYData->{FULL_INPUT} = $data;
|
|
||||||
$self->YYData->{INPUT} = $data;
|
|
||||||
$self->YYData->{LOOKUP} = $lookup;
|
|
||||||
$self->YYData->{DEREFERENCE} = $deref;
|
|
||||||
$self->YYData->{ERROR} = $error;
|
|
||||||
$self->YYData->{USE} = $use;
|
|
||||||
|
|
||||||
return $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error);
|
|
||||||
}
|
|
696
bin/pidl/idl.yp
696
bin/pidl/idl.yp
|
@ -1,696 +0,0 @@
|
||||||
########################
|
|
||||||
# IDL Parse::Yapp parser
|
|
||||||
# Copyright (C) Andrew Tridgell <tridge@samba.org>
|
|
||||||
# released under the GNU GPL version 3 or later
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# the precedence actually doesn't matter at all for this grammar, but
|
|
||||||
# by providing a precedence we reduce the number of conflicts
|
|
||||||
# enormously
|
|
||||||
%left '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ',' ';'
|
|
||||||
|
|
||||||
|
|
||||||
################
|
|
||||||
# grammar
|
|
||||||
%%
|
|
||||||
idl:
|
|
||||||
#empty { {} }
|
|
||||||
|
|
|
||||||
idl interface { push(@{$_[1]}, $_[2]); $_[1] }
|
|
||||||
|
|
|
||||||
idl coclass { push(@{$_[1]}, $_[2]); $_[1] }
|
|
||||||
|
|
|
||||||
idl import { push(@{$_[1]}, $_[2]); $_[1] }
|
|
||||||
|
|
|
||||||
idl include { push(@{$_[1]}, $_[2]); $_[1] }
|
|
||||||
|
|
|
||||||
idl importlib { push(@{$_[1]}, $_[2]); $_[1] }
|
|
||||||
|
|
|
||||||
idl cpp_quote { push(@{$_[1]}, $_[2]); $_[1] }
|
|
||||||
;
|
|
||||||
|
|
||||||
import:
|
|
||||||
'import' commalist ';'
|
|
||||||
{{
|
|
||||||
"TYPE" => "IMPORT",
|
|
||||||
"PATHS" => $_[2],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
include:
|
|
||||||
'include' commalist ';'
|
|
||||||
{{
|
|
||||||
"TYPE" => "INCLUDE",
|
|
||||||
"PATHS" => $_[2],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
importlib:
|
|
||||||
'importlib' commalist ';'
|
|
||||||
{{
|
|
||||||
"TYPE" => "IMPORTLIB",
|
|
||||||
"PATHS" => $_[2],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
commalist:
|
|
||||||
text { [ $_[1] ] }
|
|
||||||
|
|
|
||||||
commalist ',' text { push(@{$_[1]}, $_[3]); $_[1] }
|
|
||||||
;
|
|
||||||
|
|
||||||
coclass:
|
|
||||||
property_list 'coclass' identifier '{' interface_names '}' optional_semicolon
|
|
||||||
{{
|
|
||||||
"TYPE" => "COCLASS",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"NAME" => $_[3],
|
|
||||||
"DATA" => $_[5],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
interface_names:
|
|
||||||
#empty { {} }
|
|
||||||
|
|
|
||||||
interface_names 'interface' identifier ';' { push(@{$_[1]}, $_[2]); $_[1] }
|
|
||||||
;
|
|
||||||
|
|
||||||
interface:
|
|
||||||
property_list 'interface' identifier base_interface '{' definitions '}' optional_semicolon
|
|
||||||
{{
|
|
||||||
"TYPE" => "INTERFACE",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"NAME" => $_[3],
|
|
||||||
"BASE" => $_[4],
|
|
||||||
"DATA" => $_[6],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
base_interface:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
':' identifier { $_[2] }
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
cpp_quote:
|
|
||||||
'cpp_quote' '(' text ')'
|
|
||||||
{{
|
|
||||||
"TYPE" => "CPP_QUOTE",
|
|
||||||
"DATA" => $_[3],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
definitions:
|
|
||||||
definition { [ $_[1] ] }
|
|
||||||
|
|
|
||||||
definitions definition { push(@{$_[1]}, $_[2]); $_[1] }
|
|
||||||
;
|
|
||||||
|
|
||||||
definition:
|
|
||||||
function
|
|
||||||
|
|
|
||||||
const
|
|
||||||
|
|
|
||||||
typedef
|
|
||||||
|
|
|
||||||
typedecl
|
|
||||||
;
|
|
||||||
|
|
||||||
const:
|
|
||||||
'const' identifier pointers identifier '=' anytext ';'
|
|
||||||
{{
|
|
||||||
"TYPE" => "CONST",
|
|
||||||
"DTYPE" => $_[2],
|
|
||||||
"POINTERS" => $_[3],
|
|
||||||
"NAME" => $_[4],
|
|
||||||
"VALUE" => $_[6],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
|
|
|
||||||
'const' identifier pointers identifier array_len '=' anytext ';'
|
|
||||||
{{
|
|
||||||
"TYPE" => "CONST",
|
|
||||||
"DTYPE" => $_[2],
|
|
||||||
"POINTERS" => $_[3],
|
|
||||||
"NAME" => $_[4],
|
|
||||||
"ARRAY_LEN" => $_[5],
|
|
||||||
"VALUE" => $_[7],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
function:
|
|
||||||
property_list type identifier '(' element_list2 ')' ';'
|
|
||||||
{{
|
|
||||||
"TYPE" => "FUNCTION",
|
|
||||||
"NAME" => $_[3],
|
|
||||||
"RETURN_TYPE" => $_[2],
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"ELEMENTS" => $_[5],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
typedef:
|
|
||||||
property_list 'typedef' type pointers identifier array_len ';'
|
|
||||||
{{
|
|
||||||
"TYPE" => "TYPEDEF",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"NAME" => $_[5],
|
|
||||||
"DATA" => $_[3],
|
|
||||||
"POINTERS" => $_[4],
|
|
||||||
"ARRAY_LEN" => $_[6],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
usertype:
|
|
||||||
struct
|
|
||||||
|
|
|
||||||
union
|
|
||||||
|
|
|
||||||
enum
|
|
||||||
|
|
|
||||||
bitmap
|
|
||||||
|
|
|
||||||
pipe
|
|
||||||
;
|
|
||||||
|
|
||||||
typedecl:
|
|
||||||
usertype ';' { $_[1] }
|
|
||||||
;
|
|
||||||
|
|
||||||
sign:
|
|
||||||
'signed'
|
|
||||||
|
|
|
||||||
'unsigned'
|
|
||||||
;
|
|
||||||
|
|
||||||
existingtype:
|
|
||||||
sign identifier { ($_[1]?$_[1]:"signed") ." $_[2]" }
|
|
||||||
|
|
|
||||||
identifier
|
|
||||||
;
|
|
||||||
|
|
||||||
type:
|
|
||||||
usertype
|
|
||||||
|
|
|
||||||
existingtype
|
|
||||||
|
|
|
||||||
void { "void" }
|
|
||||||
;
|
|
||||||
|
|
||||||
enum_body:
|
|
||||||
'{' enum_elements '}' { $_[2] }
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_enum_body:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
enum_body
|
|
||||||
;
|
|
||||||
|
|
||||||
enum:
|
|
||||||
property_list 'enum' optional_identifier opt_enum_body
|
|
||||||
{{
|
|
||||||
"TYPE" => "ENUM",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"NAME" => $_[3],
|
|
||||||
"ELEMENTS" => $_[4],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
enum_elements:
|
|
||||||
enum_element { [ $_[1] ] }
|
|
||||||
|
|
|
||||||
enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] }
|
|
||||||
;
|
|
||||||
|
|
||||||
enum_element:
|
|
||||||
identifier
|
|
||||||
|
|
|
||||||
identifier '=' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
;
|
|
||||||
|
|
||||||
bitmap_body:
|
|
||||||
'{' opt_bitmap_elements '}' { $_[2] }
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_bitmap_body:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
bitmap_body
|
|
||||||
;
|
|
||||||
|
|
||||||
bitmap:
|
|
||||||
property_list 'bitmap' optional_identifier opt_bitmap_body
|
|
||||||
{{
|
|
||||||
"TYPE" => "BITMAP",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"NAME" => $_[3],
|
|
||||||
"ELEMENTS" => $_[4],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
bitmap_elements:
|
|
||||||
bitmap_element { [ $_[1] ] }
|
|
||||||
|
|
|
||||||
bitmap_elements ',' bitmap_element { push(@{$_[1]}, $_[3]); $_[1] }
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_bitmap_elements:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
bitmap_elements
|
|
||||||
;
|
|
||||||
|
|
||||||
bitmap_element:
|
|
||||||
identifier '=' anytext { "$_[1] ( $_[3] )" }
|
|
||||||
;
|
|
||||||
|
|
||||||
struct_body:
|
|
||||||
'{' element_list1 '}' { $_[2] }
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_struct_body:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
struct_body
|
|
||||||
;
|
|
||||||
|
|
||||||
struct:
|
|
||||||
property_list 'struct' optional_identifier opt_struct_body
|
|
||||||
{{
|
|
||||||
"TYPE" => "STRUCT",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"NAME" => $_[3],
|
|
||||||
"ELEMENTS" => $_[4],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
empty_element:
|
|
||||||
property_list ';'
|
|
||||||
{{
|
|
||||||
"NAME" => "",
|
|
||||||
"TYPE" => "EMPTY",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"POINTERS" => 0,
|
|
||||||
"ARRAY_LEN" => [],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
base_or_empty:
|
|
||||||
base_element ';'
|
|
||||||
|
|
|
||||||
empty_element;
|
|
||||||
|
|
||||||
optional_base_element:
|
|
||||||
property_list base_or_empty { $_[2]->{PROPERTIES} = FlattenHash([$_[1],$_[2]->{PROPERTIES}]); $_[2] }
|
|
||||||
;
|
|
||||||
|
|
||||||
union_elements:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
union_elements optional_base_element { push(@{$_[1]}, $_[2]); $_[1] }
|
|
||||||
;
|
|
||||||
|
|
||||||
union_body:
|
|
||||||
'{' union_elements '}' { $_[2] }
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_union_body:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
union_body
|
|
||||||
;
|
|
||||||
|
|
||||||
union:
|
|
||||||
property_list 'union' optional_identifier opt_union_body
|
|
||||||
{{
|
|
||||||
"TYPE" => "UNION",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"NAME" => $_[3],
|
|
||||||
"ELEMENTS" => $_[4],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
base_element:
|
|
||||||
property_list type pointers identifier array_len
|
|
||||||
{{
|
|
||||||
"NAME" => $_[4],
|
|
||||||
"TYPE" => $_[2],
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"POINTERS" => $_[3],
|
|
||||||
"ARRAY_LEN" => $_[5],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
pointers:
|
|
||||||
#empty
|
|
||||||
{ 0 }
|
|
||||||
|
|
|
||||||
pointers '*' { $_[1]+1 }
|
|
||||||
;
|
|
||||||
|
|
||||||
pipe:
|
|
||||||
property_list 'pipe' type
|
|
||||||
{{
|
|
||||||
"TYPE" => "PIPE",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"NAME" => undef,
|
|
||||||
"DATA" => {
|
|
||||||
"TYPE" => "STRUCT",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"NAME" => undef,
|
|
||||||
"ELEMENTS" => [{
|
|
||||||
"NAME" => "count",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"POINTERS" => 0,
|
|
||||||
"ARRAY_LEN" => [],
|
|
||||||
"TYPE" => "uint3264",
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
},{
|
|
||||||
"NAME" => "array",
|
|
||||||
"PROPERTIES" => $_[1],
|
|
||||||
"POINTERS" => 0,
|
|
||||||
"ARRAY_LEN" => [ "count" ],
|
|
||||||
"TYPE" => $_[3],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}],
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
},
|
|
||||||
"FILE" => $_[0]->YYData->{FILE},
|
|
||||||
"LINE" => $_[0]->YYData->{LINE},
|
|
||||||
}}
|
|
||||||
;
|
|
||||||
|
|
||||||
element_list1:
|
|
||||||
#empty
|
|
||||||
{ [] }
|
|
||||||
|
|
|
||||||
element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
|
|
||||||
;
|
|
||||||
|
|
||||||
optional_const:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
'const'
|
|
||||||
;
|
|
||||||
|
|
||||||
element_list2:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
'void'
|
|
||||||
|
|
|
||||||
optional_const base_element { [ $_[2] ] }
|
|
||||||
|
|
|
||||||
element_list2 ',' optional_const base_element { push(@{$_[1]}, $_[4]); $_[1] }
|
|
||||||
;
|
|
||||||
|
|
||||||
array_len:
|
|
||||||
#empty { [] }
|
|
||||||
|
|
|
||||||
'[' ']' array_len { push(@{$_[3]}, "*"); $_[3] }
|
|
||||||
|
|
|
||||||
'[' anytext ']' array_len { push(@{$_[4]}, "$_[2]"); $_[4] }
|
|
||||||
;
|
|
||||||
|
|
||||||
property_list:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
property_list '[' properties ']' { FlattenHash([$_[1],$_[3]]); }
|
|
||||||
;
|
|
||||||
|
|
||||||
properties:
|
|
||||||
property { $_[1] }
|
|
||||||
|
|
|
||||||
properties ',' property { FlattenHash([$_[1], $_[3]]); }
|
|
||||||
;
|
|
||||||
|
|
||||||
property:
|
|
||||||
identifier {{ "$_[1]" => "1" }}
|
|
||||||
|
|
|
||||||
identifier '(' commalisttext ')' {{ "$_[1]" => "$_[3]" }}
|
|
||||||
;
|
|
||||||
|
|
||||||
commalisttext:
|
|
||||||
anytext
|
|
||||||
|
|
|
||||||
commalisttext ',' anytext { "$_[1],$_[3]" }
|
|
||||||
;
|
|
||||||
|
|
||||||
anytext:
|
|
||||||
#empty
|
|
||||||
{ "" }
|
|
||||||
|
|
|
||||||
identifier
|
|
||||||
|
|
|
||||||
constant
|
|
||||||
|
|
|
||||||
text
|
|
||||||
|
|
|
||||||
anytext '-' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '.' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '*' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '>' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '<' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '|' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '&' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '/' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '?' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext ':' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '=' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '+' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '~' anytext { "$_[1]$_[2]$_[3]" }
|
|
||||||
|
|
|
||||||
anytext '(' commalisttext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
|
|
||||||
|
|
|
||||||
anytext '{' commalisttext '}' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
|
|
||||||
;
|
|
||||||
|
|
||||||
identifier:
|
|
||||||
IDENTIFIER
|
|
||||||
;
|
|
||||||
|
|
||||||
optional_identifier:
|
|
||||||
#empty { undef }
|
|
||||||
|
|
|
||||||
IDENTIFIER
|
|
||||||
;
|
|
||||||
|
|
||||||
constant:
|
|
||||||
CONSTANT
|
|
||||||
;
|
|
||||||
|
|
||||||
text:
|
|
||||||
TEXT { "\"$_[1]\"" }
|
|
||||||
;
|
|
||||||
|
|
||||||
optional_semicolon:
|
|
||||||
#empty
|
|
||||||
|
|
|
||||||
';'
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
#####################################
|
|
||||||
# start code
|
|
||||||
%%
|
|
||||||
|
|
||||||
use Parse::Pidl qw(error);
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# flatten an array of hashes into a single hash
|
|
||||||
sub FlattenHash($)
|
|
||||||
{
|
|
||||||
my $a = shift;
|
|
||||||
my %b;
|
|
||||||
for my $d (@{$a}) {
|
|
||||||
for my $k (keys %{$d}) {
|
|
||||||
$b{$k} = $d->{$k};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return \%b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# traverse a perl data structure removing any empty arrays or
|
|
||||||
# hashes and any hash elements that map to undef
|
|
||||||
sub CleanData($)
|
|
||||||
{
|
|
||||||
sub CleanData($);
|
|
||||||
my($v) = shift;
|
|
||||||
|
|
||||||
return undef if (not defined($v));
|
|
||||||
|
|
||||||
if (ref($v) eq "ARRAY") {
|
|
||||||
foreach my $i (0 .. $#{$v}) {
|
|
||||||
CleanData($v->[$i]);
|
|
||||||
}
|
|
||||||
# this removes any undefined elements from the array
|
|
||||||
@{$v} = grep { defined $_ } @{$v};
|
|
||||||
} elsif (ref($v) eq "HASH") {
|
|
||||||
foreach my $x (keys %{$v}) {
|
|
||||||
CleanData($v->{$x});
|
|
||||||
if (!defined $v->{$x}) {
|
|
||||||
delete($v->{$x});
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $v;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _Error {
|
|
||||||
if (exists $_[0]->YYData->{ERRMSG}) {
|
|
||||||
error($_[0]->YYData, $_[0]->YYData->{ERRMSG});
|
|
||||||
delete $_[0]->YYData->{ERRMSG};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $last_token = $_[0]->YYData->{LAST_TOKEN};
|
|
||||||
|
|
||||||
error($_[0]->YYData, "Syntax error near '$last_token'");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _Lexer($)
|
|
||||||
{
|
|
||||||
my($parser)=shift;
|
|
||||||
|
|
||||||
$parser->YYData->{INPUT} or return('',undef);
|
|
||||||
|
|
||||||
again:
|
|
||||||
$parser->YYData->{INPUT} =~ s/^[ \t]*//;
|
|
||||||
|
|
||||||
for ($parser->YYData->{INPUT}) {
|
|
||||||
if (/^\#/) {
|
|
||||||
# Linemarker format is described at
|
|
||||||
# http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
|
|
||||||
if (s/^\# (\d+) \"(.*?)\"(( \d+){1,4}|)//) {
|
|
||||||
$parser->YYData->{LINE} = $1-1;
|
|
||||||
$parser->YYData->{FILE} = $2;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
|
|
||||||
$parser->YYData->{LINE} = $1-1;
|
|
||||||
$parser->YYData->{FILE} = $2;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
if (s/^(\#.*)$//m) {
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (s/^(\n)//) {
|
|
||||||
$parser->YYData->{LINE}++;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
if (s/^\"(.*?)\"//) {
|
|
||||||
$parser->YYData->{LAST_TOKEN} = $1;
|
|
||||||
return('TEXT',$1);
|
|
||||||
}
|
|
||||||
if (s/^(\d+)(\W|$)/$2/) {
|
|
||||||
$parser->YYData->{LAST_TOKEN} = $1;
|
|
||||||
return('CONSTANT',$1);
|
|
||||||
}
|
|
||||||
if (s/^([\w_]+)//) {
|
|
||||||
$parser->YYData->{LAST_TOKEN} = $1;
|
|
||||||
if ($1 =~
|
|
||||||
/^(coclass|interface|import|importlib
|
|
||||||
|include|cpp_quote|typedef
|
|
||||||
|union|struct|enum|bitmap|pipe
|
|
||||||
|void|const|unsigned|signed)$/x) {
|
|
||||||
return $1;
|
|
||||||
}
|
|
||||||
return('IDENTIFIER',$1);
|
|
||||||
}
|
|
||||||
if (s/^(.)//s) {
|
|
||||||
$parser->YYData->{LAST_TOKEN} = $1;
|
|
||||||
return($1,$1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub parse_string
|
|
||||||
{
|
|
||||||
my ($data,$filename) = @_;
|
|
||||||
|
|
||||||
my $self = new Parse::Pidl::IDL;
|
|
||||||
|
|
||||||
$self->YYData->{FILE} = $filename;
|
|
||||||
$self->YYData->{INPUT} = $data;
|
|
||||||
$self->YYData->{LINE} = 0;
|
|
||||||
$self->YYData->{LAST_TOKEN} = "NONE";
|
|
||||||
|
|
||||||
my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
|
|
||||||
|
|
||||||
return CleanData($idl);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub parse_file($$)
|
|
||||||
{
|
|
||||||
my ($filename,$incdirs) = @_;
|
|
||||||
|
|
||||||
my $saved_delim = $/;
|
|
||||||
undef $/;
|
|
||||||
my $cpp = $ENV{CPP};
|
|
||||||
my $options = "";
|
|
||||||
if (! defined $cpp) {
|
|
||||||
if (defined $ENV{CC}) {
|
|
||||||
$cpp = "$ENV{CC}";
|
|
||||||
$options = "-E";
|
|
||||||
} else {
|
|
||||||
$cpp = "cpp";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
my $includes = join('',map { " -I$_" } @$incdirs);
|
|
||||||
my $data = `$cpp $options -D__PIDL__$includes -xc "$filename"`;
|
|
||||||
$/ = $saved_delim;
|
|
||||||
|
|
||||||
return parse_string($data, $filename);
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
###################################################
|
|
||||||
# package to parse IDL files and generate code for
|
|
||||||
# rpc functions in Samba
|
|
||||||
# Copyright tridge@samba.org 2000-2003
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(warning error fatal $VERSION);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw ( $VERSION );
|
|
||||||
|
|
||||||
$VERSION = '0.02';
|
|
||||||
|
|
||||||
sub warning
|
|
||||||
{
|
|
||||||
my ($l,$m) = @_;
|
|
||||||
if ($l) {
|
|
||||||
print STDERR "$l->{FILE}:$l->{LINE}: ";
|
|
||||||
}
|
|
||||||
print STDERR "warning: $m\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub error
|
|
||||||
{
|
|
||||||
my ($l,$m) = @_;
|
|
||||||
if ($l) {
|
|
||||||
print STDERR "$l->{FILE}:$l->{LINE}: ";
|
|
||||||
}
|
|
||||||
print STDERR "error: $m\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub fatal($$)
|
|
||||||
{
|
|
||||||
my ($e,$s) = @_;
|
|
||||||
die("$e->{FILE}:$e->{LINE}: $s\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,52 +0,0 @@
|
||||||
###################################################
|
|
||||||
# C utility functions for pidl
|
|
||||||
# Copyright jelmer@samba.org 2005-2007
|
|
||||||
# released under the GNU GPL
|
|
||||||
package Parse::Pidl::CUtil;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT = qw(get_pointer_to get_value_of get_array_element);
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
sub get_pointer_to($)
|
|
||||||
{
|
|
||||||
my $var_name = shift;
|
|
||||||
|
|
||||||
if ($var_name =~ /^\*(.*)$/) {
|
|
||||||
return $1;
|
|
||||||
} elsif ($var_name =~ /^\&(.*)$/) {
|
|
||||||
return "&($var_name)";
|
|
||||||
} else {
|
|
||||||
return "&$var_name";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_value_of($)
|
|
||||||
{
|
|
||||||
my $var_name = shift;
|
|
||||||
|
|
||||||
if ($var_name =~ /^\&(.*)$/) {
|
|
||||||
return $1;
|
|
||||||
} else {
|
|
||||||
return "*$var_name";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_array_element($$)
|
|
||||||
{
|
|
||||||
my ($var_name, $idx) = @_;
|
|
||||||
|
|
||||||
if ($var_name =~ /^\*.*$/) {
|
|
||||||
$var_name = "($var_name)";
|
|
||||||
} elsif ($var_name =~ /^\&.*$/) {
|
|
||||||
$var_name = "($var_name)";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "$var_name"."[$idx]";
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,168 +0,0 @@
|
||||||
###################################################
|
|
||||||
# IDL Compatibility checker
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Compat;
|
|
||||||
|
|
||||||
use Parse::Pidl qw(warning);
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
my %supported_properties = (
|
|
||||||
# interface
|
|
||||||
"helpstring" => ["INTERFACE", "FUNCTION"],
|
|
||||||
"version" => ["INTERFACE"],
|
|
||||||
"uuid" => ["INTERFACE"],
|
|
||||||
"endpoint" => ["INTERFACE"],
|
|
||||||
"pointer_default" => ["INTERFACE"],
|
|
||||||
"no_srv_register" => ["INTERFACE"],
|
|
||||||
|
|
||||||
# dcom
|
|
||||||
"object" => ["INTERFACE"],
|
|
||||||
"local" => ["INTERFACE", "FUNCTION"],
|
|
||||||
"iid_is" => ["ELEMENT"],
|
|
||||||
"call_as" => ["FUNCTION"],
|
|
||||||
"idempotent" => ["FUNCTION"],
|
|
||||||
|
|
||||||
# function
|
|
||||||
"in" => ["ELEMENT"],
|
|
||||||
"out" => ["ELEMENT"],
|
|
||||||
|
|
||||||
# pointer
|
|
||||||
"ref" => ["ELEMENT"],
|
|
||||||
"ptr" => ["ELEMENT"],
|
|
||||||
"unique" => ["ELEMENT"],
|
|
||||||
"ignore" => ["ELEMENT"],
|
|
||||||
|
|
||||||
"value" => ["ELEMENT"],
|
|
||||||
|
|
||||||
# generic
|
|
||||||
"public" => ["FUNCTION", "TYPEDEF"],
|
|
||||||
"nopush" => ["FUNCTION", "TYPEDEF"],
|
|
||||||
"nopull" => ["FUNCTION", "TYPEDEF"],
|
|
||||||
"noprint" => ["FUNCTION", "TYPEDEF"],
|
|
||||||
"nopython" => ["FUNCTION", "TYPEDEF"],
|
|
||||||
|
|
||||||
# union
|
|
||||||
"switch_is" => ["ELEMENT"],
|
|
||||||
"switch_type" => ["ELEMENT", "TYPEDEF"],
|
|
||||||
"case" => ["ELEMENT"],
|
|
||||||
"default" => ["ELEMENT"],
|
|
||||||
|
|
||||||
# subcontext
|
|
||||||
"subcontext" => ["ELEMENT"],
|
|
||||||
"subcontext_size" => ["ELEMENT"],
|
|
||||||
|
|
||||||
# enum
|
|
||||||
"enum16bit" => ["TYPEDEF"],
|
|
||||||
"v1_enum" => ["TYPEDEF"],
|
|
||||||
|
|
||||||
# bitmap
|
|
||||||
"bitmap8bit" => ["TYPEDEF"],
|
|
||||||
"bitmap16bit" => ["TYPEDEF"],
|
|
||||||
"bitmap32bit" => ["TYPEDEF"],
|
|
||||||
"bitmap64bit" => ["TYPEDEF"],
|
|
||||||
|
|
||||||
# array
|
|
||||||
"range" => ["ELEMENT"],
|
|
||||||
"size_is" => ["ELEMENT"],
|
|
||||||
"string" => ["ELEMENT"],
|
|
||||||
"noheader" => ["ELEMENT"],
|
|
||||||
"charset" => ["ELEMENT"],
|
|
||||||
"length_is" => ["ELEMENT"],
|
|
||||||
);
|
|
||||||
|
|
||||||
sub CheckTypedef($)
|
|
||||||
{
|
|
||||||
my ($td) = @_;
|
|
||||||
|
|
||||||
if (has_property($td, "nodiscriminant")) {
|
|
||||||
warning($td, "nodiscriminant property not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($td->{TYPE} eq "BITMAP") {
|
|
||||||
warning($td, "converting bitmap to scalar");
|
|
||||||
#FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($td, "gensize")) {
|
|
||||||
warning($td, "ignoring gensize() property. ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($td, "enum8bit") and has_property($td, "enum16bit")) {
|
|
||||||
warning($td, "8 and 16 bit enums not supported, converting to scalar");
|
|
||||||
#FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
StripProperties($td);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CheckElement($)
|
|
||||||
{
|
|
||||||
my $e = shift;
|
|
||||||
|
|
||||||
if (has_property($e, "noheader")) {
|
|
||||||
warning($e, "noheader property not supported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "subcontext")) {
|
|
||||||
warning($e, "converting subcontext to byte array");
|
|
||||||
#FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "compression")) {
|
|
||||||
warning($e, "compression() property not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "sptr")) {
|
|
||||||
warning($e, "sptr() pointer property not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "relative")) {
|
|
||||||
warning($e, "relative() pointer property not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "relative_short")) {
|
|
||||||
warning($e, "relative_short() pointer property not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "flag")) {
|
|
||||||
warning($e, "ignoring flag() property");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "value")) {
|
|
||||||
warning($e, "ignoring value() property");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CheckFunction($)
|
|
||||||
{
|
|
||||||
my $fn = shift;
|
|
||||||
|
|
||||||
if (has_property($fn, "noopnum")) {
|
|
||||||
warning($fn, "noopnum not converted. Opcodes will be out of sync.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CheckInterface($)
|
|
||||||
{
|
|
||||||
my $if = shift;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Check($)
|
|
||||||
{
|
|
||||||
my $pidl = shift;
|
|
||||||
my $nidl = [];
|
|
||||||
|
|
||||||
foreach (@{$pidl}) {
|
|
||||||
push (@$nidl, CheckInterface($_)) if ($_->{TYPE} eq "INTERFACE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,294 +0,0 @@
|
||||||
###################################################
|
|
||||||
# dump function for IDL structures
|
|
||||||
# Copyright tridge@samba.org 2000
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
Parse::Pidl::Dump - Dump support
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
This module provides functions that can generate IDL code from
|
|
||||||
internal pidl data structures.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
package Parse::Pidl::Dump;
|
|
||||||
|
|
||||||
use Exporter;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(DumpType DumpTypedef DumpStruct DumpEnum DumpBitmap DumpUnion DumpFunction);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a properties list
|
|
||||||
sub DumpProperties($)
|
|
||||||
{
|
|
||||||
my($props) = shift;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
foreach my $d ($props) {
|
|
||||||
foreach my $k (sort(keys %{$d})) {
|
|
||||||
if ($k eq "in") {
|
|
||||||
$res .= "[in] ";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if ($k eq "out") {
|
|
||||||
$res .= "[out] ";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if ($k eq "ref") {
|
|
||||||
$res .= "[ref] ";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
$res .= "[$k($d->{$k})] ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a structure element
|
|
||||||
sub DumpElement($)
|
|
||||||
{
|
|
||||||
my($element) = shift;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
(defined $element->{PROPERTIES}) &&
|
|
||||||
($res .= DumpProperties($element->{PROPERTIES}));
|
|
||||||
$res .= DumpType($element->{TYPE});
|
|
||||||
$res .= " ";
|
|
||||||
for my $i (1..$element->{POINTERS}) {
|
|
||||||
$res .= "*";
|
|
||||||
}
|
|
||||||
$res .= "$element->{NAME}";
|
|
||||||
foreach (@{$element->{ARRAY_LEN}}) {
|
|
||||||
$res .= "[$_]";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a struct
|
|
||||||
sub DumpStruct($)
|
|
||||||
{
|
|
||||||
my($struct) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= "struct ";
|
|
||||||
if ($struct->{NAME}) {
|
|
||||||
$res.="$struct->{NAME} ";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res.="{\n";
|
|
||||||
if (defined $struct->{ELEMENTS}) {
|
|
||||||
foreach (@{$struct->{ELEMENTS}}) {
|
|
||||||
$res .= "\t" . DumpElement($_) . ";\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$res .= "}";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a struct
|
|
||||||
sub DumpEnum($)
|
|
||||||
{
|
|
||||||
my($enum) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= "enum {\n";
|
|
||||||
|
|
||||||
foreach (@{$enum->{ELEMENTS}}) {
|
|
||||||
if (/^([A-Za-z0-9_]+)[ \t]*\((.*)\)$/) {
|
|
||||||
$res .= "\t$1 = $2,\n";
|
|
||||||
} else {
|
|
||||||
$res .= "\t$_,\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res.= "}";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a struct
|
|
||||||
sub DumpBitmap($)
|
|
||||||
{
|
|
||||||
my($bitmap) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= "bitmap {\n";
|
|
||||||
|
|
||||||
foreach (@{$bitmap->{ELEMENTS}}) {
|
|
||||||
if (/^([A-Za-z0-9_]+)[ \t]*\((.*)\)$/) {
|
|
||||||
$res .= "\t$1 = $2,\n";
|
|
||||||
} else {
|
|
||||||
die ("Bitmap $bitmap->{NAME} has field $_ without proper value");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res.= "}";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a union element
|
|
||||||
sub DumpUnionElement($)
|
|
||||||
{
|
|
||||||
my($element) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
if (has_property($element, "default")) {
|
|
||||||
$res .= "[default] ;\n";
|
|
||||||
} else {
|
|
||||||
$res .= "[case($element->{PROPERTIES}->{case})] ";
|
|
||||||
$res .= DumpElement($element), if defined($element);
|
|
||||||
$res .= ";\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a union
|
|
||||||
sub DumpUnion($)
|
|
||||||
{
|
|
||||||
my($union) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
(defined $union->{PROPERTIES}) &&
|
|
||||||
($res .= DumpProperties($union->{PROPERTIES}));
|
|
||||||
$res .= "union {\n";
|
|
||||||
foreach my $e (@{$union->{ELEMENTS}}) {
|
|
||||||
$res .= DumpUnionElement($e);
|
|
||||||
}
|
|
||||||
$res .= "}";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a type
|
|
||||||
sub DumpType($)
|
|
||||||
{
|
|
||||||
my($data) = shift;
|
|
||||||
|
|
||||||
if (ref($data) eq "HASH") {
|
|
||||||
return DumpStruct($data) if ($data->{TYPE} eq "STRUCT");
|
|
||||||
return DumpUnion($data) if ($data->{TYPE} eq "UNION");
|
|
||||||
return DumpEnum($data) if ($data->{TYPE} eq "ENUM");
|
|
||||||
return DumpBitmap($data) if ($data->{TYPE} eq "BITMAP");
|
|
||||||
} else {
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a typedef
|
|
||||||
sub DumpTypedef($)
|
|
||||||
{
|
|
||||||
my($typedef) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= "typedef ";
|
|
||||||
$res .= DumpType($typedef->{DATA});
|
|
||||||
$res .= " $typedef->{NAME};\n\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a typedef
|
|
||||||
sub DumpFunction($)
|
|
||||||
{
|
|
||||||
my($function) = shift;
|
|
||||||
my($first) = 1;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= DumpType($function->{RETURN_TYPE});
|
|
||||||
$res .= " $function->{NAME}(\n";
|
|
||||||
for my $d (@{$function->{ELEMENTS}}) {
|
|
||||||
unless ($first) { $res .= ",\n"; } $first = 0;
|
|
||||||
$res .= DumpElement($d);
|
|
||||||
}
|
|
||||||
$res .= "\n);\n\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a module header
|
|
||||||
sub DumpInterfaceProperties($)
|
|
||||||
{
|
|
||||||
my($header) = shift;
|
|
||||||
my($data) = $header->{DATA};
|
|
||||||
my($first) = 1;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= "[\n";
|
|
||||||
foreach my $k (sort(keys %{$data})) {
|
|
||||||
$first || ($res .= ",\n"); $first = 0;
|
|
||||||
$res .= "$k($data->{$k})";
|
|
||||||
}
|
|
||||||
$res .= "\n]\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump the interface definitions
|
|
||||||
sub DumpInterface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res .= DumpInterfaceProperties($interface->{PROPERTIES});
|
|
||||||
|
|
||||||
$res .= "interface $interface->{NAME}\n{\n";
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
($d->{TYPE} eq "TYPEDEF") &&
|
|
||||||
($res .= DumpTypedef($d));
|
|
||||||
($d->{TYPE} eq "FUNCTION") &&
|
|
||||||
($res .= DumpFunction($d));
|
|
||||||
}
|
|
||||||
$res .= "}\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dump a parsed IDL structure back into an IDL file
|
|
||||||
sub Dump($)
|
|
||||||
{
|
|
||||||
my($idl) = shift;
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
$res = "/* Dumped by pidl */\n\n";
|
|
||||||
foreach my $x (@{$idl}) {
|
|
||||||
($x->{TYPE} eq "INTERFACE") &&
|
|
||||||
($res .= DumpInterface($x));
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,130 +0,0 @@
|
||||||
##########################################
|
|
||||||
# Converts ODL stuctures to IDL structures
|
|
||||||
# (C) 2004-2005, 2008 Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
|
|
||||||
package Parse::Pidl::ODL;
|
|
||||||
|
|
||||||
use Parse::Pidl qw(error);
|
|
||||||
use Parse::Pidl::IDL;
|
|
||||||
use Parse::Pidl::Util qw(has_property unmake_str);
|
|
||||||
use Parse::Pidl::Typelist qw(hasType getType);
|
|
||||||
use File::Basename;
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
sub FunctionAddObjArgs($)
|
|
||||||
{
|
|
||||||
my $e = shift;
|
|
||||||
|
|
||||||
unshift(@{$e->{ELEMENTS}}, {
|
|
||||||
'NAME' => 'ORPCthis',
|
|
||||||
'POINTERS' => 0,
|
|
||||||
'PROPERTIES' => { 'in' => '1' },
|
|
||||||
'TYPE' => 'ORPCTHIS',
|
|
||||||
'FILE' => $e->{FILE},
|
|
||||||
'LINE' => $e->{LINE}
|
|
||||||
});
|
|
||||||
unshift(@{$e->{ELEMENTS}}, {
|
|
||||||
'NAME' => 'ORPCthat',
|
|
||||||
'POINTERS' => 1,
|
|
||||||
'PROPERTIES' => { 'out' => '1', 'ref' => '1' },
|
|
||||||
'TYPE' => 'ORPCTHAT',
|
|
||||||
'FILE' => $e->{FILE},
|
|
||||||
'LINE' => $e->{LINE}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ReplaceInterfacePointers($)
|
|
||||||
{
|
|
||||||
my ($e) = @_;
|
|
||||||
foreach my $x (@{$e->{ELEMENTS}}) {
|
|
||||||
next unless (hasType($x->{TYPE}));
|
|
||||||
next unless getType($x->{TYPE})->{DATA}->{TYPE} eq "INTERFACE";
|
|
||||||
|
|
||||||
$x->{TYPE} = "MInterfacePointer";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add ORPC specific bits to an interface.
|
|
||||||
sub ODL2IDL
|
|
||||||
{
|
|
||||||
my ($odl, $basedir, $opt_incdirs) = (@_);
|
|
||||||
my $addedorpc = 0;
|
|
||||||
my $interfaces = {};
|
|
||||||
|
|
||||||
foreach my $x (@$odl) {
|
|
||||||
if ($x->{TYPE} eq "IMPORT") {
|
|
||||||
foreach my $idl_file (@{$x->{PATHS}}) {
|
|
||||||
$idl_file = unmake_str($idl_file);
|
|
||||||
my $idl_path = undef;
|
|
||||||
foreach ($basedir, @$opt_incdirs) {
|
|
||||||
if (-f "$_/$idl_file") {
|
|
||||||
$idl_path = "$_/$idl_file";
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unless ($idl_path) {
|
|
||||||
error($x, "Unable to open include file `$idl_file'");
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
my $podl = Parse::Pidl::IDL::parse_file($idl_path, $opt_incdirs);
|
|
||||||
if (defined($podl)) {
|
|
||||||
require Parse::Pidl::Typelist;
|
|
||||||
my $basename = basename($idl_path, ".idl");
|
|
||||||
|
|
||||||
Parse::Pidl::Typelist::LoadIdl($podl, $basename);
|
|
||||||
my $pidl = ODL2IDL($podl, $basedir, $opt_incdirs);
|
|
||||||
|
|
||||||
foreach my $y (@$pidl) {
|
|
||||||
if ($y->{TYPE} eq "INTERFACE") {
|
|
||||||
$interfaces->{$y->{NAME}} = $y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error($x, "Failed to parse $idl_path");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($x->{TYPE} eq "INTERFACE") {
|
|
||||||
$interfaces->{$x->{NAME}} = $x;
|
|
||||||
# Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
|
|
||||||
# and replace interfacepointers with MInterfacePointer
|
|
||||||
# for 'object' interfaces
|
|
||||||
if (has_property($x, "object")) {
|
|
||||||
foreach my $e (@{$x->{DATA}}) {
|
|
||||||
($e->{TYPE} eq "FUNCTION") && FunctionAddObjArgs($e);
|
|
||||||
ReplaceInterfacePointers($e);
|
|
||||||
}
|
|
||||||
$addedorpc = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($x->{BASE}) {
|
|
||||||
my $base = $interfaces->{$x->{BASE}};
|
|
||||||
|
|
||||||
unless (defined($base)) {
|
|
||||||
error($x, "Undefined base interface `$x->{BASE}'");
|
|
||||||
} else {
|
|
||||||
foreach my $fn (reverse @{$base->{DATA}}) {
|
|
||||||
next unless ($fn->{TYPE} eq "FUNCTION");
|
|
||||||
push (@{$x->{INHERITED_FUNCTIONS}}, $fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unshift (@$odl, {
|
|
||||||
TYPE => "IMPORT",
|
|
||||||
PATHS => [ "\"orpc.idl\"" ],
|
|
||||||
FILE => undef,
|
|
||||||
LINE => undef
|
|
||||||
}) if ($addedorpc);
|
|
||||||
|
|
||||||
|
|
||||||
return $odl;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,409 +0,0 @@
|
||||||
###################################################
|
|
||||||
# Samba3 client generator for IDL structures
|
|
||||||
# on top of Samba4 style NDR functions
|
|
||||||
# Copyright jelmer@samba.org 2005-2006
|
|
||||||
# Copyright gd@samba.org 2008
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba3::ClientNDR;
|
|
||||||
|
|
||||||
use Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(ParseFunction $res $res_hdr);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Parse::Pidl qw(fatal warning error);
|
|
||||||
use Parse::Pidl::Util qw(has_property ParseExpr genpad);
|
|
||||||
use Parse::Pidl::NDR qw(ContainsPipe);
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
|
||||||
use Parse::Pidl::Samba4 qw(DeclLong);
|
|
||||||
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; }
|
|
||||||
sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); }
|
|
||||||
sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; }
|
|
||||||
sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; }
|
|
||||||
sub fn_declare($$) { my ($self,$n) = @_; $self->pidl($n); $self->pidl_hdr("$n;"); }
|
|
||||||
|
|
||||||
sub new($)
|
|
||||||
{
|
|
||||||
my ($class) = shift;
|
|
||||||
my $self = { res => "", res_hdr => "", tabs => "" };
|
|
||||||
bless($self, $class);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ElementDirection($)
|
|
||||||
{
|
|
||||||
my ($e) = @_;
|
|
||||||
|
|
||||||
return "[in,out]" 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 "[in,out]";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub HeaderProperties($$)
|
|
||||||
{
|
|
||||||
my($props,$ignores) = @_;
|
|
||||||
my $ret = "";
|
|
||||||
|
|
||||||
foreach my $d (sort(keys %{$props})) {
|
|
||||||
next if (grep(/^$d$/, @$ignores));
|
|
||||||
if($props->{$d} ne "1") {
|
|
||||||
$ret.= "$d($props->{$d}),";
|
|
||||||
} else {
|
|
||||||
$ret.="$d,";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ret) {
|
|
||||||
return "[" . substr($ret, 0, -1) . "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseInvalidResponse($$)
|
|
||||||
{
|
|
||||||
my ($self, $type) = @_;
|
|
||||||
|
|
||||||
if ($type eq "sync") {
|
|
||||||
$self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;");
|
|
||||||
} elsif ($type eq "async") {
|
|
||||||
$self->pidl("tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);");
|
|
||||||
$self->pidl("return;");
|
|
||||||
} else {
|
|
||||||
die("ParseInvalidResponse($type)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionAsyncState($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
|
||||||
my $done_fn = "rpccli_$fn->{NAME}_done";
|
|
||||||
|
|
||||||
$self->pidl("$state_str {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl(mapTypeName($fn->{RETURN_TYPE}). " result;");
|
|
||||||
}
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("};");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("static void $done_fn(struct tevent_req *subreq);");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionAsyncSend($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
my $fn_args = "";
|
|
||||||
my $uif = uc($if);
|
|
||||||
my $ufn = "NDR_".uc($fn->{NAME});
|
|
||||||
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
|
||||||
my $done_fn = "rpccli_$fn->{NAME}_done";
|
|
||||||
my $out_mem_ctx = "rpccli_$fn->{NAME}_out_memory";
|
|
||||||
my $fn_str = "struct tevent_req *rpccli_$fn->{NAME}_send";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "TALLOC_CTX *mem_ctx";
|
|
||||||
$fn_args .= ",\n" . $pad . "struct tevent_context *ev";
|
|
||||||
$fn_args .= ",\n" . $pad . "struct rpc_pipe_client *cli";
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
my $dir = ElementDirection($_);
|
|
||||||
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
|
||||||
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct tevent_req *req;");
|
|
||||||
$self->pidl("$state_str *state;");
|
|
||||||
$self->pidl("struct tevent_req *subreq;");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
|
||||||
$self->pidl("\t\t\t$state_str);");
|
|
||||||
$self->pidl("if (req == NULL) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return NULL;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("state->out_mem_ctx = NULL;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
my $out_params = 0;
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
if (grep(/out/, @{$_->{DIRECTION}})) {
|
|
||||||
$out_params++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($out_params > 0) {
|
|
||||||
$self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,");
|
|
||||||
$self->pidl("\t\t \"$out_mem_ctx\");");
|
|
||||||
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$fn_str = "subreq = dcerpc_$fn->{NAME}_send";
|
|
||||||
$pad = "\t" . genpad($fn_str);
|
|
||||||
$fn_args = "state,\n" . $pad . "ev,\n" . $pad . "cli->binding_handle";
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
$fn_args .= ",\n" . $pad . "_". $_->{NAME};
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("$fn_str($fn_args);");
|
|
||||||
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("tevent_req_set_callback(subreq, $done_fn, req);");
|
|
||||||
$self->pidl("return req;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionAsyncDone($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
|
||||||
my $done_fn = "rpccli_$fn->{NAME}_done";
|
|
||||||
|
|
||||||
$self->pidl("static void $done_fn(struct tevent_req *subreq)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct tevent_req *req = tevent_req_callback_data(");
|
|
||||||
$self->pidl("\tsubreq, struct tevent_req);");
|
|
||||||
$self->pidl("$state_str *state = tevent_req_data(");
|
|
||||||
$self->pidl("\treq, $state_str);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("TALLOC_CTX *mem_ctx;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("if (state->out_mem_ctx) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("mem_ctx = state->out_mem_ctx;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("} else {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("mem_ctx = state;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
my $fn_str = "status = dcerpc_$fn->{NAME}_recv";
|
|
||||||
my $pad = "\t" . genpad($fn_str);
|
|
||||||
my $fn_args = "subreq,\n" . $pad . "mem_ctx";
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$fn_args .= ",\n" . $pad . "&state->result";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("$fn_str($fn_args);");
|
|
||||||
$self->pidl("TALLOC_FREE(subreq);");
|
|
||||||
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("tevent_req_nterror(req, status);");
|
|
||||||
$self->pidl("return;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_done(req);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionAsyncRecv($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
my $fn_args = "";
|
|
||||||
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
|
||||||
my $fn_str = "NTSTATUS rpccli_$fn->{NAME}_recv";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "struct tevent_req *req,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$fn_args .= ",\n" . $pad . "$fn->{RETURN_TYPE} *result";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("$state_str *state = tevent_req_data(");
|
|
||||||
$self->pidl("\treq, $state_str);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return status;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Steal possible out parameters to the callers context */");
|
|
||||||
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl("/* Return result */");
|
|
||||||
$self->pidl("*result = state->result;");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionSync($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
my $fn_args = "";
|
|
||||||
my $uif = uc($if);
|
|
||||||
my $ufn = "NDR_".uc($fn->{NAME});
|
|
||||||
my $fn_str = "NTSTATUS rpccli_$fn->{NAME}";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "struct rpc_pipe_client *cli,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
my $dir = ElementDirection($_);
|
|
||||||
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
|
||||||
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE}) && ($fn->{RETURN_TYPE} eq "WERROR")) {
|
|
||||||
$fn_args .= ",\n" . $pad . "WERROR *werror";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl(mapTypeName($fn->{RETURN_TYPE})." result;");
|
|
||||||
}
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$fn_str = "status = dcerpc_$fn->{NAME}";
|
|
||||||
$pad = "\t" . genpad($fn_str);
|
|
||||||
$fn_args = "cli->binding_handle,\n" . $pad . "mem_ctx";
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
$fn_args .= ",\n" . $pad . "_". $_->{NAME};
|
|
||||||
}
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$fn_args .= ",\n" . $pad . "&result";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("$fn_str($fn_args);");
|
|
||||||
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return status;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Return result */");
|
|
||||||
if (not $fn->{RETURN_TYPE}) {
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
} elsif ($fn->{RETURN_TYPE} eq "NTSTATUS") {
|
|
||||||
$self->pidl("return result;");
|
|
||||||
} elsif ($fn->{RETURN_TYPE} eq "WERROR") {
|
|
||||||
$self->pidl("if (werror) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("*werror = result;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("return werror_to_ntstatus(result);");
|
|
||||||
} else {
|
|
||||||
warning($fn->{ORIGINAL}, "Unable to convert $fn->{RETURN_TYPE} to NTSTATUS");
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
$self->ParseFunctionAsyncState($if, $fn);
|
|
||||||
$self->ParseFunctionAsyncSend($if, $fn);
|
|
||||||
$self->ParseFunctionAsyncDone($if, $fn);
|
|
||||||
$self->ParseFunctionAsyncRecv($if, $fn);
|
|
||||||
|
|
||||||
$self->ParseFunctionSync($if, $fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseInterface($$)
|
|
||||||
{
|
|
||||||
my ($self, $if) = @_;
|
|
||||||
|
|
||||||
my $uif = uc($if->{NAME});
|
|
||||||
|
|
||||||
$self->pidl_hdr("#ifndef __CLI_$uif\__");
|
|
||||||
$self->pidl_hdr("#define __CLI_$uif\__");
|
|
||||||
foreach my $fn (@{$if->{FUNCTIONS}}) {
|
|
||||||
next if has_property($fn, "noopnum");
|
|
||||||
next if has_property($fn, "todo");
|
|
||||||
|
|
||||||
my $skip = 0;
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
if (ContainsPipe($e, $e->{LEVELS}[0])) {
|
|
||||||
$skip = 1;
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
next if $skip;
|
|
||||||
|
|
||||||
$self->ParseFunction($if->{NAME}, $fn);
|
|
||||||
}
|
|
||||||
$self->pidl_hdr("#endif /* __CLI_$uif\__ */");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$$$)
|
|
||||||
{
|
|
||||||
my($self,$ndr,$header,$c_header) = @_;
|
|
||||||
|
|
||||||
$self->pidl("/*");
|
|
||||||
$self->pidl(" * Unix SMB/CIFS implementation.");
|
|
||||||
$self->pidl(" * client auto-generated by pidl. DO NOT MODIFY!");
|
|
||||||
$self->pidl(" */");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("#include \"includes.h\"");
|
|
||||||
$self->pidl("#include \"$header\"");
|
|
||||||
$self->pidl_hdr("#include \"$c_header\"");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
foreach (@$ndr) {
|
|
||||||
$self->ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($self->{res}, $self->{res_hdr});
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,322 +0,0 @@
|
||||||
###################################################
|
|
||||||
# Samba3 server generator for IDL structures
|
|
||||||
# on top of Samba4 style NDR functions
|
|
||||||
# Copyright jelmer@samba.org 2005-2006
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba3::ServerNDR;
|
|
||||||
|
|
||||||
use Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(DeclLevel);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Parse::Pidl qw(warning error fatal);
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
|
|
||||||
use Parse::Pidl::Util qw(ParseExpr has_property is_constant);
|
|
||||||
use Parse::Pidl::NDR qw(GetNextLevel ContainsPipe);
|
|
||||||
use Parse::Pidl::Samba4 qw(ElementStars DeclLong);
|
|
||||||
use Parse::Pidl::Samba4::Header qw(GenerateFunctionOutEnv);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
my $res;
|
|
||||||
my $res_hdr;
|
|
||||||
my $tabs = "";
|
|
||||||
sub pidl_reset() { $res=""; $res_hdr="", $tabs=""; }
|
|
||||||
sub pidl_return() { my $s = $res; my $h = $res_hdr; pidl_reset(); return ($s, $h) }
|
|
||||||
sub indent() { $tabs.="\t"; }
|
|
||||||
sub deindent() { $tabs = substr($tabs, 1); }
|
|
||||||
sub pidl($) { my ($txt) = @_; $res .= $txt?$tabs.(shift)."\n":"\n"; }
|
|
||||||
sub pidl_hdr($) { $res_hdr .= (shift)."\n"; }
|
|
||||||
sub fn_declare($) { my ($n) = @_; pidl $n; pidl_hdr "$n;"; }
|
|
||||||
|
|
||||||
sub DeclLevel($$)
|
|
||||||
{
|
|
||||||
my ($e, $l) = @_;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
$res .= "const char";
|
|
||||||
} else {
|
|
||||||
$res .= mapTypeName($e->{TYPE});
|
|
||||||
}
|
|
||||||
|
|
||||||
my $stars = ElementStars($e, $l);
|
|
||||||
|
|
||||||
$res .= " ".$stars unless ($stars eq "");
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub AllocOutVar($$$$$$$)
|
|
||||||
{
|
|
||||||
my ($e, $mem_ctx, $name, $env, $check, $cleanup, $return) = @_;
|
|
||||||
|
|
||||||
my $l = $e->{LEVELS}[0];
|
|
||||||
|
|
||||||
# we skip pointer to arrays
|
|
||||||
if ($l->{TYPE} eq "POINTER") {
|
|
||||||
my $nl = GetNextLevel($e, $l);
|
|
||||||
$l = $nl if ($nl->{TYPE} eq "ARRAY");
|
|
||||||
} elsif
|
|
||||||
|
|
||||||
# we don't support multi-dimentional arrays yet
|
|
||||||
($l->{TYPE} eq "ARRAY") {
|
|
||||||
my $nl = GetNextLevel($e, $l);
|
|
||||||
if ($nl->{TYPE} eq "ARRAY") {
|
|
||||||
fatal($e->{ORIGINAL},"multi-dimentional [out] arrays are not supported!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
# neither pointer nor array, no need to alloc something.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($l->{TYPE} eq "ARRAY") {
|
|
||||||
unless(defined($l->{SIZE_IS})) {
|
|
||||||
error($e->{ORIGINAL}, "No size known for array `$e->{NAME}'");
|
|
||||||
pidl "#error No size known for array `$e->{NAME}'";
|
|
||||||
} else {
|
|
||||||
my $size = ParseExpr($l->{SIZE_IS}, $env, $e);
|
|
||||||
pidl "$name = talloc_zero_array($mem_ctx, " . DeclLevel($e, 1) . ", $size);";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pidl "$name = talloc_zero($mem_ctx, " . DeclLevel($e, 1) . ");";
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "if (" . $check->($name) . ") {";
|
|
||||||
indent;
|
|
||||||
pidl $cleanup->($name) if defined($cleanup);
|
|
||||||
pidl $return->($name) if defined($return);
|
|
||||||
deindent;
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CallWithStruct($$$$$$)
|
|
||||||
{
|
|
||||||
my ($pipes_struct, $mem_ctx, $fn, $check, $cleanup, $return) = @_;
|
|
||||||
my $env = GenerateFunctionOutEnv($fn);
|
|
||||||
my $hasout = 0;
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
if (grep(/out/, @{$_->{DIRECTION}})) { $hasout = 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "ZERO_STRUCT(r->out);" if ($hasout);
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
my @dir = @{$_->{DIRECTION}};
|
|
||||||
if (grep(/in/, @dir) and grep(/out/, @dir)) {
|
|
||||||
pidl "r->out.$_->{NAME} = r->in.$_->{NAME};";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
next if ContainsPipe($_, $_->{LEVELS}[0]);
|
|
||||||
my @dir = @{$_->{DIRECTION}};
|
|
||||||
if (grep(/in/, @dir) and grep(/out/, @dir)) {
|
|
||||||
# noop
|
|
||||||
} elsif (grep(/out/, @dir) and not
|
|
||||||
has_property($_, "represent_as")) {
|
|
||||||
AllocOutVar($_, $mem_ctx, "r->out.$_->{NAME}", $env,
|
|
||||||
$check, $cleanup, $return);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
my $proto = "_$fn->{NAME}(struct pipes_struct *p, struct $fn->{NAME} *r)";
|
|
||||||
my $ret = "_$fn->{NAME}($pipes_struct, r)";
|
|
||||||
|
|
||||||
if ($fn->{RETURN_TYPE}) {
|
|
||||||
$ret = "r->out.result = $ret";
|
|
||||||
$proto = mapTypeName($fn->{RETURN_TYPE})." $proto";
|
|
||||||
} else {
|
|
||||||
$proto = "void $proto";
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl_hdr "$proto;";
|
|
||||||
pidl "$ret;";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction($$)
|
|
||||||
{
|
|
||||||
my ($if,$fn) = @_;
|
|
||||||
|
|
||||||
my $op = "NDR_".uc($fn->{NAME});
|
|
||||||
|
|
||||||
pidl "static bool api_$fn->{NAME}(struct pipes_struct *p)";
|
|
||||||
pidl "{";
|
|
||||||
indent;
|
|
||||||
pidl "const struct ndr_interface_call *call;";
|
|
||||||
pidl "struct ndr_pull *pull;";
|
|
||||||
pidl "struct ndr_push *push;";
|
|
||||||
pidl "enum ndr_err_code ndr_err;";
|
|
||||||
pidl "struct $fn->{NAME} *r;";
|
|
||||||
pidl "";
|
|
||||||
pidl "call = &ndr_table_$if->{NAME}.calls[$op];";
|
|
||||||
pidl "";
|
|
||||||
pidl "r = talloc(talloc_tos(), struct $fn->{NAME});";
|
|
||||||
pidl "if (r == NULL) {";
|
|
||||||
pidl "\treturn false;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "pull = ndr_pull_init_blob(&p->in_data.data, r);";
|
|
||||||
pidl "if (pull == NULL) {";
|
|
||||||
pidl "\ttalloc_free(r);";
|
|
||||||
pidl "\treturn false;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "pull->flags |= LIBNDR_FLAG_REF_ALLOC;";
|
|
||||||
pidl "if (p->endian) {";
|
|
||||||
pidl "\tpull->flags |= LIBNDR_FLAG_BIGENDIAN;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "ndr_err = call->ndr_pull(pull, NDR_IN, r);";
|
|
||||||
pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {";
|
|
||||||
pidl "\ttalloc_free(r);";
|
|
||||||
pidl "\treturn false;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "if (DEBUGLEVEL >= 10) {";
|
|
||||||
pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_IN, r);";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
|
|
||||||
CallWithStruct("p", "r", $fn,
|
|
||||||
sub ($) {
|
|
||||||
my ($name) = @_;
|
|
||||||
return "${name} == NULL";
|
|
||||||
},
|
|
||||||
sub ($) {
|
|
||||||
my ($name) = @_;
|
|
||||||
return "talloc_free(r);";
|
|
||||||
},
|
|
||||||
sub ($) {
|
|
||||||
my ($name) = @_;
|
|
||||||
return "return false;";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
pidl "";
|
|
||||||
pidl "if (p->fault_state) {";
|
|
||||||
pidl "\ttalloc_free(r);";
|
|
||||||
pidl "\t/* Return true here, srv_pipe_hnd.c will take care */";
|
|
||||||
pidl "\treturn true;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "if (DEBUGLEVEL >= 10) {";
|
|
||||||
pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r);";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "push = ndr_push_init_ctx(r);";
|
|
||||||
pidl "if (push == NULL) {";
|
|
||||||
pidl "\ttalloc_free(r);";
|
|
||||||
pidl "\treturn false;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "/*";
|
|
||||||
pidl " * carry over the pointer count to the reply in case we are";
|
|
||||||
pidl " * using full pointer. See NDR specification for full pointers";
|
|
||||||
pidl " */";
|
|
||||||
pidl "push->ptr_count = pull->ptr_count;";
|
|
||||||
pidl "";
|
|
||||||
pidl "ndr_err = call->ndr_push(push, NDR_OUT, r);";
|
|
||||||
pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {";
|
|
||||||
pidl "\ttalloc_free(r);";
|
|
||||||
pidl "\treturn false;";
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
pidl "p->out_data.rdata = ndr_push_blob(push);";
|
|
||||||
pidl "talloc_steal(p->mem_ctx, p->out_data.rdata.data);";
|
|
||||||
pidl "";
|
|
||||||
pidl "talloc_free(r);";
|
|
||||||
pidl "";
|
|
||||||
pidl "return true;";
|
|
||||||
deindent;
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseInterface($)
|
|
||||||
{
|
|
||||||
my $if = shift;
|
|
||||||
|
|
||||||
my $uif = uc($if->{NAME});
|
|
||||||
|
|
||||||
pidl_hdr "#ifndef __SRV_$uif\__";
|
|
||||||
pidl_hdr "#define __SRV_$uif\__";
|
|
||||||
|
|
||||||
foreach (@{$if->{FUNCTIONS}}) {
|
|
||||||
next if ($_->{PROPERTIES}{noopnum});
|
|
||||||
ParseFunction($if, $_);
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "";
|
|
||||||
pidl "/* Tables */";
|
|
||||||
pidl "static struct api_struct api_$if->{NAME}_cmds[] = ";
|
|
||||||
pidl "{";
|
|
||||||
indent;
|
|
||||||
|
|
||||||
foreach (@{$if->{FUNCTIONS}}) {
|
|
||||||
next if ($_->{PROPERTIES}{noopnum});
|
|
||||||
pidl "{\"" . uc($_->{NAME}) . "\", NDR_" . uc($_->{NAME}) . ", api_$_->{NAME}},";
|
|
||||||
}
|
|
||||||
|
|
||||||
deindent;
|
|
||||||
pidl "};";
|
|
||||||
|
|
||||||
pidl "";
|
|
||||||
|
|
||||||
pidl_hdr "void $if->{NAME}_get_pipe_fns(struct api_struct **fns, int *n_fns);";
|
|
||||||
pidl "void $if->{NAME}_get_pipe_fns(struct api_struct **fns, int *n_fns)";
|
|
||||||
pidl "{";
|
|
||||||
indent;
|
|
||||||
pidl "*fns = api_$if->{NAME}_cmds;";
|
|
||||||
pidl "*n_fns = sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct);";
|
|
||||||
deindent;
|
|
||||||
pidl "}";
|
|
||||||
pidl "";
|
|
||||||
|
|
||||||
if (not has_property($if, "no_srv_register")) {
|
|
||||||
pidl_hdr "struct rpc_srv_callbacks;";
|
|
||||||
pidl_hdr "NTSTATUS rpc_$if->{NAME}_init(const struct rpc_srv_callbacks *rpc_srv_cb);";
|
|
||||||
pidl "NTSTATUS rpc_$if->{NAME}_init(const struct rpc_srv_callbacks *rpc_srv_cb)";
|
|
||||||
pidl "{";
|
|
||||||
pidl "\treturn rpc_srv_register(SMB_RPC_INTERFACE_VERSION, \"$if->{NAME}\", \"$if->{NAME}\", \&ndr_table_$if->{NAME}, api_$if->{NAME}_cmds, sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct), rpc_srv_cb);";
|
|
||||||
pidl "}";
|
|
||||||
|
|
||||||
pidl "";
|
|
||||||
|
|
||||||
pidl_hdr "NTSTATUS rpc_$if->{NAME}_shutdown(void);";
|
|
||||||
pidl "NTSTATUS rpc_$if->{NAME}_shutdown(void)";
|
|
||||||
pidl "{";
|
|
||||||
pidl "\treturn rpc_srv_unregister(\&ndr_table_$if->{NAME});";
|
|
||||||
pidl "}";
|
|
||||||
}
|
|
||||||
pidl_hdr "#endif /* __SRV_$uif\__ */";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$$)
|
|
||||||
{
|
|
||||||
my($ndr,$header,$ndr_header) = @_;
|
|
||||||
|
|
||||||
pidl_reset();
|
|
||||||
|
|
||||||
pidl "/*";
|
|
||||||
pidl " * Unix SMB/CIFS implementation.";
|
|
||||||
pidl " * server auto-generated by pidl. DO NOT MODIFY!";
|
|
||||||
pidl " */";
|
|
||||||
pidl "";
|
|
||||||
pidl "#include \"includes.h\"";
|
|
||||||
pidl "#include \"ntdomain.h\"";
|
|
||||||
pidl "#include \"$header\"";
|
|
||||||
pidl_hdr "#include \"$ndr_header\"";
|
|
||||||
pidl "";
|
|
||||||
|
|
||||||
foreach (@$ndr) {
|
|
||||||
ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");
|
|
||||||
}
|
|
||||||
|
|
||||||
return pidl_return();
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,98 +0,0 @@
|
||||||
###################################################
|
|
||||||
# server template function generator
|
|
||||||
# Copyright tridge@samba.org 2003
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba3::Template;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use Parse::Pidl::Util qw(genpad);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for a interface
|
|
||||||
sub Template($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
|
|
||||||
$res .=
|
|
||||||
"/*
|
|
||||||
Unix SMB/CIFS implementation.
|
|
||||||
|
|
||||||
endpoint server for the $name pipe
|
|
||||||
|
|
||||||
Copyright (C) YOUR NAME HERE YEAR
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include \"includes.h\"
|
|
||||||
#include \"ntdomain.h\"
|
|
||||||
#include \"../librpc/gen_ndr/srv_$name.h\"
|
|
||||||
|
|
||||||
";
|
|
||||||
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
if ($d->{TYPE} eq "FUNCTION") {
|
|
||||||
my $fname = $d->{NAME};
|
|
||||||
my $pad = genpad("$d->{RETURN_TYPE} _$fname");
|
|
||||||
$res .=
|
|
||||||
"
|
|
||||||
/****************************************************************
|
|
||||||
_$fname
|
|
||||||
****************************************************************/
|
|
||||||
|
|
||||||
$d->{RETURN_TYPE} _$fname(struct pipes_struct *p,
|
|
||||||
$pad"."struct $fname *r)
|
|
||||||
{
|
|
||||||
";
|
|
||||||
|
|
||||||
$res .= "\tp->fault_state = DCERPC_FAULT_OP_RNG_ERROR;\n";
|
|
||||||
if ($d->{RETURN_TYPE} eq "NTSTATUS") {
|
|
||||||
$res .= "\treturn NT_STATUS_NOT_IMPLEMENTED;\n";
|
|
||||||
} elsif ($d->{RETURN_TYPE} eq "WERROR") {
|
|
||||||
$res .= "\treturn WERR_NOT_SUPPORTED;\n";
|
|
||||||
} elsif ($d->{RETURN_TYPE} eq "HRESULT") {
|
|
||||||
$res .= "\treturn HRES_ERROR_NOT_SUPPORTED;\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= "}
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a parsed IDL structure back into an IDL file
|
|
||||||
sub Parse($)
|
|
||||||
{
|
|
||||||
my($idl) = shift;
|
|
||||||
$res = "";
|
|
||||||
foreach my $x (@{$idl}) {
|
|
||||||
($x->{TYPE} eq "INTERFACE") &&
|
|
||||||
Template($x);
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,133 +0,0 @@
|
||||||
###################################################
|
|
||||||
# Common Samba4 functions
|
|
||||||
# Copyright jelmer@samba.org 2006
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT = qw(is_intree choose_header NumStars ElementStars ArrayBrackets DeclLong ArrayDynamicallyAllocated);
|
|
||||||
|
|
||||||
use Parse::Pidl::Util qw(has_property is_constant);
|
|
||||||
use Parse::Pidl::NDR qw(GetNextLevel);
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
|
|
||||||
use Parse::Pidl qw(fatal error);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
|
|
||||||
# return true if we are using pidl within the samba source tree. This changes
|
|
||||||
# the names of include files, as some include files (such as ntstatus.h) have
|
|
||||||
# different paths when installed to the patch in the source tree
|
|
||||||
sub is_intree()
|
|
||||||
{
|
|
||||||
my $srcdir = $ENV{srcdir};
|
|
||||||
$srcdir = $srcdir ? "$srcdir/" : "";
|
|
||||||
return 1 if (-f "${srcdir}kdc/kdc.c");
|
|
||||||
return 1 if (-d "${srcdir}source4");
|
|
||||||
return 1 if (-f "${srcdir}include/smb.h");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Return an #include line depending on whether this build is an in-tree
|
|
||||||
# build or not.
|
|
||||||
sub choose_header($$)
|
|
||||||
{
|
|
||||||
my ($in,$out) = @_;
|
|
||||||
return "#include \"$in\"" if (is_intree());
|
|
||||||
return "#include <$out>";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ArrayDynamicallyAllocated($$)
|
|
||||||
{
|
|
||||||
my ($e, $l) = @_;
|
|
||||||
die("Not an array") unless ($l->{TYPE} eq "ARRAY");
|
|
||||||
return 0 if ($l->{IS_FIXED} and not has_property($e, "charset"));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub NumStars($;$)
|
|
||||||
{
|
|
||||||
my ($e, $d) = @_;
|
|
||||||
$d = 0 unless defined($d);
|
|
||||||
my $n = 0;
|
|
||||||
|
|
||||||
foreach my $l (@{$e->{LEVELS}}) {
|
|
||||||
next unless ($l->{TYPE} eq "POINTER");
|
|
||||||
|
|
||||||
my $nl = GetNextLevel($e, $l);
|
|
||||||
next if (defined($nl) and $nl->{TYPE} eq "ARRAY");
|
|
||||||
|
|
||||||
$n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($n >= 1) {
|
|
||||||
$n-- if (scalar_is_reference($e->{TYPE}));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $l (@{$e->{LEVELS}}) {
|
|
||||||
next unless ($l->{TYPE} eq "ARRAY");
|
|
||||||
next unless (ArrayDynamicallyAllocated($e, $l));
|
|
||||||
$n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
error($e->{ORIGINAL}, "Too few pointers $n < $d") if ($n < $d);
|
|
||||||
|
|
||||||
$n -= $d;
|
|
||||||
|
|
||||||
return $n;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ElementStars($;$)
|
|
||||||
{
|
|
||||||
my ($e, $d) = @_;
|
|
||||||
my $res = "";
|
|
||||||
my $n = 0;
|
|
||||||
|
|
||||||
$n = NumStars($e, $d);
|
|
||||||
$res .= "*" foreach (1..$n);
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ArrayBrackets($)
|
|
||||||
{
|
|
||||||
my ($e) = @_;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
foreach my $l (@{$e->{LEVELS}}) {
|
|
||||||
next unless ($l->{TYPE} eq "ARRAY");
|
|
||||||
next if ArrayDynamicallyAllocated($e, $l);
|
|
||||||
$res .= "[$l->{SIZE_IS}]";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub DeclLong($;$)
|
|
||||||
{
|
|
||||||
my ($e, $p) = @_;
|
|
||||||
my $res = "";
|
|
||||||
$p = "" unless defined($p);
|
|
||||||
|
|
||||||
if (has_property($e, "represent_as")) {
|
|
||||||
$res .= mapTypeName($e->{PROPERTIES}->{represent_as})." ";
|
|
||||||
} else {
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
$res .= "const char ";
|
|
||||||
} else {
|
|
||||||
$res .= mapTypeName($e->{TYPE})." ";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= ElementStars($e);
|
|
||||||
}
|
|
||||||
$res .= $p.$e->{NAME};
|
|
||||||
$res .= ArrayBrackets($e);
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,160 +0,0 @@
|
||||||
# COM Header generation
|
|
||||||
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::COM::Header;
|
|
||||||
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
|
||||||
use Parse::Pidl::Util qw(has_property is_constant);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
sub GetArgumentProtoList($)
|
|
||||||
{
|
|
||||||
my $f = shift;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
foreach my $a (@{$f->{ELEMENTS}}) {
|
|
||||||
|
|
||||||
$res .= ", " . mapTypeName($a->{TYPE}) . " ";
|
|
||||||
|
|
||||||
my $l = $a->{POINTERS};
|
|
||||||
$l-- if (Parse::Pidl::Typelist::scalar_is_reference($a->{TYPE}));
|
|
||||||
foreach my $i (1..$l) {
|
|
||||||
$res .= "*";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined $a->{ARRAY_LEN}[0] && !is_constant($a->{ARRAY_LEN}[0]) &&
|
|
||||||
!$a->{POINTERS}) {
|
|
||||||
$res .= "*";
|
|
||||||
}
|
|
||||||
$res .= $a->{NAME};
|
|
||||||
if (defined $a->{ARRAY_LEN}[0] && is_constant($a->{ARRAY_LEN}[0])) {
|
|
||||||
$res .= "[$a->{ARRAY_LEN}[0]]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub GetArgumentList($)
|
|
||||||
{
|
|
||||||
my $f = shift;
|
|
||||||
my $res = "";
|
|
||||||
|
|
||||||
foreach (@{$f->{ELEMENTS}}) { $res .= ", $_->{NAME}"; }
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# generate vtable structure for COM interface
|
|
||||||
sub HeaderVTable($)
|
|
||||||
{
|
|
||||||
my $interface = shift;
|
|
||||||
my $res;
|
|
||||||
$res .= "#define " . uc($interface->{NAME}) . "_METHODS \\\n";
|
|
||||||
if (defined($interface->{BASE})) {
|
|
||||||
$res .= "\t" . uc($interface->{BASE} . "_METHODS") . "\\\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $data = $interface->{DATA};
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
$res .= "\t" . mapTypeName($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n" if ($d->{TYPE} eq "FUNCTION");
|
|
||||||
}
|
|
||||||
$res .= "\n";
|
|
||||||
$res .= "struct $interface->{NAME}_vtable {\n";
|
|
||||||
$res .= "\tstruct GUID iid;\n";
|
|
||||||
$res .= "\t" . uc($interface->{NAME}) . "_METHODS\n";
|
|
||||||
$res .= "};\n\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseInterface($)
|
|
||||||
{
|
|
||||||
my $if = shift;
|
|
||||||
my $res;
|
|
||||||
|
|
||||||
$res .= "\n#ifndef _$if->{NAME}_\n";
|
|
||||||
$res .= "#define _$if->{NAME}_\n";
|
|
||||||
|
|
||||||
$res .="\n\n/* $if->{NAME} */\n";
|
|
||||||
|
|
||||||
$res .="#define COM_" . uc($if->{NAME}) . "_UUID $if->{PROPERTIES}->{uuid}\n\n";
|
|
||||||
|
|
||||||
$res .="struct $if->{NAME}_vtable;\n\n";
|
|
||||||
|
|
||||||
$res .="struct $if->{NAME} {
|
|
||||||
struct OBJREF obj;
|
|
||||||
struct com_context *ctx;
|
|
||||||
struct $if->{NAME}_vtable *vtable;
|
|
||||||
void *object_data;
|
|
||||||
};\n\n";
|
|
||||||
|
|
||||||
$res.=HeaderVTable($if);
|
|
||||||
|
|
||||||
foreach my $d (@{$if->{DATA}}) {
|
|
||||||
next if ($d->{TYPE} ne "FUNCTION");
|
|
||||||
|
|
||||||
$res .= "#define $if->{NAME}_$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . ") ";
|
|
||||||
|
|
||||||
$res .= "((interface)->vtable->$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . "))";
|
|
||||||
|
|
||||||
$res .="\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= "#endif\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseCoClass($)
|
|
||||||
{
|
|
||||||
my ($c) = @_;
|
|
||||||
my $res = "";
|
|
||||||
$res .= "#define CLSID_" . uc($c->{NAME}) . " $c->{PROPERTIES}->{uuid}\n";
|
|
||||||
if (has_property($c, "progid")) {
|
|
||||||
$res .= "#define PROGID_" . uc($c->{NAME}) . " $c->{PROPERTIES}->{progid}\n";
|
|
||||||
}
|
|
||||||
$res .= "\n";
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$)
|
|
||||||
{
|
|
||||||
my ($idl,$ndr_header) = @_;
|
|
||||||
my $res = "";
|
|
||||||
my $has_obj = 0;
|
|
||||||
|
|
||||||
$res .= "#include \"librpc/gen_ndr/orpc.h\"\n" .
|
|
||||||
"#include \"$ndr_header\"\n\n";
|
|
||||||
|
|
||||||
foreach (@{$idl})
|
|
||||||
{
|
|
||||||
if ($_->{TYPE} eq "INTERFACE" && has_property($_, "object")) {
|
|
||||||
$res .="struct $_->{NAME};\n";
|
|
||||||
$has_obj = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (@{$idl})
|
|
||||||
{
|
|
||||||
if ($_->{TYPE} eq "INTERFACE" && has_property($_, "object")) {
|
|
||||||
$res.=ParseInterface($_);
|
|
||||||
$has_obj = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($_->{TYPE} eq "COCLASS") {
|
|
||||||
$res.=ParseCoClass($_);
|
|
||||||
$has_obj = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res if ($has_obj);
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,225 +0,0 @@
|
||||||
###################################################
|
|
||||||
# DCOM parser for Samba
|
|
||||||
# Basically the glue between COM and DCE/RPC with NDR
|
|
||||||
# Copyright jelmer@samba.org 2003-2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::COM::Proxy;
|
|
||||||
|
|
||||||
use Parse::Pidl::Samba4::COM::Header;
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
sub ParseVTable($$)
|
|
||||||
{
|
|
||||||
my ($interface, $name) = @_;
|
|
||||||
|
|
||||||
# Generate the vtable
|
|
||||||
$res .="\tstruct $interface->{NAME}_vtable $name = {";
|
|
||||||
|
|
||||||
if (defined($interface->{BASE})) {
|
|
||||||
$res .= "\n\t\t{},";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $data = $interface->{DATA};
|
|
||||||
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
if ($d->{TYPE} eq "FUNCTION") {
|
|
||||||
$res .= "\n\t\tdcom_proxy_$interface->{NAME}_$d->{NAME}";
|
|
||||||
$res .= ",";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= "\n\t};\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseRegFunc($)
|
|
||||||
{
|
|
||||||
my $interface = shift;
|
|
||||||
|
|
||||||
$res .= "static NTSTATUS dcom_proxy_$interface->{NAME}_init(void)
|
|
||||||
{
|
|
||||||
struct $interface->{NAME}_vtable *proxy_vtable = talloc(talloc_autofree_context(), struct $interface->{NAME}_vtable);
|
|
||||||
";
|
|
||||||
|
|
||||||
if (defined($interface->{BASE})) {
|
|
||||||
$res.= "
|
|
||||||
struct GUID base_iid;
|
|
||||||
const void *base_vtable;
|
|
||||||
|
|
||||||
base_iid = ndr_table_$interface->{BASE}.syntax_id.uuid;
|
|
||||||
|
|
||||||
base_vtable = dcom_proxy_vtable_by_iid(&base_iid);
|
|
||||||
if (base_vtable == NULL) {
|
|
||||||
DEBUG(0, (\"No proxy registered for base interface '$interface->{BASE}'\\n\"));
|
|
||||||
return NT_STATUS_FOOBAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&proxy_vtable, base_vtable, sizeof(struct $interface->{BASE}_vtable));
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
foreach my $x (@{$interface->{DATA}}) {
|
|
||||||
next unless ($x->{TYPE} eq "FUNCTION");
|
|
||||||
|
|
||||||
$res .= "\tproxy_vtable->$x->{NAME} = dcom_proxy_$interface->{NAME}_$x->{NAME};\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res.= "
|
|
||||||
proxy_vtable->iid = ndr_table_$interface->{NAME}.syntax_id.uuid;
|
|
||||||
|
|
||||||
return dcom_register_proxy((struct IUnknown_vtable *)proxy_vtable);
|
|
||||||
}\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a function
|
|
||||||
sub ParseFunction($$)
|
|
||||||
{
|
|
||||||
my ($interface, $fn) = @_;
|
|
||||||
my $name = $fn->{NAME};
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
my $tn = mapTypeName($fn->{RETURN_TYPE});
|
|
||||||
|
|
||||||
$res.="
|
|
||||||
static $tn dcom_proxy_$interface->{NAME}_$name(struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . Parse::Pidl::Samba4::COM::Header::GetArgumentProtoList($fn) . ")
|
|
||||||
{
|
|
||||||
struct dcerpc_pipe *p;
|
|
||||||
NTSTATUS status = dcom_get_pipe(d, &p);
|
|
||||||
struct $name r;
|
|
||||||
struct rpc_request *req;
|
|
||||||
|
|
||||||
if (NT_STATUS_IS_ERR(status)) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZERO_STRUCT(r.in.ORPCthis);
|
|
||||||
r.in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION;
|
|
||||||
r.in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION;
|
|
||||||
";
|
|
||||||
|
|
||||||
# Put arguments into r
|
|
||||||
foreach my $a (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless (has_property($a, "in"));
|
|
||||||
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
|
||||||
$res .="\tNDR_CHECK(dcom_OBJREF_from_IUnknown(mem_ctx, &r.in.$a->{NAME}.obj, $a->{NAME}));\n";
|
|
||||||
} else {
|
|
||||||
$res .= "\tr.in.$a->{NAME} = $a->{NAME};\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .="
|
|
||||||
if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
|
|
||||||
NDR_PRINT_IN_DEBUG($name, &r);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = dcerpc_ndr_request(p, &d->ipid, &ndr_table_$interface->{NAME}, NDR_$uname, mem_ctx, &r);
|
|
||||||
|
|
||||||
if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) {
|
|
||||||
NDR_PRINT_OUT_DEBUG($name, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
";
|
|
||||||
|
|
||||||
# Put r info back into arguments
|
|
||||||
foreach my $a (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless (has_property($a, "out"));
|
|
||||||
|
|
||||||
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
|
||||||
$res .="\tNDR_CHECK(dcom_IUnknown_from_OBJREF(d->ctx, &$a->{NAME}, r.out.$a->{NAME}.obj));\n";
|
|
||||||
} else {
|
|
||||||
$res .= "\t*$a->{NAME} = r.out.$a->{NAME};\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($fn->{RETURN_TYPE} eq "NTSTATUS") {
|
|
||||||
$res .= "\tif (NT_STATUS_IS_OK(status)) status = r.out.result;\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .=
|
|
||||||
"
|
|
||||||
return r.out.result;
|
|
||||||
}\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse the interface definitions
|
|
||||||
sub ParseInterface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
$res = "/* DCOM proxy for $interface->{NAME} generated by pidl */\n\n";
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
($d->{TYPE} eq "FUNCTION") &&
|
|
||||||
ParseFunction($interface, $d);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParseRegFunc($interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub RegistrationFunction($$)
|
|
||||||
{
|
|
||||||
my $idl = shift;
|
|
||||||
my $basename = shift;
|
|
||||||
|
|
||||||
my $res = "\n\nNTSTATUS dcom_$basename\_init(void)\n";
|
|
||||||
$res .= "{\n";
|
|
||||||
$res .="\tNTSTATUS status = NT_STATUS_OK;\n";
|
|
||||||
foreach my $interface (@{$idl}) {
|
|
||||||
next if $interface->{TYPE} ne "INTERFACE";
|
|
||||||
next if not has_property($interface, "object");
|
|
||||||
|
|
||||||
my $data = $interface->{DATA};
|
|
||||||
my $count = 0;
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
if ($d->{TYPE} eq "FUNCTION") { $count++; }
|
|
||||||
}
|
|
||||||
|
|
||||||
next if ($count == 0);
|
|
||||||
|
|
||||||
$res .= "\tstatus = dcom_$interface->{NAME}_init();\n";
|
|
||||||
$res .= "\tif (NT_STATUS_IS_ERR(status)) {\n";
|
|
||||||
$res .= "\t\treturn status;\n";
|
|
||||||
$res .= "\t}\n\n";
|
|
||||||
}
|
|
||||||
$res .= "\treturn status;\n";
|
|
||||||
$res .= "}\n\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$)
|
|
||||||
{
|
|
||||||
my ($pidl,$comh_filename) = @_;
|
|
||||||
my $res = "";
|
|
||||||
my $has_obj = 0;
|
|
||||||
|
|
||||||
$res .= "#include \"includes.h\"\n" .
|
|
||||||
"#include \"lib/com/dcom/dcom.h\"\n" .
|
|
||||||
"#include \"$comh_filename\"\n" .
|
|
||||||
"#include \"librpc/rpc/dcerpc.h\"\n";
|
|
||||||
|
|
||||||
foreach (@{$pidl}) {
|
|
||||||
next if ($_->{TYPE} ne "INTERFACE");
|
|
||||||
next if has_property($_, "local");
|
|
||||||
next unless has_property($_, "object");
|
|
||||||
|
|
||||||
$res .= ParseInterface($_);
|
|
||||||
|
|
||||||
$has_obj = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res if ($has_obj);
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,327 +0,0 @@
|
||||||
###################################################
|
|
||||||
# DCOM stub boilerplate generator
|
|
||||||
# Copyright jelmer@samba.org 2004-2005
|
|
||||||
# Copyright tridge@samba.org 2003
|
|
||||||
# Copyright metze@samba.org 2004
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::COM::Stub;
|
|
||||||
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
sub pidl($)
|
|
||||||
{
|
|
||||||
$res .= shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################
|
|
||||||
# generate the switch statement for function dispatch
|
|
||||||
sub gen_dispatch_switch($)
|
|
||||||
{
|
|
||||||
my $data = shift;
|
|
||||||
|
|
||||||
my $count = 0;
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
next if ($d->{TYPE} ne "FUNCTION");
|
|
||||||
|
|
||||||
pidl "\tcase $count: {\n";
|
|
||||||
if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
|
|
||||||
pidl "\t\tNTSTATUS result;\n";
|
|
||||||
}
|
|
||||||
pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
|
|
||||||
pidl "\t\tif (DEBUGLEVEL > 10) {\n";
|
|
||||||
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_IN, r2);\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
|
|
||||||
pidl "\t\tresult = vtable->$d->{NAME}(iface, mem_ctx, r2);\n";
|
|
||||||
} else {
|
|
||||||
pidl "\t\tvtable->$d->{NAME}(iface, mem_ctx, r2);\n";
|
|
||||||
}
|
|
||||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} will reply async\\n\"));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tbreak;\n\t}\n";
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################
|
|
||||||
# generate the switch statement for function reply
|
|
||||||
sub gen_reply_switch($)
|
|
||||||
{
|
|
||||||
my $data = shift;
|
|
||||||
|
|
||||||
my $count = 0;
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
next if ($d->{TYPE} ne "FUNCTION");
|
|
||||||
|
|
||||||
pidl "\tcase $count: {\n";
|
|
||||||
pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
|
|
||||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} replied async\\n\"));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n";
|
|
||||||
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tif (dce_call->fault_code != 0) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $d->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tbreak;\n\t}\n";
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for a interface
|
|
||||||
sub Boilerplate_Iface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
my $uname = uc $name;
|
|
||||||
my $uuid = Parse::Pidl::Util::make_str($interface->{PROPERTIES}->{uuid});
|
|
||||||
my $if_version = $interface->{PROPERTIES}->{version};
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
|
|
||||||
{
|
|
||||||
#ifdef DCESRV_INTERFACE_$uname\_BIND
|
|
||||||
return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface);
|
|
||||||
#else
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
|
|
||||||
{
|
|
||||||
#ifdef DCESRV_INTERFACE_$uname\_UNBIND
|
|
||||||
DCESRV_INTERFACE_$uname\_UNBIND(context, iface);
|
|
||||||
#else
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
|
|
||||||
{
|
|
||||||
NTSTATUS status;
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
dce_call->fault_code = 0;
|
|
||||||
|
|
||||||
if (opnum >= dcerpc_table_$name.num_calls) {
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
*r = talloc_size(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size);
|
|
||||||
NT_STATUS_HAVE_NO_MEMORY(*r);
|
|
||||||
|
|
||||||
/* unravel the NDR for the packet */
|
|
||||||
status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
|
||||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
|
||||||
{
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
struct GUID ipid = dce_call->pkt.u.request.object.object;
|
|
||||||
struct dcom_interface_p *iface = dcom_get_local_iface_p(&ipid);
|
|
||||||
const struct dcom_$name\_vtable *vtable = iface->vtable;
|
|
||||||
|
|
||||||
switch (opnum) {
|
|
||||||
";
|
|
||||||
gen_dispatch_switch($data);
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
default:
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dce_call->fault_code != 0) {
|
|
||||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
|
||||||
{
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
switch (opnum) {
|
|
||||||
";
|
|
||||||
gen_reply_switch($data);
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
default:
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dce_call->fault_code != 0) {
|
|
||||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
|
|
||||||
{
|
|
||||||
NTSTATUS status;
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
status = dcerpc_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct dcesrv_interface $name\_interface = {
|
|
||||||
.name = \"$name\",
|
|
||||||
.uuid = $uuid,
|
|
||||||
.if_version = $if_version,
|
|
||||||
.bind = $name\__op_bind,
|
|
||||||
.unbind = $name\__op_unbind,
|
|
||||||
.ndr_pull = $name\__op_ndr_pull,
|
|
||||||
.dispatch = $name\__op_dispatch,
|
|
||||||
.reply = $name\__op_reply,
|
|
||||||
.ndr_push = $name\__op_ndr_push
|
|
||||||
};
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for an endpoint server
|
|
||||||
sub Boilerplate_Ep_Server($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0;i<dcerpc_table_$name.endpoints->count;i++) {
|
|
||||||
NTSTATUS ret;
|
|
||||||
const char *name = dcerpc_table_$name.endpoints->names[i];
|
|
||||||
|
|
||||||
ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL);
|
|
||||||
if (!NT_STATUS_IS_OK(ret)) {
|
|
||||||
DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32_t if_version)
|
|
||||||
{
|
|
||||||
if (dcerpc_table_$name.if_version == if_version &&
|
|
||||||
strcmp(dcerpc_table_$name.uuid, uuid)==0) {
|
|
||||||
memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
|
|
||||||
{
|
|
||||||
if (strcmp(dcerpc_table_$name.name, name)==0) {
|
|
||||||
memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS dcerpc_server_$name\_init(void)
|
|
||||||
{
|
|
||||||
NTSTATUS ret;
|
|
||||||
struct dcesrv_endpoint_server ep_server;
|
|
||||||
|
|
||||||
/* fill in our name */
|
|
||||||
ep_server.name = \"$name\";
|
|
||||||
|
|
||||||
/* fill in all the operations */
|
|
||||||
ep_server.init_server = $name\__op_init_server;
|
|
||||||
|
|
||||||
ep_server.interface_by_uuid = $name\__op_interface_by_uuid;
|
|
||||||
ep_server.interface_by_name = $name\__op_interface_by_name;
|
|
||||||
|
|
||||||
/* register ourselves with the DCERPC subsystem. */
|
|
||||||
ret = dcerpc_register_ep_server(&ep_server);
|
|
||||||
|
|
||||||
if (!NT_STATUS_IS_OK(ret)) {
|
|
||||||
DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dcom interface stub from a parsed IDL structure
|
|
||||||
sub ParseInterface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
|
|
||||||
return "" if has_property($interface, "local");
|
|
||||||
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
my $count = 0;
|
|
||||||
|
|
||||||
$res = "";
|
|
||||||
|
|
||||||
if (!defined $interface->{PROPERTIES}->{uuid}) {
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defined $interface->{PROPERTIES}->{version}) {
|
|
||||||
$interface->{PROPERTIES}->{version} = "0.0";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
if ($d->{TYPE} eq "FUNCTION") { $count++; }
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($count == 0) {
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
$res = "/* dcom interface stub generated by pidl */\n\n";
|
|
||||||
Boilerplate_Iface($interface);
|
|
||||||
Boilerplate_Ep_Server($interface);
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,537 +0,0 @@
|
||||||
###################################################
|
|
||||||
# create C header files for an IDL structure
|
|
||||||
# Copyright tridge@samba.org 2000
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::Header;
|
|
||||||
require Exporter;
|
|
||||||
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Parse::Pidl qw(fatal);
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
|
|
||||||
use Parse::Pidl::Util qw(has_property is_constant unmake_str ParseExpr);
|
|
||||||
use Parse::Pidl::Samba4 qw(is_intree ElementStars ArrayBrackets choose_header);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
my($tab_depth);
|
|
||||||
|
|
||||||
sub pidl($) { $res .= shift; }
|
|
||||||
|
|
||||||
sub tabs()
|
|
||||||
{
|
|
||||||
my $res = "";
|
|
||||||
$res .="\t" foreach (1..$tab_depth);
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a properties list
|
|
||||||
sub HeaderProperties($$)
|
|
||||||
{
|
|
||||||
my($props,$ignores) = @_;
|
|
||||||
my $ret = "";
|
|
||||||
|
|
||||||
foreach my $d (sort(keys %{$props})) {
|
|
||||||
next if (grep(/^$d$/, @$ignores));
|
|
||||||
if($props->{$d} ne "1") {
|
|
||||||
$ret.= "$d($props->{$d}),";
|
|
||||||
} else {
|
|
||||||
$ret.="$d,";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ret) {
|
|
||||||
pidl "/* [" . substr($ret, 0, -1) . "] */";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a structure element
|
|
||||||
sub HeaderElement($)
|
|
||||||
{
|
|
||||||
my($element) = shift;
|
|
||||||
|
|
||||||
pidl tabs();
|
|
||||||
if (has_property($element, "represent_as")) {
|
|
||||||
pidl mapTypeName($element->{PROPERTIES}->{represent_as})." ";
|
|
||||||
} else {
|
|
||||||
if (ref($element->{TYPE}) eq "HASH") {
|
|
||||||
HeaderType($element, $element->{TYPE}, $element->{TYPE}->{NAME});
|
|
||||||
} else {
|
|
||||||
HeaderType($element, $element->{TYPE}, "");
|
|
||||||
}
|
|
||||||
pidl " ".ElementStars($element);
|
|
||||||
}
|
|
||||||
pidl $element->{NAME};
|
|
||||||
pidl ArrayBrackets($element);
|
|
||||||
|
|
||||||
pidl ";";
|
|
||||||
if (defined $element->{PROPERTIES}) {
|
|
||||||
HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
|
|
||||||
}
|
|
||||||
pidl "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a struct
|
|
||||||
sub HeaderStruct($$;$)
|
|
||||||
{
|
|
||||||
my($struct,$name,$tail) = @_;
|
|
||||||
pidl "struct $name";
|
|
||||||
pidl $tail if defined($tail) and not defined($struct->{ELEMENTS});
|
|
||||||
return if (not defined($struct->{ELEMENTS}));
|
|
||||||
pidl " {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
my $el_count=0;
|
|
||||||
foreach (@{$struct->{ELEMENTS}}) {
|
|
||||||
HeaderElement($_);
|
|
||||||
$el_count++;
|
|
||||||
}
|
|
||||||
if ($el_count == 0) {
|
|
||||||
# some compilers can't handle empty structures
|
|
||||||
pidl tabs()."char _empty_;\n";
|
|
||||||
}
|
|
||||||
$tab_depth--;
|
|
||||||
pidl tabs()."}";
|
|
||||||
if (defined $struct->{PROPERTIES}) {
|
|
||||||
HeaderProperties($struct->{PROPERTIES}, []);
|
|
||||||
}
|
|
||||||
pidl $tail if defined($tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a enum
|
|
||||||
sub HeaderEnum($$;$)
|
|
||||||
{
|
|
||||||
my($enum,$name,$tail) = @_;
|
|
||||||
my $first = 1;
|
|
||||||
|
|
||||||
pidl "enum $name";
|
|
||||||
if (defined($enum->{ELEMENTS})) {
|
|
||||||
pidl "\n#ifndef USE_UINT_ENUMS\n";
|
|
||||||
pidl " {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
foreach my $e (@{$enum->{ELEMENTS}}) {
|
|
||||||
my @enum_els = ();
|
|
||||||
unless ($first) { pidl ",\n"; }
|
|
||||||
$first = 0;
|
|
||||||
pidl tabs();
|
|
||||||
@enum_els = split(/=/, $e);
|
|
||||||
if (@enum_els == 2) {
|
|
||||||
pidl $enum_els[0];
|
|
||||||
pidl "=(int)";
|
|
||||||
pidl "(";
|
|
||||||
pidl $enum_els[1];
|
|
||||||
pidl ")";
|
|
||||||
} else {
|
|
||||||
pidl $e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pidl "\n";
|
|
||||||
$tab_depth--;
|
|
||||||
pidl "}";
|
|
||||||
pidl "\n";
|
|
||||||
pidl "#else\n";
|
|
||||||
my $count = 0;
|
|
||||||
my $with_val = 0;
|
|
||||||
my $without_val = 0;
|
|
||||||
pidl " { __do_not_use_enum_$name=0x7FFFFFFF}\n";
|
|
||||||
foreach my $e (@{$enum->{ELEMENTS}}) {
|
|
||||||
my $t = "$e";
|
|
||||||
my $name;
|
|
||||||
my $value;
|
|
||||||
if ($t =~ /(.*)=(.*)/) {
|
|
||||||
$name = $1;
|
|
||||||
$value = $2;
|
|
||||||
$with_val = 1;
|
|
||||||
fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
|
|
||||||
unless ($without_val == 0);
|
|
||||||
} else {
|
|
||||||
$name = $t;
|
|
||||||
$value = $count++;
|
|
||||||
$without_val = 1;
|
|
||||||
fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
|
|
||||||
unless ($with_val == 0);
|
|
||||||
}
|
|
||||||
pidl "#define $name ( $value )\n";
|
|
||||||
}
|
|
||||||
pidl "#endif\n";
|
|
||||||
}
|
|
||||||
pidl $tail if defined($tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a bitmap
|
|
||||||
sub HeaderBitmap($$)
|
|
||||||
{
|
|
||||||
my($bitmap,$name) = @_;
|
|
||||||
|
|
||||||
return unless defined($bitmap->{ELEMENTS});
|
|
||||||
|
|
||||||
pidl "/* bitmap $name */\n";
|
|
||||||
pidl "#define $_\n" foreach (@{$bitmap->{ELEMENTS}});
|
|
||||||
pidl "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a union
|
|
||||||
sub HeaderUnion($$;$)
|
|
||||||
{
|
|
||||||
my($union,$name,$tail) = @_;
|
|
||||||
my %done = ();
|
|
||||||
|
|
||||||
pidl "union $name";
|
|
||||||
pidl $tail if defined($tail) and not defined($union->{ELEMENTS});
|
|
||||||
return if (not defined($union->{ELEMENTS}));
|
|
||||||
pidl " {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
my $needed = 0;
|
|
||||||
foreach my $e (@{$union->{ELEMENTS}}) {
|
|
||||||
if ($e->{TYPE} ne "EMPTY") {
|
|
||||||
if (! defined $done{$e->{NAME}}) {
|
|
||||||
HeaderElement($e);
|
|
||||||
}
|
|
||||||
$done{$e->{NAME}} = 1;
|
|
||||||
$needed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!$needed) {
|
|
||||||
# sigh - some compilers don't like empty structures
|
|
||||||
pidl tabs()."int _dummy_element;\n";
|
|
||||||
}
|
|
||||||
$tab_depth--;
|
|
||||||
pidl "}";
|
|
||||||
|
|
||||||
if (defined $union->{PROPERTIES}) {
|
|
||||||
HeaderProperties($union->{PROPERTIES}, []);
|
|
||||||
}
|
|
||||||
pidl $tail if defined($tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a pipe
|
|
||||||
sub HeaderPipe($$;$)
|
|
||||||
{
|
|
||||||
my($pipe,$name,$tail) = @_;
|
|
||||||
|
|
||||||
my $struct = $pipe->{DATA};
|
|
||||||
my $e = $struct->{ELEMENTS}[1];
|
|
||||||
|
|
||||||
pidl "struct $name;\n";
|
|
||||||
pidl "struct $struct->{NAME} {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
pidl tabs()."uint32_t count;\n";
|
|
||||||
pidl tabs().mapTypeName($e->{TYPE})." *array;\n";
|
|
||||||
$tab_depth--;
|
|
||||||
pidl "}";
|
|
||||||
|
|
||||||
if (defined $struct->{PROPERTIES}) {
|
|
||||||
HeaderProperties($struct->{PROPERTIES}, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl $tail if defined($tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a type
|
|
||||||
sub HeaderType($$$;$)
|
|
||||||
{
|
|
||||||
my($e,$data,$name,$tail) = @_;
|
|
||||||
if (ref($data) eq "HASH") {
|
|
||||||
($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name, $tail);
|
|
||||||
($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
|
|
||||||
($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail);
|
|
||||||
($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail);
|
|
||||||
($data->{TYPE} eq "PIPE") && HeaderPipe($data, $name, $tail);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
pidl "const char";
|
|
||||||
} else {
|
|
||||||
pidl mapTypeName($e->{TYPE});
|
|
||||||
}
|
|
||||||
pidl $tail if defined($tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a typedef
|
|
||||||
sub HeaderTypedef($;$)
|
|
||||||
{
|
|
||||||
my($typedef,$tail) = @_;
|
|
||||||
# Don't print empty "enum foo;", since some compilers don't like it.
|
|
||||||
return if ($typedef->{DATA}->{TYPE} eq "ENUM" and not defined($typedef->{DATA}->{ELEMENTS}));
|
|
||||||
HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME}, $tail) if defined ($typedef->{DATA});
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a const
|
|
||||||
sub HeaderConst($)
|
|
||||||
{
|
|
||||||
my($const) = shift;
|
|
||||||
if (!defined($const->{ARRAY_LEN}[0])) {
|
|
||||||
pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
|
|
||||||
} else {
|
|
||||||
pidl "#define $const->{NAME}\t $const->{VALUE}\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) = @_;
|
|
||||||
|
|
||||||
return unless defined($fn->{ELEMENTS});
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
HeaderElement($e) if (ElementDirection($e) eq $prop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# determine if we need an "in" or "out" section
|
|
||||||
sub HeaderFunctionInOut_needed($$)
|
|
||||||
{
|
|
||||||
my($fn,$prop) = @_;
|
|
||||||
|
|
||||||
return 1 if ($prop eq "out" && defined($fn->{RETURN_TYPE}));
|
|
||||||
|
|
||||||
return undef unless defined($fn->{ELEMENTS});
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
return 1 if (ElementDirection($e) eq $prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
my %headerstructs;
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a function
|
|
||||||
sub HeaderFunction($)
|
|
||||||
{
|
|
||||||
my($fn) = shift;
|
|
||||||
|
|
||||||
return if ($headerstructs{$fn->{NAME}});
|
|
||||||
|
|
||||||
$headerstructs{$fn->{NAME}} = 1;
|
|
||||||
|
|
||||||
pidl "\nstruct $fn->{NAME} {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
my $needed = 0;
|
|
||||||
|
|
||||||
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") or
|
|
||||||
HeaderFunctionInOut_needed($fn, "inout")) {
|
|
||||||
pidl tabs()."struct {\n";
|
|
||||||
$tab_depth++;
|
|
||||||
HeaderFunctionInOut($fn, "out");
|
|
||||||
HeaderFunctionInOut($fn, "inout");
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
pidl tabs().mapTypeName($fn->{RETURN_TYPE}) . " result;\n";
|
|
||||||
}
|
|
||||||
$tab_depth--;
|
|
||||||
pidl tabs()."} out;\n\n";
|
|
||||||
$needed++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$needed) {
|
|
||||||
# sigh - some compilers don't like empty structures
|
|
||||||
pidl tabs()."int _dummy_element;\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$tab_depth--;
|
|
||||||
pidl "};\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub HeaderImport
|
|
||||||
{
|
|
||||||
my @imports = @_;
|
|
||||||
foreach my $import (@imports) {
|
|
||||||
$import = unmake_str($import);
|
|
||||||
$import =~ s/\.idl$//;
|
|
||||||
pidl choose_header("librpc/gen_ndr/$import\.h", "gen_ndr/$import.h") . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub HeaderInclude
|
|
||||||
{
|
|
||||||
my @includes = @_;
|
|
||||||
foreach (@includes) {
|
|
||||||
pidl "#include $_\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse the interface definitions
|
|
||||||
sub HeaderInterface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
|
|
||||||
pidl "#ifndef _HEADER_$interface->{NAME}\n";
|
|
||||||
pidl "#define _HEADER_$interface->{NAME}\n\n";
|
|
||||||
|
|
||||||
foreach my $c (@{$interface->{CONSTS}}) {
|
|
||||||
HeaderConst($c);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $t (@{$interface->{TYPES}}) {
|
|
||||||
HeaderTypedef($t, ";\n\n") if ($t->{TYPE} eq "TYPEDEF");
|
|
||||||
HeaderStruct($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "STRUCT");
|
|
||||||
HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION");
|
|
||||||
HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM");
|
|
||||||
HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
|
|
||||||
HeaderPipe($t, $t->{NAME}, "\n\n") if ($t->{TYPE} eq "PIPE");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
|
||||||
HeaderFunction($fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "#endif /* _HEADER_$interface->{NAME} */\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub HeaderQuote($)
|
|
||||||
{
|
|
||||||
my($quote) = shift;
|
|
||||||
|
|
||||||
pidl unmake_str($quote->{DATA}) . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a parsed IDL into a C header
|
|
||||||
sub Parse($)
|
|
||||||
{
|
|
||||||
my($ndr) = shift;
|
|
||||||
$tab_depth = 0;
|
|
||||||
|
|
||||||
$res = "";
|
|
||||||
%headerstructs = ();
|
|
||||||
pidl "/* header auto-generated by pidl */\n\n";
|
|
||||||
|
|
||||||
my $ifacename = "";
|
|
||||||
|
|
||||||
# work out a unique interface name
|
|
||||||
foreach (@{$ndr}) {
|
|
||||||
if ($_->{TYPE} eq "INTERFACE") {
|
|
||||||
$ifacename = $_->{NAME};
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "#ifndef _PIDL_HEADER_$ifacename\n";
|
|
||||||
pidl "#define _PIDL_HEADER_$ifacename\n\n";
|
|
||||||
|
|
||||||
if (!is_intree()) {
|
|
||||||
pidl "#include <util/data_blob.h>\n";
|
|
||||||
}
|
|
||||||
pidl "#include <stdint.h>\n";
|
|
||||||
pidl "\n";
|
|
||||||
# FIXME: Include this only if NTSTATUS was actually used
|
|
||||||
pidl choose_header("libcli/util/ntstatus.h", "core/ntstatus.h") . "\n";
|
|
||||||
pidl "\n";
|
|
||||||
|
|
||||||
foreach (@{$ndr}) {
|
|
||||||
($_->{TYPE} eq "CPP_QUOTE") && HeaderQuote($_);
|
|
||||||
($_->{TYPE} eq "INTERFACE") && HeaderInterface($_);
|
|
||||||
($_->{TYPE} eq "IMPORT") && HeaderImport(@{$_->{PATHS}});
|
|
||||||
($_->{TYPE} eq "INCLUDE") && HeaderInclude(@{$_->{PATHS}});
|
|
||||||
}
|
|
||||||
|
|
||||||
pidl "#endif /* _PIDL_HEADER_$ifacename */\n";
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub GenerateStructEnv($$)
|
|
||||||
{
|
|
||||||
my ($x, $v) = @_;
|
|
||||||
my %env;
|
|
||||||
|
|
||||||
foreach my $e (@{$x->{ELEMENTS}}) {
|
|
||||||
$env{$e->{NAME}} = "$v->$e->{NAME}";
|
|
||||||
}
|
|
||||||
|
|
||||||
$env{"this"} = $v;
|
|
||||||
|
|
||||||
return \%env;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub EnvSubstituteValue($$)
|
|
||||||
{
|
|
||||||
my ($env,$s) = @_;
|
|
||||||
|
|
||||||
# Substitute the value() values in the env
|
|
||||||
foreach my $e (@{$s->{ELEMENTS}}) {
|
|
||||||
next unless (defined(my $v = has_property($e, "value")));
|
|
||||||
|
|
||||||
$env->{$e->{NAME}} = ParseExpr($v, $env, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $env;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub GenerateFunctionInEnv($;$)
|
|
||||||
{
|
|
||||||
my ($fn, $base) = @_;
|
|
||||||
my %env;
|
|
||||||
|
|
||||||
$base = "r->" unless defined($base);
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
if (grep (/in/, @{$e->{DIRECTION}})) {
|
|
||||||
$env{$e->{NAME}} = $base."in.$e->{NAME}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return \%env;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub GenerateFunctionOutEnv($;$)
|
|
||||||
{
|
|
||||||
my ($fn, $base) = @_;
|
|
||||||
my %env;
|
|
||||||
|
|
||||||
$base = "r->" unless defined($base);
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
if (grep (/out/, @{$e->{DIRECTION}})) {
|
|
||||||
$env{$e->{NAME}} = $base."out.$e->{NAME}";
|
|
||||||
} elsif (grep (/in/, @{$e->{DIRECTION}})) {
|
|
||||||
$env{$e->{NAME}} = $base."in.$e->{NAME}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return \%env;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,884 +0,0 @@
|
||||||
###################################################
|
|
||||||
# client calls generator
|
|
||||||
# Copyright tridge@samba.org 2003
|
|
||||||
# Copyright jelmer@samba.org 2005-2006
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::NDR::Client;
|
|
||||||
|
|
||||||
use Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(Parse);
|
|
||||||
|
|
||||||
use Parse::Pidl qw(fatal warning error);
|
|
||||||
use Parse::Pidl::Util qw(has_property ParseExpr genpad);
|
|
||||||
use Parse::Pidl::NDR qw(ContainsPipe);
|
|
||||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
|
||||||
use Parse::Pidl::Samba4 qw(choose_header is_intree DeclLong);
|
|
||||||
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; }
|
|
||||||
sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); }
|
|
||||||
sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; }
|
|
||||||
sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; }
|
|
||||||
sub pidl_both($$) { my ($self, $txt) = @_; $self->{hdr} .= "$txt\n"; $self->{res_hdr} .= "$txt\n"; }
|
|
||||||
sub fn_declare($$) { my ($self,$n) = @_; $self->pidl($n); $self->pidl_hdr("$n;"); }
|
|
||||||
|
|
||||||
sub new($)
|
|
||||||
{
|
|
||||||
my ($class) = shift;
|
|
||||||
my $self = { res => "", res_hdr => "", tabs => "" };
|
|
||||||
bless($self, $class);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunctionHasPipes($$)
|
|
||||||
{
|
|
||||||
my ($self, $fn) = @_;
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
return 1 if ContainsPipe($e, $e->{LEVELS}[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_r_State($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
$self->pidl("struct dcerpc_$name\_r_state {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("};");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("static void dcerpc_$name\_r_done(struct tevent_req *subreq);");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_r_Send($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
my $proto = "struct tevent_req *dcerpc_$name\_r_send(TALLOC_CTX *mem_ctx,\n";
|
|
||||||
$proto .= "\tstruct tevent_context *ev,\n",
|
|
||||||
$proto .= "\tstruct dcerpc_binding_handle *h,\n",
|
|
||||||
$proto .= "\tstruct $name *r)";
|
|
||||||
|
|
||||||
$self->fn_declare($proto);
|
|
||||||
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
|
|
||||||
$self->pidl("struct tevent_req *req;");
|
|
||||||
$self->pidl("struct dcerpc_$name\_r_state *state;");
|
|
||||||
$self->pidl("struct tevent_req *subreq;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
|
||||||
$self->pidl("\t\t\tstruct dcerpc_$name\_r_state);");
|
|
||||||
$self->pidl("if (req == NULL) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return NULL;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
my $out_params = 0;
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless grep(/out/, @{$e->{DIRECTION}});
|
|
||||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
|
||||||
$out_params++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
my $submem;
|
|
||||||
if ($out_params > 0) {
|
|
||||||
$self->pidl("state->out_mem_ctx = talloc_new(state);");
|
|
||||||
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$submem = "state->out_mem_ctx";
|
|
||||||
} else {
|
|
||||||
$self->pidl("state->out_mem_ctx = NULL;");
|
|
||||||
$submem = "state";
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("subreq = dcerpc_binding_handle_call_send(state, ev, h,");
|
|
||||||
$self->pidl("\t\tNULL, &ndr_table_$if->{NAME},");
|
|
||||||
$self->pidl("\t\tNDR_$uname, $submem, r);");
|
|
||||||
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("tevent_req_set_callback(subreq, dcerpc_$name\_r_done, req);");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("return req;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_r_Done($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
my $proto = "static void dcerpc_$name\_r_done(struct tevent_req *subreq)";
|
|
||||||
|
|
||||||
$self->pidl("$proto");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
|
|
||||||
$self->pidl("struct tevent_req *req =");
|
|
||||||
$self->pidl("\ttevent_req_callback_data(subreq,");
|
|
||||||
$self->pidl("\tstruct tevent_req);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("status = dcerpc_binding_handle_call_recv(subreq);");
|
|
||||||
$self->pidl("TALLOC_FREE(subreq);");
|
|
||||||
$self->pidl("if (tevent_req_nterror(req, status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_done(req);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_r_Recv($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
my $proto = "NTSTATUS dcerpc_$name\_r_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)";
|
|
||||||
|
|
||||||
$self->fn_declare($proto);
|
|
||||||
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
|
|
||||||
$self->pidl("struct dcerpc_$name\_r_state *state =");
|
|
||||||
$self->pidl("\ttevent_req_data(req,");
|
|
||||||
$self->pidl("\tstruct dcerpc_$name\_r_state);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return status;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_r_Sync($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
if ($self->ParseFunctionHasPipes($fn)) {
|
|
||||||
$self->pidl_both("/*");
|
|
||||||
$self->pidl_both(" * The following function is skipped because");
|
|
||||||
$self->pidl_both(" * it uses pipes:");
|
|
||||||
$self->pidl_both(" *");
|
|
||||||
$self->pidl_both(" * dcerpc_$name\_r()");
|
|
||||||
$self->pidl_both(" */");
|
|
||||||
$self->pidl_both("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $proto = "NTSTATUS dcerpc_$name\_r(struct dcerpc_binding_handle *h, TALLOC_CTX *mem_ctx, struct $name *r)";
|
|
||||||
|
|
||||||
$self->fn_declare($proto);
|
|
||||||
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("status = dcerpc_binding_handle_call(h,");
|
|
||||||
$self->pidl("\t\tNULL, &ndr_table_$if->{NAME},");
|
|
||||||
$self->pidl("\t\tNDR_$uname, mem_ctx, r);");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("return status;");
|
|
||||||
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ElementDirection($)
|
|
||||||
{
|
|
||||||
my ($e) = @_;
|
|
||||||
|
|
||||||
return "[in,out]" 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 "[in,out]";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub HeaderProperties($$)
|
|
||||||
{
|
|
||||||
my($props,$ignores) = @_;
|
|
||||||
my $ret = "";
|
|
||||||
|
|
||||||
foreach my $d (sort(keys %{$props})) {
|
|
||||||
next if (grep(/^$d$/, @$ignores));
|
|
||||||
if($props->{$d} ne "1") {
|
|
||||||
$ret.= "$d($props->{$d}),";
|
|
||||||
} else {
|
|
||||||
$ret.="$d,";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ret) {
|
|
||||||
return "[" . substr($ret, 0, -1) . "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseCopyArgument($$$$$)
|
|
||||||
{
|
|
||||||
my ($self, $fn, $e, $r, $i) = @_;
|
|
||||||
my $l = $e->{LEVELS}[0];
|
|
||||||
|
|
||||||
if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED} == 1) {
|
|
||||||
$self->pidl("memcpy(${r}$e->{NAME}, ${i}$e->{NAME}, sizeof(${r}$e->{NAME}));");
|
|
||||||
} else {
|
|
||||||
$self->pidl("${r}$e->{NAME} = ${i}$e->{NAME};");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseInvalidResponse($$)
|
|
||||||
{
|
|
||||||
my ($self, $type) = @_;
|
|
||||||
|
|
||||||
if ($type eq "sync") {
|
|
||||||
$self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;");
|
|
||||||
} elsif ($type eq "async") {
|
|
||||||
$self->pidl("tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);");
|
|
||||||
$self->pidl("return;");
|
|
||||||
} else {
|
|
||||||
die("ParseInvalidResponse($type)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseOutputArgument($$$$$$)
|
|
||||||
{
|
|
||||||
my ($self, $fn, $e, $r, $o, $invalid_response_type) = @_;
|
|
||||||
my $level = 0;
|
|
||||||
|
|
||||||
if ($e->{LEVELS}[0]->{TYPE} ne "POINTER" and $e->{LEVELS}[0]->{TYPE} ne "ARRAY") {
|
|
||||||
fatal($e->{ORIGINAL}, "[out] argument is not a pointer or array");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
|
||||||
$level = 1;
|
|
||||||
if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") {
|
|
||||||
$self->pidl("if ($o$e->{NAME} && ${r}out.$e->{NAME}) {");
|
|
||||||
$self->indent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($e->{LEVELS}[$level]->{TYPE} eq "ARRAY") {
|
|
||||||
# This is a call to GenerateFunctionInEnv intentionally.
|
|
||||||
# Since the data is being copied into a user-provided data
|
|
||||||
# structure, the user should be able to know the size beforehand
|
|
||||||
# to allocate a structure of the right size.
|
|
||||||
my $in_env = GenerateFunctionInEnv($fn, $r);
|
|
||||||
my $out_env = GenerateFunctionOutEnv($fn, $r);
|
|
||||||
my $l = $e->{LEVELS}[$level];
|
|
||||||
|
|
||||||
my $in_var = undef;
|
|
||||||
if (grep(/in/, @{$e->{DIRECTION}})) {
|
|
||||||
$in_var = ParseExpr($e->{NAME}, $in_env, $e->{ORIGINAL});
|
|
||||||
}
|
|
||||||
my $out_var = ParseExpr($e->{NAME}, $out_env, $e->{ORIGINAL});
|
|
||||||
|
|
||||||
my $in_size_is = undef;
|
|
||||||
my $out_size_is = undef;
|
|
||||||
my $out_length_is = undef;
|
|
||||||
|
|
||||||
my $avail_len = undef;
|
|
||||||
my $needed_len = undef;
|
|
||||||
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
my $copy_len_var = "_copy_len_$e->{NAME}";
|
|
||||||
$self->pidl("size_t $copy_len_var;");
|
|
||||||
|
|
||||||
if (not defined($l->{SIZE_IS})) {
|
|
||||||
if (not $l->{IS_ZERO_TERMINATED}) {
|
|
||||||
fatal($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'");
|
|
||||||
}
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
$avail_len = "ndr_charset_length($in_var, CH_UNIX)";
|
|
||||||
$needed_len = "ndr_charset_length($out_var, CH_UNIX)";
|
|
||||||
} else {
|
|
||||||
$avail_len = "ndr_string_length($in_var, sizeof(*$in_var))";
|
|
||||||
$needed_len = "ndr_string_length($out_var, sizeof(*$out_var))";
|
|
||||||
}
|
|
||||||
$in_size_is = "";
|
|
||||||
$out_size_is = "";
|
|
||||||
$out_length_is = "";
|
|
||||||
} else {
|
|
||||||
$in_size_is = ParseExpr($l->{SIZE_IS}, $in_env, $e->{ORIGINAL});
|
|
||||||
$out_size_is = ParseExpr($l->{SIZE_IS}, $out_env, $e->{ORIGINAL});
|
|
||||||
$out_length_is = $out_size_is;
|
|
||||||
if (defined($l->{LENGTH_IS})) {
|
|
||||||
$out_length_is = ParseExpr($l->{LENGTH_IS}, $out_env, $e->{ORIGINAL});
|
|
||||||
}
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
if (defined($in_var)) {
|
|
||||||
$avail_len = "ndr_charset_length($in_var, CH_UNIX)";
|
|
||||||
} else {
|
|
||||||
$avail_len = $out_length_is;
|
|
||||||
}
|
|
||||||
$needed_len = "ndr_charset_length($out_var, CH_UNIX)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($out_size_is ne $in_size_is) {
|
|
||||||
$self->pidl("if (($out_size_is) > ($in_size_is)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->ParseInvalidResponse($invalid_response_type);
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
}
|
|
||||||
if ($out_length_is ne $out_size_is) {
|
|
||||||
$self->pidl("if (($out_length_is) > ($out_size_is)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->ParseInvalidResponse($invalid_response_type);
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
}
|
|
||||||
if (defined($needed_len)) {
|
|
||||||
$self->pidl("$copy_len_var = $needed_len;");
|
|
||||||
$self->pidl("if ($copy_len_var > $avail_len) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->ParseInvalidResponse($invalid_response_type);
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
} else {
|
|
||||||
$self->pidl("$copy_len_var = $out_length_is;");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $dest_ptr = "$o$e->{NAME}";
|
|
||||||
my $elem_size = "sizeof(*$dest_ptr)";
|
|
||||||
$self->pidl("if ($dest_ptr != $out_var) {");
|
|
||||||
$self->indent;
|
|
||||||
if (has_property($e, "charset")) {
|
|
||||||
$dest_ptr = "discard_const_p(uint8_t *, $dest_ptr)";
|
|
||||||
}
|
|
||||||
$self->pidl("memcpy($dest_ptr, $out_var, $copy_len_var * $elem_size);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
} else {
|
|
||||||
$self->pidl("*$o$e->{NAME} = *${r}out.$e->{NAME};");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
|
||||||
if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") {
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_State($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
|
|
||||||
my $state_str = "struct dcerpc_$name\_state";
|
|
||||||
my $done_fn = "dcerpc_$name\_done";
|
|
||||||
|
|
||||||
$self->pidl("$state_str {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct $name orig;");
|
|
||||||
$self->pidl("struct $name tmp;");
|
|
||||||
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("};");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("static void $done_fn(struct tevent_req *subreq);");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_Send($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
|
|
||||||
my $fn_args = "";
|
|
||||||
my $state_str = "struct dcerpc_$name\_state";
|
|
||||||
my $done_fn = "dcerpc_$name\_done";
|
|
||||||
my $out_mem_ctx = "dcerpc_$name\_out_memory";
|
|
||||||
my $fn_str = "struct tevent_req *dcerpc_$name\_send";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "TALLOC_CTX *mem_ctx";
|
|
||||||
$fn_args .= ",\n" . $pad . "struct tevent_context *ev";
|
|
||||||
$fn_args .= ",\n" . $pad . "struct dcerpc_binding_handle *h";
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
my $dir = ElementDirection($_);
|
|
||||||
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
|
||||||
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct tevent_req *req;");
|
|
||||||
$self->pidl("$state_str *state;");
|
|
||||||
$self->pidl("struct tevent_req *subreq;");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
|
||||||
$self->pidl("\t\t\t$state_str);");
|
|
||||||
$self->pidl("if (req == NULL) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return NULL;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("state->out_mem_ctx = NULL;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* In parameters */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless (grep(/in/, @{$e->{DIRECTION}}));
|
|
||||||
|
|
||||||
$self->ParseCopyArgument($fn, $e, "state->orig.in.", "_");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
my $out_params = 0;
|
|
||||||
$self->pidl("/* Out parameters */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless grep(/out/, @{$e->{DIRECTION}});
|
|
||||||
|
|
||||||
$self->ParseCopyArgument($fn, $e, "state->orig.out.", "_");
|
|
||||||
|
|
||||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
|
||||||
|
|
||||||
$out_params++;
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl("/* Result */");
|
|
||||||
$self->pidl("ZERO_STRUCT(state->orig.out.result);");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($out_params > 0) {
|
|
||||||
$self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,");
|
|
||||||
$self->pidl("\t\t \"$out_mem_ctx\");");
|
|
||||||
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("/* make a temporary copy, that we pass to the dispatch function */");
|
|
||||||
$self->pidl("state->tmp = state->orig;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("subreq = dcerpc_$name\_r_send(state, ev, h, &state->tmp);");
|
|
||||||
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return tevent_req_post(req, ev);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("tevent_req_set_callback(subreq, $done_fn, req);");
|
|
||||||
$self->pidl("return req;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_Done($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
|
|
||||||
my $state_str = "struct dcerpc_$name\_state";
|
|
||||||
my $done_fn = "dcerpc_$name\_done";
|
|
||||||
|
|
||||||
$self->pidl("static void $done_fn(struct tevent_req *subreq)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct tevent_req *req = tevent_req_callback_data(");
|
|
||||||
$self->pidl("\tsubreq, struct tevent_req);");
|
|
||||||
$self->pidl("$state_str *state = tevent_req_data(");
|
|
||||||
$self->pidl("\treq, $state_str);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("TALLOC_CTX *mem_ctx;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("if (state->out_mem_ctx) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("mem_ctx = state->out_mem_ctx;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("} else {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("mem_ctx = state;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("status = dcerpc_$name\_r_recv(subreq, mem_ctx);");
|
|
||||||
$self->pidl("TALLOC_FREE(subreq);");
|
|
||||||
$self->pidl("if (tevent_req_nterror(req, status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Copy out parameters */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
|
||||||
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
|
||||||
|
|
||||||
$self->ParseOutputArgument($fn, $e,
|
|
||||||
"state->tmp.",
|
|
||||||
"state->orig.out.",
|
|
||||||
"async");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl("/* Copy result */");
|
|
||||||
$self->pidl("state->orig.out.result = state->tmp.out.result;");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("/* Reset temporary structure */");
|
|
||||||
$self->pidl("ZERO_STRUCT(state->tmp);");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_done(req);");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_Recv($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
|
|
||||||
my $fn_args = "";
|
|
||||||
my $state_str = "struct dcerpc_$name\_state";
|
|
||||||
my $fn_str = "NTSTATUS dcerpc_$name\_recv";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "struct tevent_req *req,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("$state_str *state = tevent_req_data(");
|
|
||||||
$self->pidl("\treq, $state_str);");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return status;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Steal possible out parameters to the callers context */");
|
|
||||||
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl("/* Return result */");
|
|
||||||
$self->pidl("*result = state->orig.out.result;");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("tevent_req_received(req);");
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParseFunction_Sync($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn, $name) = @_;
|
|
||||||
|
|
||||||
if ($self->ParseFunctionHasPipes($fn)) {
|
|
||||||
$self->pidl_both("/*");
|
|
||||||
$self->pidl_both(" * The following function is skipped because");
|
|
||||||
$self->pidl_both(" * it uses pipes:");
|
|
||||||
$self->pidl_both(" *");
|
|
||||||
$self->pidl_both(" * dcerpc_$name()");
|
|
||||||
$self->pidl_both(" */");
|
|
||||||
$self->pidl_both("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $uname = uc $name;
|
|
||||||
my $fn_args = "";
|
|
||||||
my $fn_str = "NTSTATUS dcerpc_$name";
|
|
||||||
my $pad = genpad($fn_str);
|
|
||||||
|
|
||||||
$fn_args .= "struct dcerpc_binding_handle *h,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
|
||||||
|
|
||||||
foreach (@{$fn->{ELEMENTS}}) {
|
|
||||||
my $dir = ElementDirection($_);
|
|
||||||
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
|
||||||
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->fn_declare("$fn_str($fn_args)");
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("struct $name r;");
|
|
||||||
$self->pidl("NTSTATUS status;");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* In parameters */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless (grep(/in/, @{$e->{DIRECTION}}));
|
|
||||||
|
|
||||||
$self->ParseCopyArgument($fn, $e, "r.in.", "_");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Out parameters */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless grep(/out/, @{$e->{DIRECTION}});
|
|
||||||
|
|
||||||
$self->ParseCopyArgument($fn, $e, "r.out.", "_");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
if (defined($fn->{RETURN_TYPE})) {
|
|
||||||
$self->pidl("/* Result */");
|
|
||||||
$self->pidl("ZERO_STRUCT(r.out.result);");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("status = dcerpc_$name\_r(h, mem_ctx, &r);");
|
|
||||||
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("return status;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Return variables */");
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
|
||||||
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
|
||||||
|
|
||||||
$self->ParseOutputArgument($fn, $e, "r.", "_", "sync");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("/* Return result */");
|
|
||||||
if ($fn->{RETURN_TYPE}) {
|
|
||||||
$self->pidl("*result = r.out.result;");
|
|
||||||
}
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a function
|
|
||||||
sub ParseFunction($$$)
|
|
||||||
{
|
|
||||||
my ($self, $if, $fn) = @_;
|
|
||||||
|
|
||||||
if ($self->ParseFunctionHasPipes($fn)) {
|
|
||||||
$self->pidl_both("/*");
|
|
||||||
$self->pidl_both(" * The following function is skipped because");
|
|
||||||
$self->pidl_both(" * it uses pipes:");
|
|
||||||
$self->pidl_both(" *");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_r_send()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_r_recv()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_r()");
|
|
||||||
$self->pidl_both(" *");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_send()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_recv()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}()");
|
|
||||||
$self->pidl_both(" */");
|
|
||||||
$self->pidl_both("");
|
|
||||||
warning($fn->{ORIGINAL}, "$fn->{NAME}: dcerpc client does not support pipe yet");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->ParseFunction_r_State($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_r_Send($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_r_Done($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_r_Recv($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_r_Sync($if, $fn, $fn->{NAME});
|
|
||||||
|
|
||||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
|
||||||
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
|
||||||
|
|
||||||
my $reason = "is not a pointer or array";
|
|
||||||
|
|
||||||
# TODO: make this fatal at NDR level
|
|
||||||
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
|
||||||
if ($e->{LEVELS}[1]->{TYPE} eq "DATA" and
|
|
||||||
$e->{LEVELS}[1]->{DATA_TYPE} eq "string") {
|
|
||||||
$reason = "is a pointer to type 'string'";
|
|
||||||
} elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and
|
|
||||||
$e->{LEVELS}[1]->{IS_ZERO_TERMINATED}) {
|
|
||||||
next;
|
|
||||||
} elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and
|
|
||||||
not defined($e->{LEVELS}[1]->{SIZE_IS})) {
|
|
||||||
$reason = "is a pointer to an unsized array";
|
|
||||||
} else {
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($e->{LEVELS}[0]->{TYPE} eq "ARRAY") {
|
|
||||||
if (not defined($e->{LEVELS}[0]->{SIZE_IS})) {
|
|
||||||
$reason = "is an unsized array";
|
|
||||||
} else {
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl_both("/*");
|
|
||||||
$self->pidl_both(" * The following functions are skipped because");
|
|
||||||
$self->pidl_both(" * an [out] argument $e->{NAME} $reason:");
|
|
||||||
$self->pidl_both(" *");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_send()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_recv()");
|
|
||||||
$self->pidl_both(" * dcerpc_$fn->{NAME}()");
|
|
||||||
$self->pidl_both(" */");
|
|
||||||
$self->pidl_both("");
|
|
||||||
|
|
||||||
error($e->{ORIGINAL}, "$fn->{NAME}: [out] argument '$e->{NAME}' $reason, skip client functions");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->ParseFunction_State($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_Send($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_Done($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_Recv($if, $fn, $fn->{NAME});
|
|
||||||
$self->ParseFunction_Sync($if, $fn, $fn->{NAME});
|
|
||||||
|
|
||||||
$self->pidl_hdr("");
|
|
||||||
}
|
|
||||||
|
|
||||||
my %done;
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse the interface definitions
|
|
||||||
sub ParseInterface($$)
|
|
||||||
{
|
|
||||||
my ($self, $if) = @_;
|
|
||||||
my $ifu = uc($if->{NAME});
|
|
||||||
|
|
||||||
$self->pidl_hdr("#ifndef _HEADER_RPC_$if->{NAME}");
|
|
||||||
$self->pidl_hdr("#define _HEADER_RPC_$if->{NAME}");
|
|
||||||
$self->pidl_hdr("");
|
|
||||||
|
|
||||||
if (defined $if->{PROPERTIES}->{uuid}) {
|
|
||||||
$self->pidl_hdr("extern const struct ndr_interface_table ndr_table_$if->{NAME};");
|
|
||||||
$self->pidl_hdr("");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("/* $if->{NAME} - client functions generated by pidl */");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
foreach my $fn (@{$if->{FUNCTIONS}}) {
|
|
||||||
next if defined($done{$fn->{NAME}});
|
|
||||||
next if has_property($fn, "noopnum");
|
|
||||||
next if has_property($fn, "todo");
|
|
||||||
$self->ParseFunction($if, $fn);
|
|
||||||
$done{$fn->{NAME}} = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl_hdr("#endif /* _HEADER_RPC_$if->{NAME} */");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$$$$$)
|
|
||||||
{
|
|
||||||
my($self,$ndr,$header,$ndr_header,$client_header) = @_;
|
|
||||||
|
|
||||||
$self->pidl("/* client functions auto-generated by pidl */");
|
|
||||||
$self->pidl("");
|
|
||||||
if (is_intree()) {
|
|
||||||
$self->pidl("#include \"includes.h\"");
|
|
||||||
} else {
|
|
||||||
$self->pidl("#ifndef _GNU_SOURCE");
|
|
||||||
$self->pidl("#define _GNU_SOURCE");
|
|
||||||
$self->pidl("#endif");
|
|
||||||
$self->pidl("#include <stdio.h>");
|
|
||||||
$self->pidl("#include <stdbool.h>");
|
|
||||||
$self->pidl("#include <stdlib.h>");
|
|
||||||
$self->pidl("#include <stdint.h>");
|
|
||||||
$self->pidl("#include <stdarg.h>");
|
|
||||||
$self->pidl("#include <string.h>");
|
|
||||||
$self->pidl("#include <core/ntstatus.h>");
|
|
||||||
}
|
|
||||||
$self->pidl("#include <tevent.h>");
|
|
||||||
$self->pidl(choose_header("lib/util/tevent_ntstatus.h", "util/tevent_ntstatus.h")."");
|
|
||||||
$self->pidl("#include \"$ndr_header\"");
|
|
||||||
$self->pidl("#include \"$client_header\"");
|
|
||||||
$self->pidl("");
|
|
||||||
|
|
||||||
$self->pidl_hdr(choose_header("librpc/rpc/dcerpc.h", "dcerpc.h")."");
|
|
||||||
$self->pidl_hdr("#include \"$header\"");
|
|
||||||
|
|
||||||
foreach my $x (@{$ndr}) {
|
|
||||||
($x->{TYPE} eq "INTERFACE") && $self->ParseInterface($x);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($self->{res},$self->{res_hdr});
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,335 +0,0 @@
|
||||||
###################################################
|
|
||||||
# server boilerplate generator
|
|
||||||
# Copyright tridge@samba.org 2003
|
|
||||||
# Copyright metze@samba.org 2004
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::NDR::Server;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Parse::Pidl::Util;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
sub pidl($)
|
|
||||||
{
|
|
||||||
$res .= shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################
|
|
||||||
# generate the switch statement for function dispatch
|
|
||||||
sub gen_dispatch_switch($)
|
|
||||||
{
|
|
||||||
my $interface = shift;
|
|
||||||
|
|
||||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
|
||||||
next if not defined($fn->{OPNUM});
|
|
||||||
|
|
||||||
pidl "\tcase $fn->{OPNUM}: {\n";
|
|
||||||
pidl "\t\tstruct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;\n";
|
|
||||||
pidl "\t\tif (DEBUGLEVEL >= 10) {\n";
|
|
||||||
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_IN, r2);\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
|
|
||||||
pidl "\t\tr2->out.result = dcesrv_$fn->{NAME}(dce_call, mem_ctx, r2);\n";
|
|
||||||
} else {
|
|
||||||
pidl "\t\tdcesrv_$fn->{NAME}(dce_call, mem_ctx, r2);\n";
|
|
||||||
}
|
|
||||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(5,(\"function $fn->{NAME} will reply async\\n\"));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tbreak;\n\t}\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################
|
|
||||||
# generate the switch statement for function reply
|
|
||||||
sub gen_reply_switch($)
|
|
||||||
{
|
|
||||||
my $interface = shift;
|
|
||||||
|
|
||||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
|
||||||
next if not defined($fn->{OPNUM});
|
|
||||||
|
|
||||||
pidl "\tcase $fn->{OPNUM}: {\n";
|
|
||||||
pidl "\t\tstruct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;\n";
|
|
||||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(5,(\"function $fn->{NAME} replied async\\n\"));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tif (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {\n";
|
|
||||||
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tif (dce_call->fault_code != 0) {\n";
|
|
||||||
pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $fn->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n";
|
|
||||||
pidl "\t\t}\n";
|
|
||||||
pidl "\t\tbreak;\n\t}\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for a interface
|
|
||||||
sub Boilerplate_Iface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
my $uname = uc $name;
|
|
||||||
my $uuid = lc($interface->{UUID});
|
|
||||||
my $if_version = $interface->{VERSION};
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
|
|
||||||
{
|
|
||||||
#ifdef DCESRV_INTERFACE_$uname\_BIND
|
|
||||||
return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface);
|
|
||||||
#else
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
|
|
||||||
{
|
|
||||||
#ifdef DCESRV_INTERFACE_$uname\_UNBIND
|
|
||||||
DCESRV_INTERFACE_$uname\_UNBIND(context, iface);
|
|
||||||
#else
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
|
|
||||||
{
|
|
||||||
enum ndr_err_code ndr_err;
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
dce_call->fault_code = 0;
|
|
||||||
|
|
||||||
if (opnum >= ndr_table_$name.num_calls) {
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
*r = talloc_named(mem_ctx,
|
|
||||||
ndr_table_$name.calls[opnum].struct_size,
|
|
||||||
\"struct %s\",
|
|
||||||
ndr_table_$name.calls[opnum].name);
|
|
||||||
NT_STATUS_HAVE_NO_MEMORY(*r);
|
|
||||||
|
|
||||||
/* unravel the NDR for the packet */
|
|
||||||
ndr_err = ndr_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|
||||||
dcerpc_log_packet(dce_call->conn->packet_log_dir,
|
|
||||||
&ndr_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
|
||||||
{
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
switch (opnum) {
|
|
||||||
";
|
|
||||||
gen_dispatch_switch($interface);
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
default:
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dce_call->fault_code != 0) {
|
|
||||||
dcerpc_log_packet(dce_call->conn->packet_log_dir,
|
|
||||||
&ndr_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
|
||||||
{
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
switch (opnum) {
|
|
||||||
";
|
|
||||||
gen_reply_switch($interface);
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
default:
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dce_call->fault_code != 0) {
|
|
||||||
dcerpc_log_packet(dce_call->conn->packet_log_dir,
|
|
||||||
&ndr_table_$name, opnum, NDR_IN,
|
|
||||||
&dce_call->pkt.u.request.stub_and_verifier);
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
|
|
||||||
{
|
|
||||||
enum ndr_err_code ndr_err;
|
|
||||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
|
||||||
|
|
||||||
ndr_err = ndr_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|
||||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
|
||||||
return NT_STATUS_NET_WRITE_FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct dcesrv_interface dcesrv\_$name\_interface = {
|
|
||||||
.name = \"$name\",
|
|
||||||
.syntax_id = {".print_uuid($uuid).",$if_version},
|
|
||||||
.bind = $name\__op_bind,
|
|
||||||
.unbind = $name\__op_unbind,
|
|
||||||
.ndr_pull = $name\__op_ndr_pull,
|
|
||||||
.dispatch = $name\__op_dispatch,
|
|
||||||
.reply = $name\__op_reply,
|
|
||||||
.ndr_push = $name\__op_ndr_push
|
|
||||||
};
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for an endpoint server
|
|
||||||
sub Boilerplate_Ep_Server($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
my $uname = uc $name;
|
|
||||||
|
|
||||||
pidl "
|
|
||||||
static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0;i<ndr_table_$name.endpoints->count;i++) {
|
|
||||||
NTSTATUS ret;
|
|
||||||
const char *name = ndr_table_$name.endpoints->names[i];
|
|
||||||
|
|
||||||
ret = dcesrv_interface_register(dce_ctx, name, &dcesrv_$name\_interface, NULL);
|
|
||||||
if (!NT_STATUS_IS_OK(ret)) {
|
|
||||||
DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version)
|
|
||||||
{
|
|
||||||
if (dcesrv_$name\_interface.syntax_id.if_version == if_version &&
|
|
||||||
GUID_equal(\&dcesrv\_$name\_interface.syntax_id.uuid, uuid)) {
|
|
||||||
memcpy(iface,&dcesrv\_$name\_interface, sizeof(*iface));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
|
|
||||||
{
|
|
||||||
if (strcmp(dcesrv_$name\_interface.name, name)==0) {
|
|
||||||
memcpy(iface, &dcesrv_$name\_interface, sizeof(*iface));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS dcerpc_server_$name\_init(void)
|
|
||||||
{
|
|
||||||
NTSTATUS ret;
|
|
||||||
struct dcesrv_endpoint_server ep_server;
|
|
||||||
|
|
||||||
/* fill in our name */
|
|
||||||
ep_server.name = \"$name\";
|
|
||||||
|
|
||||||
/* fill in all the operations */
|
|
||||||
ep_server.init_server = $name\__op_init_server;
|
|
||||||
|
|
||||||
ep_server.interface_by_uuid = $name\__op_interface_by_uuid;
|
|
||||||
ep_server.interface_by_name = $name\__op_interface_by_name;
|
|
||||||
|
|
||||||
/* register ourselves with the DCERPC subsystem. */
|
|
||||||
ret = dcerpc_register_ep_server(&ep_server);
|
|
||||||
|
|
||||||
if (!NT_STATUS_IS_OK(ret)) {
|
|
||||||
DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# dcerpc server boilerplate from a parsed IDL structure
|
|
||||||
sub ParseInterface($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my $count = 0;
|
|
||||||
|
|
||||||
$res .= "NTSTATUS dcerpc_server_$interface->{NAME}\_init(void);\n";
|
|
||||||
$res .= "\n";
|
|
||||||
|
|
||||||
if (!defined $interface->{PROPERTIES}->{uuid}) {
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defined $interface->{PROPERTIES}->{version}) {
|
|
||||||
$interface->{PROPERTIES}->{version} = "0.0";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
|
||||||
if (defined($fn->{OPNUM})) { $count++; }
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($count == 0) {
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= "/* $interface->{NAME} - dcerpc server boilerplate generated by pidl */\n\n";
|
|
||||||
Boilerplate_Iface($interface);
|
|
||||||
Boilerplate_Ep_Server($interface);
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parse($$)
|
|
||||||
{
|
|
||||||
my($ndr,$header) = @_;
|
|
||||||
|
|
||||||
$res = "";
|
|
||||||
$res .= "/* server functions auto-generated by pidl */\n";
|
|
||||||
$res .= "#include \"$header\"\n";
|
|
||||||
$res .= "#include <util/debug.h>\n";
|
|
||||||
$res .= "\n";
|
|
||||||
|
|
||||||
foreach my $x (@{$ndr}) {
|
|
||||||
ParseInterface($x) if ($x->{TYPE} eq "INTERFACE" and not defined($x->{PROPERTIES}{object}));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,283 +0,0 @@
|
||||||
###################################################
|
|
||||||
# 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 Parse::Pidl::Typelist qw(mapTypeName);
|
|
||||||
|
|
||||||
use Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(ParserType $ret $ret_hdr);
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
sub new($) {
|
|
||||||
my ($class) = shift;
|
|
||||||
my $self = { ret => "", ret_hdr => "", tabs => "" };
|
|
||||||
bless($self, $class);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub indent($) { my $self = shift; $self->{tabs}.="\t"; }
|
|
||||||
sub deindent($) { my $self = shift; $self->{tabs} = substr($self->{tabs}, 1); }
|
|
||||||
sub pidl($$) { my $self = shift; $self->{ret} .= $self->{tabs}.(shift)."\n"; }
|
|
||||||
sub pidl_hdr($$) { my $self = shift; $self->{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 ($self, $p, $d) = @_;
|
|
||||||
if ($p) {
|
|
||||||
$self->pidl($d); $self->pidl_hdr("$d;");
|
|
||||||
} else {
|
|
||||||
$self->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 ($self, $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")) {
|
|
||||||
$self->pidl("{");
|
|
||||||
$self->indent;
|
|
||||||
$self->pidl("uint32_t saved_flags = tdr->flags;");
|
|
||||||
$self->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");
|
|
||||||
$self->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)) {
|
|
||||||
$self->pidl("TDR_ALLOC(mem_ctx, v->$e->{NAME}, $len);");
|
|
||||||
$mem_ctx = "v->$e->{NAME}";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("for (i = 0; i < $len; i++) {");
|
|
||||||
$self->indent;
|
|
||||||
$array = "[i]";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($t eq "pull") {
|
|
||||||
$name = ", $mem_ctx";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_property($e, "value") && $t eq "push") {
|
|
||||||
$self->pidl("v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env, $e).";");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));");
|
|
||||||
|
|
||||||
if ($array) { $self->deindent; $self->pidl("}"); }
|
|
||||||
|
|
||||||
if (has_property($e, "flag")) {
|
|
||||||
$self->pidl("tdr->flags = saved_flags;");
|
|
||||||
$self->deindent;
|
|
||||||
$self->pidl("}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserStruct($$$$$)
|
|
||||||
{
|
|
||||||
my ($self, $e,$t,$p) = @_;
|
|
||||||
|
|
||||||
$self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", struct $e->{NAME} *v)");
|
|
||||||
$self->pidl("{"); $self->indent;
|
|
||||||
$self->pidl("int i;") if (ContainsArray($e));
|
|
||||||
|
|
||||||
if ($t eq "print") {
|
|
||||||
$self->pidl("tdr->print(tdr, \"\%-25s: struct $e->{NAME}\", name);");
|
|
||||||
$self->pidl("tdr->level++;");
|
|
||||||
}
|
|
||||||
|
|
||||||
my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}};
|
|
||||||
$env{"this"} = "v";
|
|
||||||
$self->ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}});
|
|
||||||
|
|
||||||
if ($t eq "print") {
|
|
||||||
$self->pidl("tdr->level--;");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("return NT_STATUS_OK;");
|
|
||||||
|
|
||||||
$self->deindent; $self->pidl("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserUnion($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $e,$t,$p) = @_;
|
|
||||||
|
|
||||||
$self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME}(struct tdr_$t *tdr".typearg($t).", int level, union $e->{NAME} *v)");
|
|
||||||
$self->pidl("{"); $self->indent;
|
|
||||||
$self->pidl("int i;") if (ContainsArray($e));
|
|
||||||
|
|
||||||
if ($t eq "print") {
|
|
||||||
$self->pidl("tdr->print(tdr, \"\%-25s: union $e->{NAME}\", name);");
|
|
||||||
$self->pidl("tdr->level++;");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("switch (level) {"); $self->indent;
|
|
||||||
foreach (@{$e->{ELEMENTS}}) {
|
|
||||||
if (has_property($_, "case")) {
|
|
||||||
$self->pidl("case " . $_->{PROPERTIES}->{case} . ":");
|
|
||||||
} elsif (has_property($_, "default")) {
|
|
||||||
$self->pidl("default:");
|
|
||||||
}
|
|
||||||
$self->indent; $self->ParserElement($_, $t, {}); $self->deindent;
|
|
||||||
$self->pidl("break;");
|
|
||||||
}
|
|
||||||
$self->deindent; $self->pidl("}");
|
|
||||||
|
|
||||||
if ($t eq "print") {
|
|
||||||
$self->pidl("tdr->level--;");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl("return NT_STATUS_OK;\n");
|
|
||||||
$self->deindent; $self->pidl("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserBitmap($$$$)
|
|
||||||
{
|
|
||||||
my ($self,$e,$t,$p) = @_;
|
|
||||||
return if ($p);
|
|
||||||
$self->pidl("#define tdr_$t\_$e->{NAME} tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e));
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserEnum($$$$)
|
|
||||||
{
|
|
||||||
my ($self,$e,$t,$p) = @_;
|
|
||||||
my $bt = Parse::Pidl::Typelist::enum_type_fn($e);
|
|
||||||
my $mt = mapTypeName($bt);
|
|
||||||
|
|
||||||
$self->fn_declare($p, "NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", enum $e->{NAME} *v)");
|
|
||||||
$self->pidl("{");
|
|
||||||
if ($t eq "pull") {
|
|
||||||
$self->pidl("\t$mt r;");
|
|
||||||
$self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, mem_ctx, \&r));");
|
|
||||||
$self->pidl("\t*v = r;");
|
|
||||||
} elsif ($t eq "push") {
|
|
||||||
$self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, ($mt *)v));");
|
|
||||||
} elsif ($t eq "print") {
|
|
||||||
$self->pidl("\t/* FIXME */");
|
|
||||||
}
|
|
||||||
$self->pidl("\treturn NT_STATUS_OK;");
|
|
||||||
$self->pidl("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserTypedef($$$$)
|
|
||||||
{
|
|
||||||
my ($self, $e,$t,$p) = @_;
|
|
||||||
|
|
||||||
$self->ParserType($e->{DATA},$t);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserType($$$)
|
|
||||||
{
|
|
||||||
my ($self, $e,$t) = @_;
|
|
||||||
|
|
||||||
return if (has_property($e, "no$t"));
|
|
||||||
|
|
||||||
my $handlers = {
|
|
||||||
STRUCT => \&ParserStruct, UNION => \&ParserUnion,
|
|
||||||
ENUM => \&ParserEnum, BITMAP => \&ParserBitmap,
|
|
||||||
TYPEDEF => \&ParserTypedef
|
|
||||||
};
|
|
||||||
|
|
||||||
$handlers->{$e->{TYPE}}->($self, $e, $t, has_property($e, "public"))
|
|
||||||
if (defined($handlers->{$e->{TYPE}}));
|
|
||||||
|
|
||||||
$self->pidl("");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ParserInterface($$)
|
|
||||||
{
|
|
||||||
my ($self,$x) = @_;
|
|
||||||
|
|
||||||
$self->pidl_hdr("#ifndef __TDR_$x->{NAME}_HEADER__");
|
|
||||||
$self->pidl_hdr("#define __TDR_$x->{NAME}_HEADER__");
|
|
||||||
|
|
||||||
foreach (@{$x->{DATA}}) {
|
|
||||||
$self->ParserType($_, "pull");
|
|
||||||
$self->ParserType($_, "push");
|
|
||||||
$self->ParserType($_, "print");
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->pidl_hdr("#endif /* __TDR_$x->{NAME}_HEADER__ */");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Parser($$$$)
|
|
||||||
{
|
|
||||||
my ($self,$idl,$hdrname,$baseheader) = @_;
|
|
||||||
$self->pidl("/* autogenerated by pidl */");
|
|
||||||
if (is_intree()) {
|
|
||||||
$self->pidl("#include \"includes.h\"");
|
|
||||||
} else {
|
|
||||||
$self->pidl("#include <stdio.h>");
|
|
||||||
$self->pidl("#include <stdbool.h>");
|
|
||||||
$self->pidl("#include <stdlib.h>");
|
|
||||||
$self->pidl("#include <stdint.h>");
|
|
||||||
$self->pidl("#include <stdarg.h>");
|
|
||||||
$self->pidl("#include <string.h>");
|
|
||||||
$self->pidl("#include <core/ntstatus.h>");
|
|
||||||
}
|
|
||||||
$self->pidl("#include \"$hdrname\"");
|
|
||||||
$self->pidl("");
|
|
||||||
$self->pidl_hdr("/* autogenerated by pidl */");
|
|
||||||
$self->pidl_hdr("#include \"$baseheader\"");
|
|
||||||
$self->pidl_hdr(choose_header("lib/tdr/tdr.h", "tdr.h"));
|
|
||||||
$self->pidl_hdr("");
|
|
||||||
|
|
||||||
foreach (@$idl) { $self->ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); }
|
|
||||||
return ($self->{ret_hdr}, $self->{ret});
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,103 +0,0 @@
|
||||||
###################################################
|
|
||||||
# server template function generator
|
|
||||||
# Copyright tridge@samba.org 2003
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Samba4::Template;
|
|
||||||
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use Parse::Pidl::Util qw(genpad);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
my($res);
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# produce boilerplate code for a interface
|
|
||||||
sub Template($)
|
|
||||||
{
|
|
||||||
my($interface) = shift;
|
|
||||||
my($data) = $interface->{DATA};
|
|
||||||
my $name = $interface->{NAME};
|
|
||||||
|
|
||||||
$res .=
|
|
||||||
"/*
|
|
||||||
Unix SMB/CIFS implementation.
|
|
||||||
|
|
||||||
endpoint server for the $name pipe
|
|
||||||
|
|
||||||
Copyright (C) YOUR NAME HERE YEAR
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include \"includes.h\"
|
|
||||||
#include \"rpc_server/dcerpc_server.h\"
|
|
||||||
#include \"librpc/gen_ndr/ndr_$name.h\"
|
|
||||||
#include \"rpc_server/common/common.h\"
|
|
||||||
|
|
||||||
";
|
|
||||||
|
|
||||||
foreach my $d (@{$data}) {
|
|
||||||
if ($d->{TYPE} eq "FUNCTION") {
|
|
||||||
my $fname = $d->{NAME};
|
|
||||||
my $pad = genpad("static $d->{RETURN_TYPE} dcesrv_$fname");
|
|
||||||
$res .=
|
|
||||||
"
|
|
||||||
/*
|
|
||||||
$fname
|
|
||||||
*/
|
|
||||||
|
|
||||||
static $d->{RETURN_TYPE} dcesrv_$fname(struct dcesrv_call_state *dce_call,
|
|
||||||
$pad"."TALLOC_CTX *mem_ctx,
|
|
||||||
$pad"."struct $fname *r)
|
|
||||||
{
|
|
||||||
";
|
|
||||||
|
|
||||||
if ($d->{RETURN_TYPE} eq "void") {
|
|
||||||
$res .= "\tDCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);\n";
|
|
||||||
} else {
|
|
||||||
$res .= "\tDCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .= "}
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res .=
|
|
||||||
"
|
|
||||||
/* include the generated boilerplate */
|
|
||||||
#include \"librpc/gen_ndr/ndr_$name\_s.c\"
|
|
||||||
"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# parse a parsed IDL structure back into an IDL file
|
|
||||||
sub Parse($)
|
|
||||||
{
|
|
||||||
my($idl) = shift;
|
|
||||||
$res = "";
|
|
||||||
foreach my $x (@{$idl}) {
|
|
||||||
($x->{TYPE} eq "INTERFACE") &&
|
|
||||||
Template($x);
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,354 +0,0 @@
|
||||||
###################################################
|
|
||||||
# Samba4 parser generator for IDL structures
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
package Parse::Pidl::Typelist;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(hasType getType resolveType mapTypeName scalar_is_reference expandAlias
|
|
||||||
mapScalarType addType typeIs is_signed is_scalar enum_type_fn
|
|
||||||
bitmap_type_fn mapType typeHasBody is_fixed_size_scalar
|
|
||||||
);
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
my %types = ();
|
|
||||||
|
|
||||||
my @reference_scalars = (
|
|
||||||
"string", "string_array", "nbt_string", "dns_string",
|
|
||||||
"wrepl_nbt_name", "dnsp_name", "dnsp_string",
|
|
||||||
"ipv4address", "ipv6address"
|
|
||||||
);
|
|
||||||
|
|
||||||
my @non_fixed_size_scalars = (
|
|
||||||
"string", "string_array", "nbt_string", "dns_string",
|
|
||||||
"wrepl_nbt_name", "dnsp_name", "dnsp_string"
|
|
||||||
);
|
|
||||||
|
|
||||||
# a list of known scalar types
|
|
||||||
my %scalars = (
|
|
||||||
"void" => "void",
|
|
||||||
"char" => "char",
|
|
||||||
"int8" => "int8_t",
|
|
||||||
"uint8" => "uint8_t",
|
|
||||||
"int16" => "int16_t",
|
|
||||||
"uint16" => "uint16_t",
|
|
||||||
"int1632" => "int16_t",
|
|
||||||
"uint1632" => "uint16_t",
|
|
||||||
"int32" => "int32_t",
|
|
||||||
"uint32" => "uint32_t",
|
|
||||||
"int3264" => "int32_t",
|
|
||||||
"uint3264" => "uint32_t",
|
|
||||||
"hyper" => "uint64_t",
|
|
||||||
"dlong" => "int64_t",
|
|
||||||
"udlong" => "uint64_t",
|
|
||||||
"udlongr" => "uint64_t",
|
|
||||||
"double" => "double",
|
|
||||||
"pointer" => "void*",
|
|
||||||
"DATA_BLOB" => "DATA_BLOB",
|
|
||||||
"string" => "const char *",
|
|
||||||
"string_array" => "const char **",
|
|
||||||
"time_t" => "time_t",
|
|
||||||
"uid_t" => "uid_t",
|
|
||||||
"gid_t" => "gid_t",
|
|
||||||
"NTTIME" => "NTTIME",
|
|
||||||
"NTTIME_1sec" => "NTTIME",
|
|
||||||
"NTTIME_hyper" => "NTTIME",
|
|
||||||
"WERROR" => "WERROR",
|
|
||||||
"HRESULT" => "HRESULT",
|
|
||||||
"NTSTATUS" => "NTSTATUS",
|
|
||||||
"COMRESULT" => "COMRESULT",
|
|
||||||
"dns_string" => "const char *",
|
|
||||||
"nbt_string" => "const char *",
|
|
||||||
"wrepl_nbt_name"=> "struct nbt_name *",
|
|
||||||
"ipv4address" => "const char *",
|
|
||||||
"ipv6address" => "const char *",
|
|
||||||
"dnsp_name" => "const char *",
|
|
||||||
"dnsp_string" => "const char *",
|
|
||||||
);
|
|
||||||
|
|
||||||
my %aliases = (
|
|
||||||
"error_status_t" => "uint32",
|
|
||||||
"boolean8" => "uint8",
|
|
||||||
"boolean32" => "uint32",
|
|
||||||
"DWORD" => "uint32",
|
|
||||||
"uint" => "uint32",
|
|
||||||
"int" => "int32",
|
|
||||||
"WORD" => "uint16",
|
|
||||||
"char" => "uint8",
|
|
||||||
"long" => "int32",
|
|
||||||
"short" => "int16",
|
|
||||||
"HYPER_T" => "hyper",
|
|
||||||
"mode_t" => "uint32",
|
|
||||||
);
|
|
||||||
|
|
||||||
sub expandAlias($)
|
|
||||||
{
|
|
||||||
my $name = shift;
|
|
||||||
|
|
||||||
return $aliases{$name} if defined($aliases{$name});
|
|
||||||
|
|
||||||
return $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
# map from a IDL type to a C header type
|
|
||||||
sub mapScalarType($)
|
|
||||||
{
|
|
||||||
my $name = shift;
|
|
||||||
|
|
||||||
# it's a bug when a type is not in the list
|
|
||||||
# of known scalars or has no mapping
|
|
||||||
return $scalars{$name} if defined($scalars{$name});
|
|
||||||
|
|
||||||
die("Unknown scalar type $name");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub addType($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
$types{$t->{NAME}} = $t;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub resolveType($)
|
|
||||||
{
|
|
||||||
my ($ctype) = @_;
|
|
||||||
|
|
||||||
if (not hasType($ctype)) {
|
|
||||||
# assume struct typedef
|
|
||||||
return { TYPE => "TYPEDEF", NAME => $ctype, DATA => { TYPE => "STRUCT" } };
|
|
||||||
} else {
|
|
||||||
return getType($ctype);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ctype;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub getType($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
return ($t) if (ref($t) eq "HASH" and not defined($t->{NAME}));
|
|
||||||
return undef if not hasType($t);
|
|
||||||
return $types{$t->{NAME}} if (ref($t) eq "HASH");
|
|
||||||
return $types{$t};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub typeIs($$);
|
|
||||||
sub typeIs($$)
|
|
||||||
{
|
|
||||||
my ($t,$tt) = @_;
|
|
||||||
|
|
||||||
if (ref($t) eq "HASH") {
|
|
||||||
return 1 if ($t->{TYPE} eq "TYPEDEF" and $t->{DATA}->{TYPE} eq $tt);
|
|
||||||
return 1 if ($t->{TYPE} eq $tt);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (hasType($t) and getType($t)->{TYPE} eq "TYPEDEF") {
|
|
||||||
return typeIs(getType($t)->{DATA}, $tt);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub hasType($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
if (ref($t) eq "HASH") {
|
|
||||||
return 1 if (not defined($t->{NAME}));
|
|
||||||
return 1 if (defined($types{$t->{NAME}}) and
|
|
||||||
$types{$t->{NAME}}->{TYPE} eq $t->{TYPE});
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1 if defined($types{$t});
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub is_signed($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
|
|
||||||
return ($t eq "int8"
|
|
||||||
or $t eq "int16"
|
|
||||||
or $t eq "int32"
|
|
||||||
or $t eq "dlong"
|
|
||||||
or $t eq "int"
|
|
||||||
or $t eq "long"
|
|
||||||
or $t eq "short");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub is_scalar($)
|
|
||||||
{
|
|
||||||
sub is_scalar($);
|
|
||||||
my $type = shift;
|
|
||||||
|
|
||||||
return 1 if (ref($type) eq "HASH" and
|
|
||||||
($type->{TYPE} eq "SCALAR" or $type->{TYPE} eq "ENUM" or
|
|
||||||
$type->{TYPE} eq "BITMAP"));
|
|
||||||
|
|
||||||
if (my $dt = getType($type)) {
|
|
||||||
return is_scalar($dt->{DATA}) if ($dt->{TYPE} eq "TYPEDEF");
|
|
||||||
return 1 if ($dt->{TYPE} eq "SCALAR" or $dt->{TYPE} eq "ENUM" or
|
|
||||||
$dt->{TYPE} eq "BITMAP");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub is_fixed_size_scalar($)
|
|
||||||
{
|
|
||||||
my $name = shift;
|
|
||||||
|
|
||||||
return 0 unless is_scalar($name);
|
|
||||||
return 0 if (grep(/^$name$/, @non_fixed_size_scalars));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub scalar_is_reference($)
|
|
||||||
{
|
|
||||||
my $name = shift;
|
|
||||||
|
|
||||||
return 1 if (grep(/^$name$/, @reference_scalars));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub RegisterScalars()
|
|
||||||
{
|
|
||||||
foreach (keys %scalars) {
|
|
||||||
addType({
|
|
||||||
NAME => $_,
|
|
||||||
TYPE => "TYPEDEF",
|
|
||||||
BASEFILE => "<builtin>",
|
|
||||||
DATA => {
|
|
||||||
TYPE => "SCALAR",
|
|
||||||
NAME => $_
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub enum_type_fn($)
|
|
||||||
{
|
|
||||||
my $enum = shift;
|
|
||||||
$enum->{TYPE} eq "ENUM" or die("not an enum");
|
|
||||||
|
|
||||||
# for typedef enum { } we need to check $enum->{PARENT}
|
|
||||||
if (has_property($enum, "enum8bit")) {
|
|
||||||
return "uint8";
|
|
||||||
} elsif (has_property($enum, "enum16bit")) {
|
|
||||||
return "uint16";
|
|
||||||
} elsif (has_property($enum, "v1_enum")) {
|
|
||||||
return "uint32";
|
|
||||||
} elsif (has_property($enum->{PARENT}, "enum8bit")) {
|
|
||||||
return "uint8";
|
|
||||||
} elsif (has_property($enum->{PARENT}, "enum16bit")) {
|
|
||||||
return "uint16";
|
|
||||||
} elsif (has_property($enum->{PARENT}, "v1_enum")) {
|
|
||||||
return "uint32";
|
|
||||||
}
|
|
||||||
return "uint1632";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub bitmap_type_fn($)
|
|
||||||
{
|
|
||||||
my $bitmap = shift;
|
|
||||||
|
|
||||||
$bitmap->{TYPE} eq "BITMAP" or die("not a bitmap");
|
|
||||||
|
|
||||||
if (has_property($bitmap, "bitmap8bit")) {
|
|
||||||
return "uint8";
|
|
||||||
} elsif (has_property($bitmap, "bitmap16bit")) {
|
|
||||||
return "uint16";
|
|
||||||
} elsif (has_property($bitmap, "bitmap64bit")) {
|
|
||||||
return "hyper";
|
|
||||||
}
|
|
||||||
return "uint32";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub typeHasBody($)
|
|
||||||
{
|
|
||||||
sub typeHasBody($);
|
|
||||||
my ($e) = @_;
|
|
||||||
|
|
||||||
if ($e->{TYPE} eq "TYPEDEF") {
|
|
||||||
return 0 unless(defined($e->{DATA}));
|
|
||||||
return typeHasBody($e->{DATA});
|
|
||||||
}
|
|
||||||
|
|
||||||
return defined($e->{ELEMENTS});
|
|
||||||
}
|
|
||||||
|
|
||||||
sub mapType($$)
|
|
||||||
{
|
|
||||||
sub mapType($$);
|
|
||||||
my ($t, $n) = @_;
|
|
||||||
|
|
||||||
return mapType($t->{DATA}, $n) if ($t->{TYPE} eq "TYPEDEF");
|
|
||||||
return mapScalarType($n) if ($t->{TYPE} eq "SCALAR");
|
|
||||||
return "enum $n" if ($t->{TYPE} eq "ENUM");
|
|
||||||
return "struct $n" if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "INTERFACE");
|
|
||||||
return "union $n" if ($t->{TYPE} eq "UNION");
|
|
||||||
return mapScalarType(bitmap_type_fn($t)) if ($t->{TYPE} eq "BITMAP");
|
|
||||||
return "struct $n" if ($t->{TYPE} eq "PIPE");
|
|
||||||
die("Unknown type $t->{TYPE}");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub mapTypeName($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
return "void" unless defined($t);
|
|
||||||
my $dt;
|
|
||||||
$t = expandAlias($t);
|
|
||||||
|
|
||||||
if ($dt = getType($t)) {
|
|
||||||
return mapType($dt, $dt->{NAME});
|
|
||||||
} elsif (ref($t) eq "HASH" and defined($t->{NAME})) {
|
|
||||||
return mapType($t, $t->{NAME});
|
|
||||||
} else {
|
|
||||||
# Best guess
|
|
||||||
return "struct $t";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sub LoadIdl($;$)
|
|
||||||
{
|
|
||||||
my $idl = shift;
|
|
||||||
my $basename = shift;
|
|
||||||
|
|
||||||
foreach my $x (@{$idl}) {
|
|
||||||
next if $x->{TYPE} ne "INTERFACE";
|
|
||||||
|
|
||||||
# DCOM interfaces can be types as well
|
|
||||||
addType({
|
|
||||||
NAME => $x->{NAME},
|
|
||||||
TYPE => "TYPEDEF",
|
|
||||||
DATA => $x,
|
|
||||||
BASEFILE => $basename,
|
|
||||||
}) if (has_property($x, "object"));
|
|
||||||
|
|
||||||
foreach my $y (@{$x->{DATA}}) {
|
|
||||||
if ($y->{TYPE} eq "TYPEDEF"
|
|
||||||
or $y->{TYPE} eq "UNION"
|
|
||||||
or $y->{TYPE} eq "STRUCT"
|
|
||||||
or $y->{TYPE} eq "ENUM"
|
|
||||||
or $y->{TYPE} eq "BITMAP"
|
|
||||||
or $y->{TYPE} eq "PIPE") {
|
|
||||||
$y->{BASEFILE} = $basename;
|
|
||||||
addType($y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub GenerateTypeLib()
|
|
||||||
{
|
|
||||||
return Parse::Pidl::Util::MyDumper(\%types);
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterScalars();
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,197 +0,0 @@
|
||||||
###################################################
|
|
||||||
# utility functions to support pidl
|
|
||||||
# Copyright tridge@samba.org 2000
|
|
||||||
# released under the GNU GPL
|
|
||||||
package Parse::Pidl::Util;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT = qw(has_property property_matches ParseExpr ParseExprExt is_constant make_str unmake_str print_uuid MyDumper genpad);
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Parse::Pidl::Expr;
|
|
||||||
use Parse::Pidl qw(error);
|
|
||||||
|
|
||||||
=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;
|
|
||||||
$Data::Dumper::Sortkeys = 1;
|
|
||||||
my $s = shift;
|
|
||||||
return Data::Dumper::Dumper($s);
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<has_property>
|
|
||||||
see if a pidl property list contains a given property
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub has_property($$)
|
|
||||||
{
|
|
||||||
my($e, $p) = @_;
|
|
||||||
|
|
||||||
return undef if (not defined($e->{PROPERTIES}));
|
|
||||||
|
|
||||||
return $e->{PROPERTIES}->{$p};
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<property_matches>
|
|
||||||
see if a pidl property matches a value
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub property_matches($$$)
|
|
||||||
{
|
|
||||||
my($e,$p,$v) = @_;
|
|
||||||
|
|
||||||
if (!defined has_property($e, $p)) {
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($e->{PROPERTIES}->{$p} =~ /$v/) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<is_constant>
|
|
||||||
return 1 if the string is a C constant
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub is_constant($)
|
|
||||||
{
|
|
||||||
my $s = shift;
|
|
||||||
return 1 if ($s =~ /^\d+$/);
|
|
||||||
return 1 if ($s =~ /^0x[0-9A-Fa-f]+$/);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<make_str>
|
|
||||||
return a "" quoted string, unless already quoted
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub make_str($)
|
|
||||||
{
|
|
||||||
my $str = shift;
|
|
||||||
if (substr($str, 0, 1) eq "\"") {
|
|
||||||
return $str;
|
|
||||||
}
|
|
||||||
return "\"$str\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<unmake_str>
|
|
||||||
unquote a "" quoted string
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub unmake_str($)
|
|
||||||
{
|
|
||||||
my $str = shift;
|
|
||||||
|
|
||||||
$str =~ s/^\"(.*)\"$/$1/;
|
|
||||||
|
|
||||||
return $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<print_uuid>
|
|
||||||
Print C representation of a UUID.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub print_uuid($)
|
|
||||||
{
|
|
||||||
my ($uuid) = @_;
|
|
||||||
$uuid =~ s/"//g;
|
|
||||||
my ($time_low,$time_mid,$time_hi,$clock_seq,$node) = split /-/, $uuid;
|
|
||||||
return undef if not defined($node);
|
|
||||||
|
|
||||||
my @clock_seq = $clock_seq =~ /(..)/g;
|
|
||||||
my @node = $node =~ /(..)/g;
|
|
||||||
|
|
||||||
return "{0x$time_low,0x$time_mid,0x$time_hi," .
|
|
||||||
"{".join(',', map {"0x$_"} @clock_seq)."}," .
|
|
||||||
"{".join(',', map {"0x$_"} @node)."}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<ParseExpr>
|
|
||||||
Interpret an IDL expression, substituting particular variables.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub ParseExpr($$$)
|
|
||||||
{
|
|
||||||
my($expr, $varlist, $e) = @_;
|
|
||||||
|
|
||||||
my $x = new Parse::Pidl::Expr();
|
|
||||||
|
|
||||||
return $x->Run($expr, sub { my $x = shift; error($e, $x); },
|
|
||||||
# Lookup fn
|
|
||||||
sub { my $x = shift;
|
|
||||||
return($varlist->{$x}) if (defined($varlist->{$x}));
|
|
||||||
return $x;
|
|
||||||
},
|
|
||||||
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) = @_;
|
|
||||||
|
|
||||||
my $x = new Parse::Pidl::Expr();
|
|
||||||
|
|
||||||
return $x->Run($expr, sub { my $x = shift; error($e, $x); },
|
|
||||||
# Lookup fn
|
|
||||||
sub { my $x = shift;
|
|
||||||
return($varlist->{$x}) if (defined($varlist->{$x}));
|
|
||||||
return $x;
|
|
||||||
},
|
|
||||||
$deref, $use);
|
|
||||||
}
|
|
||||||
|
|
||||||
=item B<genpad>
|
|
||||||
return an empty string consisting of tabs and spaces suitable for proper indent
|
|
||||||
of C-functions.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
sub genpad($)
|
|
||||||
{
|
|
||||||
my ($s) = @_;
|
|
||||||
my $nt = int((length($s)+1)/8);
|
|
||||||
my $lt = ($nt*8)-1;
|
|
||||||
my $ns = (length($s)-$lt);
|
|
||||||
return "\t"x($nt)." "x($ns);
|
|
||||||
}
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,509 +0,0 @@
|
||||||
###################################################
|
|
||||||
# parse an Wireshark conformance file
|
|
||||||
# Copyright jelmer@samba.org 2005
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
Parse::Pidl::Wireshark::Conformance - Conformance file parser for Wireshark
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
This module supports parsing Wireshark conformance files (*.cnf).
|
|
||||||
|
|
||||||
=head1 FILE FORMAT
|
|
||||||
|
|
||||||
Pidl needs additional data for Wireshark output. This data is read from
|
|
||||||
so-called conformance files. This section describes the format of these
|
|
||||||
files.
|
|
||||||
|
|
||||||
Conformance files are simple text files with a single command on each line.
|
|
||||||
Empty lines and lines starting with a '#' character are ignored.
|
|
||||||
Arguments to commands are separated by spaces.
|
|
||||||
|
|
||||||
The following commands are currently supported:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item I<TYPE> name dissector ft_type base_type mask valsstring alignment
|
|
||||||
|
|
||||||
Register new data type with specified name, what dissector function to call
|
|
||||||
and what properties to give header fields for elements of this type.
|
|
||||||
|
|
||||||
=item I<NOEMIT> type
|
|
||||||
|
|
||||||
Suppress emitting a dissect_type function for the specified type
|
|
||||||
|
|
||||||
=item I<PARAM_VALUE> type param
|
|
||||||
|
|
||||||
Set parameter to specify to dissector function for given type.
|
|
||||||
|
|
||||||
=item I<HF_FIELD> hf title filter ft_type base_type valsstring mask description
|
|
||||||
|
|
||||||
Generate a custom header field with specified properties.
|
|
||||||
|
|
||||||
=item I<HF_RENAME> old_hf_name new_hf_name
|
|
||||||
|
|
||||||
Force the use of new_hf_name when the parser generator was going to
|
|
||||||
use old_hf_name.
|
|
||||||
|
|
||||||
This can be used in conjunction with HF_FIELD in order to make more than
|
|
||||||
one element use the same filter name.
|
|
||||||
|
|
||||||
=item I<ETT_FIELD> ett
|
|
||||||
|
|
||||||
Register a custom ett field
|
|
||||||
|
|
||||||
=item I<STRIP_PREFIX> prefix
|
|
||||||
|
|
||||||
Remove the specified prefix from all function names (if present).
|
|
||||||
|
|
||||||
=item I<PROTOCOL> longname shortname filtername
|
|
||||||
|
|
||||||
Change the short-, long- and filter-name for the current interface in
|
|
||||||
Wireshark.
|
|
||||||
|
|
||||||
=item I<FIELD_DESCRIPTION> field desc
|
|
||||||
|
|
||||||
Change description for the specified header field. `field' is the hf name of the field.
|
|
||||||
|
|
||||||
=item I<IMPORT> dissector code...
|
|
||||||
|
|
||||||
Code to insert when generating the specified dissector. @HF@ and
|
|
||||||
@PARAM@ will be substituted.
|
|
||||||
|
|
||||||
=item I<INCLUDE> filename
|
|
||||||
|
|
||||||
Include conformance data from the specified filename in the dissector.
|
|
||||||
|
|
||||||
=item I<TFS> hf_name "true string" "false string"
|
|
||||||
|
|
||||||
Override the text shown when a bitmap boolean value is enabled or disabled.
|
|
||||||
|
|
||||||
=item I<MANUAL> fn_name
|
|
||||||
|
|
||||||
Force pidl to not generate a particular function but allow the user
|
|
||||||
to write a function manually. This can be used to remove the function
|
|
||||||
for only one level for a particular element rather than all the functions and
|
|
||||||
ett/hf variables for a particular element as the NOEMIT command does.
|
|
||||||
|
|
||||||
=item I<CODE START>/I<CODE END>
|
|
||||||
Begin and end a section of code to be put directly into the generated
|
|
||||||
source file for the dissector.
|
|
||||||
|
|
||||||
=item I<HEADER START>/I<HEADER END>
|
|
||||||
Begin and end a section of code to be put directly into the generated
|
|
||||||
header file for the dissector.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 EXAMPLE
|
|
||||||
|
|
||||||
INFO_KEY OpenKey.Ke
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
package Parse::Pidl::Wireshark::Conformance;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
use vars qw($VERSION);
|
|
||||||
$VERSION = '0.01';
|
|
||||||
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT_OK = qw(ReadConformance ReadConformanceFH valid_ft_type valid_base_type);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Parse::Pidl qw(fatal warning error);
|
|
||||||
use Parse::Pidl::Util qw(has_property);
|
|
||||||
use Parse::Pidl::Typelist qw(addType);
|
|
||||||
|
|
||||||
sub handle_type($$$$$$$$$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$name,$dissectorname,$ft_type,$base_type,$mask,$valsstring,$alignment) = @_;
|
|
||||||
|
|
||||||
unless(defined($alignment)) {
|
|
||||||
error($pos, "incomplete TYPE command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unless ($dissectorname =~ /.*dissect_.*/) {
|
|
||||||
warning($pos, "dissector name does not contain `dissect'");
|
|
||||||
}
|
|
||||||
|
|
||||||
unless(valid_ft_type($ft_type)) {
|
|
||||||
warning($pos, "invalid FT_TYPE `$ft_type'");
|
|
||||||
}
|
|
||||||
|
|
||||||
unless (valid_base_type($base_type)) {
|
|
||||||
warning($pos, "invalid BASE_TYPE `$base_type'");
|
|
||||||
}
|
|
||||||
|
|
||||||
$dissectorname =~ s/^\"(.*)\"$/$1/g;
|
|
||||||
|
|
||||||
if (not ($dissectorname =~ /;$/)) {
|
|
||||||
warning($pos, "missing semicolon");
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{types}->{$name} = {
|
|
||||||
NAME => $name,
|
|
||||||
POS => $pos,
|
|
||||||
USED => 0,
|
|
||||||
DISSECTOR_NAME => $dissectorname,
|
|
||||||
FT_TYPE => $ft_type,
|
|
||||||
BASE_TYPE => $base_type,
|
|
||||||
MASK => $mask,
|
|
||||||
VALSSTRING => $valsstring,
|
|
||||||
ALIGNMENT => $alignment
|
|
||||||
};
|
|
||||||
|
|
||||||
addType({
|
|
||||||
NAME => $name,
|
|
||||||
TYPE => "CONFORMANCE",
|
|
||||||
BASEFILE => "conformance file",
|
|
||||||
DATA => {
|
|
||||||
NAME => $name,
|
|
||||||
TYPE => "CONFORMANCE",
|
|
||||||
ALIGN => $alignment
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_tfs($$$$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$hf,$trues,$falses) = @_;
|
|
||||||
|
|
||||||
unless(defined($falses)) {
|
|
||||||
error($pos, "incomplete TFS command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{tfs}->{$hf} = {
|
|
||||||
TRUE_STRING => $trues,
|
|
||||||
FALSE_STRING => $falses
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_hf_rename($$$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$old,$new) = @_;
|
|
||||||
|
|
||||||
unless(defined($new)) {
|
|
||||||
warning($pos, "incomplete HF_RENAME command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{hf_renames}->{$old} = {
|
|
||||||
OLDNAME => $old,
|
|
||||||
NEWNAME => $new,
|
|
||||||
POS => $pos,
|
|
||||||
USED => 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_param_value($$$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$dissector_name,$value) = @_;
|
|
||||||
|
|
||||||
unless(defined($value)) {
|
|
||||||
error($pos, "incomplete PARAM_VALUE command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{dissectorparams}->{$dissector_name} = {
|
|
||||||
DISSECTOR => $dissector_name,
|
|
||||||
PARAM => $value,
|
|
||||||
POS => $pos,
|
|
||||||
USED => 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub valid_base_type($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
return 0 unless($t =~ /^BASE_.*/);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub valid_ft_type($)
|
|
||||||
{
|
|
||||||
my $t = shift;
|
|
||||||
return 0 unless($t =~ /^FT_.*/);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_hf_field($$$$$$$$$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$index,$name,$filter,$ft_type,$base_type,$valsstring,$mask,$blurb) = @_;
|
|
||||||
|
|
||||||
unless(defined($blurb)) {
|
|
||||||
error($pos, "incomplete HF_FIELD command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unless(valid_ft_type($ft_type)) {
|
|
||||||
warning($pos, "invalid FT_TYPE `$ft_type'");
|
|
||||||
}
|
|
||||||
|
|
||||||
unless(valid_base_type($base_type)) {
|
|
||||||
warning($pos, "invalid BASE_TYPE `$base_type'");
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{header_fields}->{$index} = {
|
|
||||||
INDEX => $index,
|
|
||||||
POS => $pos,
|
|
||||||
USED => 0,
|
|
||||||
NAME => $name,
|
|
||||||
FILTER => $filter,
|
|
||||||
FT_TYPE => $ft_type,
|
|
||||||
BASE_TYPE => $base_type,
|
|
||||||
VALSSTRING => $valsstring,
|
|
||||||
MASK => $mask,
|
|
||||||
BLURB => $blurb
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_strip_prefix($$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$x) = @_;
|
|
||||||
|
|
||||||
push (@{$data->{strip_prefixes}}, $x);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_noemit($$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$type) = @_;
|
|
||||||
|
|
||||||
if (defined($type)) {
|
|
||||||
$data->{noemit}->{$type} = 1;
|
|
||||||
} else {
|
|
||||||
$data->{noemit_dissector} = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_manual($$$)
|
|
||||||
{
|
|
||||||
my ($pos,$data,$fn) = @_;
|
|
||||||
|
|
||||||
unless(defined($fn)) {
|
|
||||||
warning($pos, "incomplete MANUAL command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{manual}->{$fn} = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_protocol($$$$$$)
|
|
||||||
{
|
|
||||||
my ($pos, $data, $name, $longname, $shortname, $filtername) = @_;
|
|
||||||
|
|
||||||
$data->{protocols}->{$name} = {
|
|
||||||
LONGNAME => $longname,
|
|
||||||
SHORTNAME => $shortname,
|
|
||||||
FILTERNAME => $filtername
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
USED => 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_import
|
|
||||||
{
|
|
||||||
my $pos = shift @_;
|
|
||||||
my $data = shift @_;
|
|
||||||
my $dissectorname = shift @_;
|
|
||||||
|
|
||||||
unless(defined($dissectorname)) {
|
|
||||||
error($pos, "no dissectorname specified");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->{imports}->{$dissectorname} = {
|
|
||||||
NAME => $dissectorname,
|
|
||||||
DATA => join(' ', @_),
|
|
||||||
USED => 0,
|
|
||||||
POS => $pos
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_ett_field
|
|
||||||
{
|
|
||||||
my $pos = shift @_;
|
|
||||||
my $data = shift @_;
|
|
||||||
my $ett = shift @_;
|
|
||||||
|
|
||||||
unless(defined($ett)) {
|
|
||||||
error($pos, "incomplete ETT_FIELD command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
push (@{$data->{ett}}, $ett);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub handle_include
|
|
||||||
{
|
|
||||||
my $pos = shift @_;
|
|
||||||
my $data = shift @_;
|
|
||||||
my $fn = shift @_;
|
|
||||||
|
|
||||||
unless(defined($fn)) {
|
|
||||||
error($pos, "incomplete INCLUDE command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadConformance($fn, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
my %field_handlers = (
|
|
||||||
TYPE => \&handle_type,
|
|
||||||
NOEMIT => \&handle_noemit,
|
|
||||||
MANUAL => \&handle_manual,
|
|
||||||
PARAM_VALUE => \&handle_param_value,
|
|
||||||
HF_FIELD => \&handle_hf_field,
|
|
||||||
HF_RENAME => \&handle_hf_rename,
|
|
||||||
ETT_FIELD => \&handle_ett_field,
|
|
||||||
TFS => \&handle_tfs,
|
|
||||||
STRIP_PREFIX => \&handle_strip_prefix,
|
|
||||||
PROTOCOL => \&handle_protocol,
|
|
||||||
FIELD_DESCRIPTION => \&handle_fielddescription,
|
|
||||||
IMPORT => \&handle_import,
|
|
||||||
INCLUDE => \&handle_include
|
|
||||||
);
|
|
||||||
|
|
||||||
sub ReadConformance($$)
|
|
||||||
{
|
|
||||||
my ($f,$data) = @_;
|
|
||||||
my $ret;
|
|
||||||
|
|
||||||
open(IN,"<$f") or return undef;
|
|
||||||
|
|
||||||
$ret = ReadConformanceFH(*IN, $data, $f);
|
|
||||||
|
|
||||||
close(IN);
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub ReadConformanceFH($$$)
|
|
||||||
{
|
|
||||||
my ($fh,$data,$f) = @_;
|
|
||||||
|
|
||||||
my $incodeblock = 0;
|
|
||||||
my $inheaderblock = 0;
|
|
||||||
|
|
||||||
my $ln = 0;
|
|
||||||
|
|
||||||
foreach (<$fh>) {
|
|
||||||
$ln++;
|
|
||||||
next if (/^#.*$/);
|
|
||||||
next if (/^$/);
|
|
||||||
|
|
||||||
s/[\r\n]//g;
|
|
||||||
|
|
||||||
if ($_ eq "CODE START") {
|
|
||||||
if ($incodeblock) {
|
|
||||||
warning({ FILE => $f, LINE => $ln },
|
|
||||||
"CODE START inside CODE section");
|
|
||||||
}
|
|
||||||
if ($inheaderblock) {
|
|
||||||
error({ FILE => $f, LINE => $ln },
|
|
||||||
"CODE START inside HEADER section");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
$incodeblock = 1;
|
|
||||||
next;
|
|
||||||
} elsif ($_ eq "CODE END") {
|
|
||||||
if (!$incodeblock) {
|
|
||||||
warning({ FILE => $f, LINE => $ln },
|
|
||||||
"CODE END outside CODE section");
|
|
||||||
}
|
|
||||||
if ($inheaderblock) {
|
|
||||||
error({ FILE => $f, LINE => $ln },
|
|
||||||
"CODE END inside HEADER section");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
$incodeblock = 0;
|
|
||||||
next;
|
|
||||||
} elsif ($incodeblock) {
|
|
||||||
if (exists $data->{override}) {
|
|
||||||
$data->{override}.="$_\n";
|
|
||||||
} else {
|
|
||||||
$data->{override} = "$_\n";
|
|
||||||
}
|
|
||||||
next;
|
|
||||||
} elsif ($_ eq "HEADER START") {
|
|
||||||
if ($inheaderblock) {
|
|
||||||
warning({ FILE => $f, LINE => $ln },
|
|
||||||
"HEADER START inside HEADER section");
|
|
||||||
}
|
|
||||||
if ($incodeblock) {
|
|
||||||
error({ FILE => $f, LINE => $ln },
|
|
||||||
"HEADER START inside CODE section");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
$inheaderblock = 1;
|
|
||||||
next;
|
|
||||||
} elsif ($_ eq "HEADER END") {
|
|
||||||
if (!$inheaderblock) {
|
|
||||||
warning({ FILE => $f, LINE => $ln },
|
|
||||||
"HEADER END outside HEADER section");
|
|
||||||
}
|
|
||||||
if ($incodeblock) {
|
|
||||||
error({ FILE => $f, LINE => $ln },
|
|
||||||
"CODE END inside HEADER section");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
$inheaderblock = 0;
|
|
||||||
next;
|
|
||||||
} elsif ($inheaderblock) {
|
|
||||||
if (exists $data->{header}) {
|
|
||||||
$data->{header}.="$_\n";
|
|
||||||
} else {
|
|
||||||
$data->{header} = "$_\n";
|
|
||||||
}
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
my @fields = /([^ "]+|"[^"]+")/g;
|
|
||||||
|
|
||||||
my $cmd = $fields[0];
|
|
||||||
|
|
||||||
shift @fields;
|
|
||||||
|
|
||||||
my $pos = { FILE => $f, LINE => $ln };
|
|
||||||
|
|
||||||
next unless(defined($cmd));
|
|
||||||
|
|
||||||
if (not defined($field_handlers{$cmd})) {
|
|
||||||
warning($pos, "Unknown command `$cmd'");
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
$field_handlers{$cmd}($pos, $data, @fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($incodeblock) {
|
|
||||||
warning({ FILE => $f, LINE => $ln },
|
|
||||||
"Expecting CODE END");
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,471 +0,0 @@
|
||||||
#
|
|
||||||
# Module Parse::Yapp::Driver
|
|
||||||
#
|
|
||||||
# This module is part of the Parse::Yapp package available on your
|
|
||||||
# nearest CPAN
|
|
||||||
#
|
|
||||||
# Any use of this module in a standalone parser make the included
|
|
||||||
# text under the same copyright as the Parse::Yapp module itself.
|
|
||||||
#
|
|
||||||
# This notice should remain unchanged.
|
|
||||||
#
|
|
||||||
# (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved.
|
|
||||||
# (see the pod text in Parse::Yapp module for use and distribution rights)
|
|
||||||
#
|
|
||||||
|
|
||||||
package Parse::Yapp::Driver;
|
|
||||||
|
|
||||||
require 5.004;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use vars qw ( $VERSION $COMPATIBLE $FILENAME );
|
|
||||||
|
|
||||||
$VERSION = '1.05';
|
|
||||||
$COMPATIBLE = '0.07';
|
|
||||||
$FILENAME=__FILE__;
|
|
||||||
|
|
||||||
use Carp;
|
|
||||||
|
|
||||||
#Known parameters, all starting with YY (leading YY will be discarded)
|
|
||||||
my(%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '',
|
|
||||||
YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => '');
|
|
||||||
#Mandatory parameters
|
|
||||||
my(@params)=('LEX','RULES','STATES');
|
|
||||||
|
|
||||||
sub new {
|
|
||||||
my($class)=shift;
|
|
||||||
my($errst,$nberr,$token,$value,$check,$dotpos);
|
|
||||||
my($self)={ ERROR => \&_Error,
|
|
||||||
ERRST => \$errst,
|
|
||||||
NBERR => \$nberr,
|
|
||||||
TOKEN => \$token,
|
|
||||||
VALUE => \$value,
|
|
||||||
DOTPOS => \$dotpos,
|
|
||||||
STACK => [],
|
|
||||||
DEBUG => 0,
|
|
||||||
CHECK => \$check };
|
|
||||||
|
|
||||||
_CheckParams( [], \%params, \@_, $self );
|
|
||||||
|
|
||||||
exists($$self{VERSION})
|
|
||||||
and $$self{VERSION} < $COMPATIBLE
|
|
||||||
and croak "Yapp driver version $VERSION ".
|
|
||||||
"incompatible with version $$self{VERSION}:\n".
|
|
||||||
"Please recompile parser module.";
|
|
||||||
|
|
||||||
ref($class)
|
|
||||||
and $class=ref($class);
|
|
||||||
|
|
||||||
bless($self,$class);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYParse {
|
|
||||||
my($self)=shift;
|
|
||||||
my($retval);
|
|
||||||
|
|
||||||
_CheckParams( \@params, \%params, \@_, $self );
|
|
||||||
|
|
||||||
if($$self{DEBUG}) {
|
|
||||||
_DBLoad();
|
|
||||||
$retval = eval '$self->_DBParse()';#Do not create stab entry on compile
|
|
||||||
$@ and die $@;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$retval = $self->_Parse();
|
|
||||||
}
|
|
||||||
$retval
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYData {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
exists($$self{USER})
|
|
||||||
or $$self{USER}={};
|
|
||||||
|
|
||||||
$$self{USER};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYErrok {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{ERRST}}=0;
|
|
||||||
undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYNberr {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{NBERR}};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYRecovering {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{ERRST}} != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYAbort {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{CHECK}}='ABORT';
|
|
||||||
undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYAccept {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{CHECK}}='ACCEPT';
|
|
||||||
undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYError {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
${$$self{CHECK}}='ERROR';
|
|
||||||
undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYSemval {
|
|
||||||
my($self)=shift;
|
|
||||||
my($index)= $_[0] - ${$$self{DOTPOS}} - 1;
|
|
||||||
|
|
||||||
$index < 0
|
|
||||||
and -$index <= @{$$self{STACK}}
|
|
||||||
and return $$self{STACK}[$index][1];
|
|
||||||
|
|
||||||
undef; #Invalid index
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYCurtok {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
@_
|
|
||||||
and ${$$self{TOKEN}}=$_[0];
|
|
||||||
${$$self{TOKEN}};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYCurval {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
@_
|
|
||||||
and ${$$self{VALUE}}=$_[0];
|
|
||||||
${$$self{VALUE}};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYExpect {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
keys %{$self->{STATES}[$self->{STACK}[-1][0]]{ACTIONS}}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub YYLexer {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
$$self{LEX};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Private stuff #
|
|
||||||
#################
|
|
||||||
|
|
||||||
|
|
||||||
sub _CheckParams {
|
|
||||||
my($mandatory,$checklist,$inarray,$outhash)=@_;
|
|
||||||
my($prm,$value);
|
|
||||||
my($prmlst)={};
|
|
||||||
|
|
||||||
while(($prm,$value)=splice(@$inarray,0,2)) {
|
|
||||||
$prm=uc($prm);
|
|
||||||
exists($$checklist{$prm})
|
|
||||||
or croak("Unknow parameter '$prm'");
|
|
||||||
ref($value) eq $$checklist{$prm}
|
|
||||||
or croak("Invalid value for parameter '$prm'");
|
|
||||||
$prm=unpack('@2A*',$prm);
|
|
||||||
$$outhash{$prm}=$value;
|
|
||||||
}
|
|
||||||
for (@$mandatory) {
|
|
||||||
exists($$outhash{$_})
|
|
||||||
or croak("Missing mandatory parameter '".lc($_)."'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _Error {
|
|
||||||
print "Parse error.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _DBLoad {
|
|
||||||
{
|
|
||||||
no strict 'refs';
|
|
||||||
|
|
||||||
exists(${__PACKAGE__.'::'}{_DBParse})#Already loaded ?
|
|
||||||
and return;
|
|
||||||
}
|
|
||||||
my($fname)=__FILE__;
|
|
||||||
my(@drv);
|
|
||||||
open(DRV,"<$fname") or die "Report this as a BUG: Cannot open $fname";
|
|
||||||
while(<DRV>) {
|
|
||||||
/^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/
|
|
||||||
and do {
|
|
||||||
s/^#DBG>//;
|
|
||||||
push(@drv,$_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(DRV);
|
|
||||||
|
|
||||||
$drv[0]=~s/_P/_DBP/;
|
|
||||||
eval join('',@drv);
|
|
||||||
}
|
|
||||||
|
|
||||||
#Note that for loading debugging version of the driver,
|
|
||||||
#this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive.
|
|
||||||
#So, DO NOT remove comment at end of sub !!!
|
|
||||||
sub _Parse {
|
|
||||||
my($self)=shift;
|
|
||||||
|
|
||||||
my($rules,$states,$lex,$error)
|
|
||||||
= @$self{ 'RULES', 'STATES', 'LEX', 'ERROR' };
|
|
||||||
my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos)
|
|
||||||
= @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' };
|
|
||||||
|
|
||||||
#DBG> my($debug)=$$self{DEBUG};
|
|
||||||
#DBG> my($dbgerror)=0;
|
|
||||||
|
|
||||||
#DBG> my($ShowCurToken) = sub {
|
|
||||||
#DBG> my($tok)='>';
|
|
||||||
#DBG> for (split('',$$token)) {
|
|
||||||
#DBG> $tok.= (ord($_) < 32 or ord($_) > 126)
|
|
||||||
#DBG> ? sprintf('<%02X>',ord($_))
|
|
||||||
#DBG> : $_;
|
|
||||||
#DBG> }
|
|
||||||
#DBG> $tok.='<';
|
|
||||||
#DBG> };
|
|
||||||
|
|
||||||
$$errstatus=0;
|
|
||||||
$$nberror=0;
|
|
||||||
($$token,$$value)=(undef,undef);
|
|
||||||
@$stack=( [ 0, undef ] );
|
|
||||||
$$check='';
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
my($actions,$act,$stateno);
|
|
||||||
|
|
||||||
$stateno=$$stack[-1][0];
|
|
||||||
$actions=$$states[$stateno];
|
|
||||||
|
|
||||||
#DBG> print STDERR ('-' x 40),"\n";
|
|
||||||
#DBG> $debug & 0x2
|
|
||||||
#DBG> and print STDERR "In state $stateno:\n";
|
|
||||||
#DBG> $debug & 0x08
|
|
||||||
#DBG> and print STDERR "Stack:[".
|
|
||||||
#DBG> join(',',map { $$_[0] } @$stack).
|
|
||||||
#DBG> "]\n";
|
|
||||||
|
|
||||||
|
|
||||||
if (exists($$actions{ACTIONS})) {
|
|
||||||
|
|
||||||
defined($$token)
|
|
||||||
or do {
|
|
||||||
($$token,$$value)=&$lex($self);
|
|
||||||
#DBG> $debug & 0x01
|
|
||||||
#DBG> and print STDERR "Need token. Got ".&$ShowCurToken."\n";
|
|
||||||
};
|
|
||||||
|
|
||||||
$act= exists($$actions{ACTIONS}{$$token})
|
|
||||||
? $$actions{ACTIONS}{$$token}
|
|
||||||
: exists($$actions{DEFAULT})
|
|
||||||
? $$actions{DEFAULT}
|
|
||||||
: undef;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$act=$$actions{DEFAULT};
|
|
||||||
#DBG> $debug & 0x01
|
|
||||||
#DBG> and print STDERR "Don't need token.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
defined($act)
|
|
||||||
and do {
|
|
||||||
|
|
||||||
$act > 0
|
|
||||||
and do { #shift
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR "Shift and go to state $act.\n";
|
|
||||||
|
|
||||||
$$errstatus
|
|
||||||
and do {
|
|
||||||
--$$errstatus;
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and $dbgerror
|
|
||||||
#DBG> and $$errstatus == 0
|
|
||||||
#DBG> and do {
|
|
||||||
#DBG> print STDERR "**End of Error recovery.\n";
|
|
||||||
#DBG> $dbgerror=0;
|
|
||||||
#DBG> };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
push(@$stack,[ $act, $$value ]);
|
|
||||||
|
|
||||||
$$token ne '' #Don't eat the eof
|
|
||||||
and $$token=$$value=undef;
|
|
||||||
next;
|
|
||||||
};
|
|
||||||
|
|
||||||
#reduce
|
|
||||||
my($lhs,$len,$code,@sempar,$semval);
|
|
||||||
($lhs,$len,$code)=@{$$rules[-$act]};
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and $act
|
|
||||||
#DBG> and print STDERR "Reduce using rule ".-$act." ($lhs,$len): ";
|
|
||||||
|
|
||||||
$act
|
|
||||||
or $self->YYAccept();
|
|
||||||
|
|
||||||
$$dotpos=$len;
|
|
||||||
|
|
||||||
unpack('A1',$lhs) eq '@' #In line rule
|
|
||||||
and do {
|
|
||||||
$lhs =~ /^\@[0-9]+\-([0-9]+)$/
|
|
||||||
or die "In line rule name '$lhs' ill formed: ".
|
|
||||||
"report it as a BUG.\n";
|
|
||||||
$$dotpos = $1;
|
|
||||||
};
|
|
||||||
|
|
||||||
@sempar = $$dotpos
|
|
||||||
? map { $$_[1] } @$stack[ -$$dotpos .. -1 ]
|
|
||||||
: ();
|
|
||||||
|
|
||||||
$semval = $code ? &$code( $self, @sempar )
|
|
||||||
: @sempar ? $sempar[0] : undef;
|
|
||||||
|
|
||||||
splice(@$stack,-$len,$len);
|
|
||||||
|
|
||||||
$$check eq 'ACCEPT'
|
|
||||||
and do {
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR "Accept.\n";
|
|
||||||
|
|
||||||
return($semval);
|
|
||||||
};
|
|
||||||
|
|
||||||
$$check eq 'ABORT'
|
|
||||||
and do {
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR "Abort.\n";
|
|
||||||
|
|
||||||
return(undef);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR "Back to state $$stack[-1][0], then ";
|
|
||||||
|
|
||||||
$$check eq 'ERROR'
|
|
||||||
or do {
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR
|
|
||||||
#DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n";
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and $dbgerror
|
|
||||||
#DBG> and $$errstatus == 0
|
|
||||||
#DBG> and do {
|
|
||||||
#DBG> print STDERR "**End of Error recovery.\n";
|
|
||||||
#DBG> $dbgerror=0;
|
|
||||||
#DBG> };
|
|
||||||
|
|
||||||
push(@$stack,
|
|
||||||
[ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval ]);
|
|
||||||
$$check='';
|
|
||||||
next;
|
|
||||||
};
|
|
||||||
|
|
||||||
#DBG> $debug & 0x04
|
|
||||||
#DBG> and print STDERR "Forced Error recovery.\n";
|
|
||||||
|
|
||||||
$$check='';
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#Error
|
|
||||||
$$errstatus
|
|
||||||
or do {
|
|
||||||
|
|
||||||
$$errstatus = 1;
|
|
||||||
&$error($self);
|
|
||||||
$$errstatus # if 0, then YYErrok has been called
|
|
||||||
or next; # so continue parsing
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and do {
|
|
||||||
#DBG> print STDERR "**Entering Error recovery.\n";
|
|
||||||
#DBG> ++$dbgerror;
|
|
||||||
#DBG> };
|
|
||||||
|
|
||||||
++$$nberror;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
$$errstatus == 3 #The next token is not valid: discard it
|
|
||||||
and do {
|
|
||||||
$$token eq '' # End of input: no hope
|
|
||||||
and do {
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and print STDERR "**At eof: aborting.\n";
|
|
||||||
return(undef);
|
|
||||||
};
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and print STDERR "**Dicard invalid token ".&$ShowCurToken.".\n";
|
|
||||||
|
|
||||||
$$token=$$value=undef;
|
|
||||||
};
|
|
||||||
|
|
||||||
$$errstatus=3;
|
|
||||||
|
|
||||||
while( @$stack
|
|
||||||
and ( not exists($$states[$$stack[-1][0]]{ACTIONS})
|
|
||||||
or not exists($$states[$$stack[-1][0]]{ACTIONS}{error})
|
|
||||||
or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) {
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and print STDERR "**Pop state $$stack[-1][0].\n";
|
|
||||||
|
|
||||||
pop(@$stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
@$stack
|
|
||||||
or do {
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and print STDERR "**No state left on stack: aborting.\n";
|
|
||||||
|
|
||||||
return(undef);
|
|
||||||
};
|
|
||||||
|
|
||||||
#shift the error token
|
|
||||||
|
|
||||||
#DBG> $debug & 0x10
|
|
||||||
#DBG> and print STDERR "**Shift \$error token and go to state ".
|
|
||||||
#DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}.
|
|
||||||
#DBG> ".\n";
|
|
||||||
|
|
||||||
push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef ]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#never reached
|
|
||||||
croak("Error in driver logic. Please, report it as a BUG");
|
|
||||||
|
|
||||||
}#_Parse
|
|
||||||
#DO NOT remove comment
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
# install the pidl modules
|
|
||||||
bld.INSTALL_FILES(bld.env.PERL_LIB_INSTALL_DIR,
|
|
||||||
'''
|
|
||||||
Parse/Pidl.pm
|
|
||||||
Parse/Pidl/Samba4.pm
|
|
||||||
Parse/Pidl/CUtil.pm
|
|
||||||
Parse/Pidl/Expr.pm
|
|
||||||
Parse/Pidl/Wireshark/Conformance.pm
|
|
||||||
Parse/Pidl/Wireshark/NDR.pm
|
|
||||||
Parse/Pidl/ODL.pm
|
|
||||||
Parse/Pidl/Dump.pm
|
|
||||||
Parse/Pidl/Util.pm
|
|
||||||
Parse/Pidl/Samba4/Header.pm
|
|
||||||
Parse/Pidl/Samba4/COM/Header.pm
|
|
||||||
Parse/Pidl/Samba4/COM/Proxy.pm
|
|
||||||
Parse/Pidl/Samba4/COM/Stub.pm
|
|
||||||
Parse/Pidl/Samba4/TDR.pm
|
|
||||||
Parse/Pidl/Samba4/NDR/Server.pm
|
|
||||||
Parse/Pidl/Samba4/NDR/Client.pm
|
|
||||||
Parse/Pidl/Samba4/NDR/Parser.pm
|
|
||||||
Parse/Pidl/Samba4/Python.pm
|
|
||||||
Parse/Pidl/Samba4/Template.pm
|
|
||||||
Parse/Pidl/IDL.pm
|
|
||||||
Parse/Pidl/Typelist.pm
|
|
||||||
Parse/Pidl/Samba3/ClientNDR.pm
|
|
||||||
Parse/Pidl/Samba3/ServerNDR.pm
|
|
||||||
Parse/Pidl/Compat.pm
|
|
||||||
Parse/Pidl/NDR.pm
|
|
||||||
''',
|
|
||||||
flat=False)
|
|
||||||
|
|
||||||
if not bld.CONFIG_SET('USING_SYSTEM_PARSE_YAPP_DRIVER'):
|
|
||||||
bld.INSTALL_FILES(bld.env.PERL_LIB_INSTALL_DIR,
|
|
||||||
'Parse/Yapp/Driver.pm',
|
|
||||||
flat=False)
|
|
804
bin/pidl/pidl
804
bin/pidl/pidl
|
@ -1,804 +0,0 @@
|
||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
###################################################
|
|
||||||
# package to parse IDL files and generate code for
|
|
||||||
# rpc functions in Samba
|
|
||||||
# Copyright tridge@samba.org 2000-2003
|
|
||||||
# Copyright jelmer@samba.org 2005-2007
|
|
||||||
# released under the GNU GPL
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
pidl - An IDL compiler written in Perl
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
pidl --help
|
|
||||||
|
|
||||||
pidl [--outputdir[=OUTNAME]] [--includedir DIR...] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--header[=OUTPUT]] [--python[=OUTPUT]] [--ndr-parser[=OUTPUT]] [--client] [--server] [--warn-compat] [--quiet] [--verbose] [--template] [--ws-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-parser[=OUTPUT]] [--samba3-ndr-client[=OUTPUT]] [--samba3-ndr-server[=OUTPUT]] [--typelib=[OUTPUT]] [<idlfile>.idl]...
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
pidl is an IDL compiler written in Perl that aims to be somewhat
|
|
||||||
compatible with the midl compiler. IDL is short for
|
|
||||||
"Interface Definition Language".
|
|
||||||
|
|
||||||
pidl can generate stubs for DCE/RPC server code, DCE/RPC
|
|
||||||
client code and Wireshark dissectors for DCE/RPC traffic.
|
|
||||||
|
|
||||||
IDL compilers like pidl take a description
|
|
||||||
of an interface as their input and use it to generate C
|
|
||||||
(though support for other languages may be added later) code that
|
|
||||||
can use these interfaces, pretty print data sent
|
|
||||||
using these interfaces, or even generate Wireshark
|
|
||||||
dissectors that can parse data sent over the
|
|
||||||
wire by these interfaces.
|
|
||||||
|
|
||||||
pidl takes IDL files in the same format as is used by midl,
|
|
||||||
converts it to a .pidl file (which contains pidl's internal representation of the interface) and can then generate whatever output you need.
|
|
||||||
.pidl files should be used for debugging purposes only. Write your
|
|
||||||
interface definitions in .idl format.
|
|
||||||
|
|
||||||
The goal of pidl is to implement a IDL compiler that can be used
|
|
||||||
while developing the RPC subsystem in Samba (for
|
|
||||||
both marshalling/unmarshalling and debugging purposes).
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item I<--help>
|
|
||||||
|
|
||||||
Show list of available options.
|
|
||||||
|
|
||||||
=item I<--version>
|
|
||||||
|
|
||||||
Show pidl version
|
|
||||||
|
|
||||||
=item I<--outputdir OUTNAME>
|
|
||||||
|
|
||||||
Write output files to the specified directory. Defaults to the current
|
|
||||||
directory.
|
|
||||||
|
|
||||||
=item I<--includedir DIR>
|
|
||||||
|
|
||||||
Add DIR to the search path used by the preprocessor. This option can be
|
|
||||||
specified multiple times.
|
|
||||||
|
|
||||||
=item I<--parse-idl-tree>
|
|
||||||
|
|
||||||
Read internal tree structure from input files rather
|
|
||||||
than assuming they contain IDL.
|
|
||||||
|
|
||||||
=item I<--dump-idl>
|
|
||||||
|
|
||||||
Generate a new IDL file. File will be named OUTNAME.idl.
|
|
||||||
|
|
||||||
=item I<--header>
|
|
||||||
|
|
||||||
Generate a C header file for the specified interface. Filename defaults to OUTNAME.h.
|
|
||||||
|
|
||||||
=item I<--ndr-parser>
|
|
||||||
|
|
||||||
Generate a C file and C header containing NDR parsers. The filename for
|
|
||||||
the parser defaults to ndr_OUTNAME.c. The header filename will be the
|
|
||||||
parser filename with the extension changed from .c to .h.
|
|
||||||
|
|
||||||
=item I<--tdr-parser>
|
|
||||||
|
|
||||||
Generate a C file and C header containing TDR parsers. The filename for
|
|
||||||
the parser defaults to tdr_OUTNAME.c. The header filename will be the
|
|
||||||
parser filename with the extension changed from .c to .h.
|
|
||||||
|
|
||||||
=item I<--typelib>
|
|
||||||
|
|
||||||
Write type information to the specified file.
|
|
||||||
|
|
||||||
=item I<--server>
|
|
||||||
|
|
||||||
Generate boilerplate for the RPC server that implements
|
|
||||||
the interface. Filename defaults to ndr_OUTNAME_s.c.
|
|
||||||
|
|
||||||
=item I<--template>
|
|
||||||
|
|
||||||
Generate stubs for a RPC server that implements the interface. Output will
|
|
||||||
be written to stdout.
|
|
||||||
|
|
||||||
=item I<--ws-parser>
|
|
||||||
|
|
||||||
Generate an Wireshark dissector (in C) and header file. The dissector filename
|
|
||||||
defaults to packet-dcerpc-OUTNAME.c while the header filename defaults to
|
|
||||||
packet-dcerpc-OUTNAME.h.
|
|
||||||
|
|
||||||
Pidl will read additional data from an Wireshark conformance file if present.
|
|
||||||
Such a file should have the same location as the IDL file but with the
|
|
||||||
extension I<cnf> rather than I<idl>. See L<Parse::Pidl::Wireshark::Conformance>
|
|
||||||
for details on the format of this file.
|
|
||||||
|
|
||||||
=item I<--diff>
|
|
||||||
|
|
||||||
Parse an IDL file, generate a new IDL file based on the internal data
|
|
||||||
structures and see if there are any differences with the original IDL file.
|
|
||||||
Useful for debugging pidl.
|
|
||||||
|
|
||||||
=item I<--dump-idl-tree>
|
|
||||||
|
|
||||||
Tell pidl to dump the internal tree representation of an IDL
|
|
||||||
file the to disk. Useful for debugging pidl.
|
|
||||||
|
|
||||||
=item I<--dump-ndr-tree>
|
|
||||||
|
|
||||||
Tell pidl to dump the internal NDR information tree it generated
|
|
||||||
from the IDL file to disk. Useful for debugging pidl.
|
|
||||||
|
|
||||||
=item I<--samba3-ndr-client>
|
|
||||||
|
|
||||||
Generate client calls for Samba3, to be placed in rpc_client/. Instead of
|
|
||||||
calling out to the code in Samba3's rpc_parse/, this will call out to
|
|
||||||
Samba4's NDR code instead.
|
|
||||||
|
|
||||||
=item I<--samba3-ndr-server>
|
|
||||||
|
|
||||||
Generate server calls for Samba3, to be placed in rpc_server/. Instead of
|
|
||||||
calling out to the code in Samba3's rpc_parse/, this will call out to
|
|
||||||
Samba4's NDR code instead.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 IDL SYNTAX
|
|
||||||
|
|
||||||
IDL files are always preprocessed using the C preprocessor.
|
|
||||||
|
|
||||||
Pretty much everything in an interface (the interface itself, functions,
|
|
||||||
parameters) can have attributes (or properties whatever name you give them).
|
|
||||||
Attributes always prepend the element they apply to and are surrounded
|
|
||||||
by square brackets ([]). Multiple attributes are separated by comma's;
|
|
||||||
arguments to attributes are specified between parentheses.
|
|
||||||
|
|
||||||
See the section COMPATIBILITY for the list of attributes that
|
|
||||||
pidl supports.
|
|
||||||
|
|
||||||
C-style comments can be used.
|
|
||||||
|
|
||||||
=head2 CONFORMANT ARRAYS
|
|
||||||
|
|
||||||
A conformant array is one with that ends in [*] or []. The strange
|
|
||||||
things about conformant arrays are that they can only appear as the last
|
|
||||||
element of a structure (unless there is a pointer to the conformant array,
|
|
||||||
of course) and the array size appears before the structure itself on the wire.
|
|
||||||
|
|
||||||
So, in this example:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long abc;
|
|
||||||
long count;
|
|
||||||
long foo;
|
|
||||||
[size_is(count)] long s[*];
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
it appears like this:
|
|
||||||
|
|
||||||
[size_is] [abc] [count] [foo] [s...]
|
|
||||||
|
|
||||||
the first [size_is] field is the allocation size of the array, and
|
|
||||||
occurs before the array elements and even before the structure
|
|
||||||
alignment.
|
|
||||||
|
|
||||||
Note that size_is() can refer to a constant, but that doesn't change
|
|
||||||
the wire representation. It does not make the array a fixed array.
|
|
||||||
|
|
||||||
midl.exe would write the above array as the following C header:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long abc;
|
|
||||||
long count;
|
|
||||||
long foo;
|
|
||||||
long s[1];
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
pidl takes a different approach, and writes it like this:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long abc;
|
|
||||||
long count;
|
|
||||||
long foo;
|
|
||||||
long *s;
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
=head2 VARYING ARRAYS
|
|
||||||
|
|
||||||
A varying array looks like this:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long abc;
|
|
||||||
long count;
|
|
||||||
long foo;
|
|
||||||
[size_is(count)] long *s;
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
This will look like this on the wire:
|
|
||||||
|
|
||||||
[abc] [count] [foo] [PTR_s] [count] [s...]
|
|
||||||
|
|
||||||
=head2 FIXED ARRAYS
|
|
||||||
|
|
||||||
A fixed array looks like this:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long s[10];
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
The NDR representation looks just like 10 separate long
|
|
||||||
declarations. The array size is not encoded on the wire.
|
|
||||||
|
|
||||||
pidl also supports "inline" arrays, which are not part of the IDL/NDR
|
|
||||||
standard. These are declared like this:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32 foo;
|
|
||||||
uint32 count;
|
|
||||||
uint32 bar;
|
|
||||||
long s[count];
|
|
||||||
} Struct1;
|
|
||||||
|
|
||||||
This appears like this:
|
|
||||||
|
|
||||||
[foo] [count] [bar] [s...]
|
|
||||||
|
|
||||||
Fixed arrays are an extension added to support some of the strange
|
|
||||||
embedded structures in security descriptors and spoolss.
|
|
||||||
|
|
||||||
This section is by no means complete. See the OpenGroup and MSDN
|
|
||||||
documentation for additional information.
|
|
||||||
|
|
||||||
=head1 COMPATIBILITY WITH MIDL
|
|
||||||
|
|
||||||
=head2 Missing features in pidl
|
|
||||||
|
|
||||||
The following MIDL features are not (yet) implemented in pidl
|
|
||||||
or are implemented with an incompatible interface:
|
|
||||||
|
|
||||||
=over
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Asynchronous communication
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Typelibs (.tlb files)
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Datagram support (ncadg_*)
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head2 Supported attributes and statements
|
|
||||||
|
|
||||||
in, out, ref, length_is, switch_is, size_is, uuid, case, default, string,
|
|
||||||
unique, ptr, pointer_default, v1_enum, object, helpstring, range, local,
|
|
||||||
call_as, endpoint, switch_type, progid, coclass, iid_is, represent_as,
|
|
||||||
transmit_as, import, include, cpp_quote.
|
|
||||||
|
|
||||||
=head2 PIDL Specific properties
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item public
|
|
||||||
|
|
||||||
The [public] property on a structure or union is a pidl extension that
|
|
||||||
forces the generated pull/push functions to be non-static. This allows
|
|
||||||
you to declare types that can be used between modules. If you don't
|
|
||||||
specify [public] then pull/push functions for other than top-level
|
|
||||||
functions are declared static.
|
|
||||||
|
|
||||||
=item noprint
|
|
||||||
|
|
||||||
The [noprint] property is a pidl extension that allows you to specify
|
|
||||||
that pidl should not generate a ndr_print_*() function for that
|
|
||||||
structure or union. This is used when you wish to define your own
|
|
||||||
print function that prints a structure in a nicer manner. A good
|
|
||||||
example is the use of [noprint] on dom_sid, which allows the
|
|
||||||
pretty-printing of SIDs.
|
|
||||||
|
|
||||||
=item value
|
|
||||||
|
|
||||||
The [value(expression)] property is a pidl extension that allows you
|
|
||||||
to specify the value of a field when it is put on the wire. This
|
|
||||||
allows fields that always have a well-known value to be automatically
|
|
||||||
filled in, thus making the API more programmer friendly. The
|
|
||||||
expression can be any C expression.
|
|
||||||
|
|
||||||
=item relative
|
|
||||||
|
|
||||||
The [relative] property can be supplied on a pointer. When it is used
|
|
||||||
it declares the pointer as a spoolss style "relative" pointer, which
|
|
||||||
means it appears on the wire as an offset within the current
|
|
||||||
encapsulating structure. This is not part of normal IDL/NDR, but it is
|
|
||||||
a very useful extension as it avoids the manual encoding of many
|
|
||||||
complex structures.
|
|
||||||
|
|
||||||
=item subcontext(length)
|
|
||||||
|
|
||||||
Specifies that a size of I<length>
|
|
||||||
bytes should be read, followed by a blob of that size,
|
|
||||||
which will be parsed as NDR.
|
|
||||||
|
|
||||||
subcontext() is deprecated now, and should not be used in new code.
|
|
||||||
Instead, use represent_as() or transmit_as().
|
|
||||||
|
|
||||||
=item flag
|
|
||||||
|
|
||||||
Specify boolean options, mostly used for
|
|
||||||
low-level NDR options. Several options
|
|
||||||
can be specified using the | character.
|
|
||||||
Note that flags are inherited by substructures!
|
|
||||||
|
|
||||||
=item nodiscriminant
|
|
||||||
|
|
||||||
The [nodiscriminant] property on a union means that the usual uint16
|
|
||||||
discriminent field at the start of the union on the wire is
|
|
||||||
omitted. This is not normally allowed in IDL/NDR, but is used for some
|
|
||||||
spoolss structures.
|
|
||||||
|
|
||||||
=item charset(name)
|
|
||||||
|
|
||||||
Specify that the array or string uses the specified
|
|
||||||
charset. If this attribute is specified, pidl will
|
|
||||||
take care of converting the character data from this format
|
|
||||||
to the host format. Commonly used values are UCS2, DOS and UTF8.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head2 Unsupported MIDL properties or statements
|
|
||||||
|
|
||||||
aggregatable, appobject, async_uuid, bindable, control,
|
|
||||||
defaultbind, defaultcollelem, defaultvalue, defaultvtable, dispinterface,
|
|
||||||
displaybind, dual, entry, first_is, helpcontext, helpfile, helpstringcontext,
|
|
||||||
helpstringdll, hidden, idl_module, idl_quote, id, immediatebind, importlib,
|
|
||||||
includelib, last_is, lcid, licensed, max_is, module,
|
|
||||||
ms_union, no_injected_text, nonbrowsable, noncreatable, nonextensible, odl,
|
|
||||||
oleautomation, optional, pragma, propget, propputref, propput, readonly,
|
|
||||||
requestedit, restricted, retval, source, uidefault,
|
|
||||||
usesgetlasterror, vararg, vi_progid, wire_marshal.
|
|
||||||
|
|
||||||
=head1 EXAMPLES
|
|
||||||
|
|
||||||
# Generating an Wireshark parser
|
|
||||||
$ ./pidl --ws-parser -- atsvc.idl
|
|
||||||
|
|
||||||
# Generating a TDR parser and header
|
|
||||||
$ ./pidl --tdr-parser --header -- regf.idl
|
|
||||||
|
|
||||||
# Generating a Samba3 client and server
|
|
||||||
$ ./pidl --samba3-ndr-client --samba3-ndr-server -- dfs.idl
|
|
||||||
|
|
||||||
# Generating a Samba4 NDR parser, client and server
|
|
||||||
$ ./pidl --ndr-parser --ndr-client --ndr-server -- samr.idl
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
L<https://msdn.microsoft.com/en-us/library/windows/desktop/aa373864%28v=vs.85%29.aspx>
|
|
||||||
L<https://wiki.wireshark.org/DCE/RPC>,
|
|
||||||
L<https://www.samba.org/>,
|
|
||||||
L<yapp(1)>
|
|
||||||
|
|
||||||
=head1 LICENSE
|
|
||||||
|
|
||||||
pidl is licensed under the GNU General Public License L<https://www.gnu.org/licenses/gpl.html>.
|
|
||||||
|
|
||||||
=head1 AUTHOR
|
|
||||||
|
|
||||||
pidl was written by Andrew Tridgell, Stefan Metzmacher, Tim Potter and Jelmer
|
|
||||||
Vernooij. The current maintainer is Jelmer Vernooij.
|
|
||||||
|
|
||||||
This manpage was written by Jelmer Vernooij, partially based on the original
|
|
||||||
pidl README by Andrew Tridgell.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use FindBin qw($RealBin $Script);
|
|
||||||
use lib "$RealBin/lib";
|
|
||||||
use Getopt::Long;
|
|
||||||
use File::Basename;
|
|
||||||
use Parse::Pidl qw ( $VERSION );
|
|
||||||
use Parse::Pidl::Util;
|
|
||||||
use Parse::Pidl::ODL;
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# save a data structure into a file
|
|
||||||
sub SaveStructure($$)
|
|
||||||
{
|
|
||||||
my($filename,$v) = @_;
|
|
||||||
FileSave($filename, Parse::Pidl::Util::MyDumper($v));
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# load a data structure from a file (as saved with SaveStructure)
|
|
||||||
sub LoadStructure($)
|
|
||||||
{
|
|
||||||
my $f = shift;
|
|
||||||
my $contents = FileLoad($f);
|
|
||||||
defined $contents || return undef;
|
|
||||||
return eval "$contents";
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# read a file into a string
|
|
||||||
sub FileLoad($)
|
|
||||||
{
|
|
||||||
my($filename) = shift;
|
|
||||||
local(*INPUTFILE);
|
|
||||||
open(INPUTFILE, $filename) || return undef;
|
|
||||||
my($saved_delim) = $/;
|
|
||||||
undef $/;
|
|
||||||
my($data) = <INPUTFILE>;
|
|
||||||
close(INPUTFILE);
|
|
||||||
$/ = $saved_delim;
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# write a string into a file
|
|
||||||
sub FileSave($$)
|
|
||||||
{
|
|
||||||
my($filename) = shift;
|
|
||||||
my($v) = shift;
|
|
||||||
local(*FILE);
|
|
||||||
open(FILE, ">$filename") || die "can't open $filename";
|
|
||||||
print FILE $v;
|
|
||||||
close(FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
my(@opt_incdirs) = ();
|
|
||||||
my($opt_help) = 0;
|
|
||||||
my($opt_version) = 0;
|
|
||||||
my($opt_parse_idl_tree) = 0;
|
|
||||||
my($opt_dump_idl_tree);
|
|
||||||
my($opt_dump_ndr_tree);
|
|
||||||
my($opt_dump_idl) = 0;
|
|
||||||
my($opt_diff) = 0;
|
|
||||||
my($opt_header);
|
|
||||||
my($opt_samba3_header);
|
|
||||||
my($opt_samba3_parser);
|
|
||||||
my($opt_samba3_server);
|
|
||||||
my($opt_samba3_ndr_client);
|
|
||||||
my($opt_samba3_ndr_server);
|
|
||||||
my($opt_samba3_template) = 0;
|
|
||||||
my($opt_template) = 0;
|
|
||||||
my($opt_client);
|
|
||||||
my($opt_typelib);
|
|
||||||
my($opt_server);
|
|
||||||
my($opt_ndr_parser);
|
|
||||||
my($opt_tdr_parser);
|
|
||||||
my($opt_ws_parser);
|
|
||||||
my($opt_python);
|
|
||||||
my($opt_quiet) = 0;
|
|
||||||
my($opt_outputdir) = '.';
|
|
||||||
my($opt_verbose) = 0;
|
|
||||||
my($opt_warn_compat) = 0;
|
|
||||||
my($opt_dcom_proxy);
|
|
||||||
my($opt_com_header);
|
|
||||||
|
|
||||||
#########################################
|
|
||||||
# display help text
|
|
||||||
sub ShowHelp()
|
|
||||||
{
|
|
||||||
print "perl IDL parser and code generator\n";
|
|
||||||
ShowVersion();
|
|
||||||
print"
|
|
||||||
Copyright (C) Andrew Tridgell <tridge\@samba.org>
|
|
||||||
Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
|
|
||||||
|
|
||||||
Usage: $Script [options] [--] <idlfile> [<idlfile>...]
|
|
||||||
|
|
||||||
Generic Options:
|
|
||||||
--help this help page
|
|
||||||
--version show pidl version
|
|
||||||
--outputdir=OUTDIR put output in OUTDIR/ [.]
|
|
||||||
--warn-compat warn about incompatibility with other compilers
|
|
||||||
--quiet be quiet
|
|
||||||
--verbose be verbose
|
|
||||||
--includedir DIR search DIR for included files
|
|
||||||
|
|
||||||
Debugging:
|
|
||||||
--dump-idl-tree[=FILE] dump internal representation to file [BASENAME.pidl]
|
|
||||||
--parse-idl-tree read internal representation instead of IDL
|
|
||||||
--dump-ndr-tree[=FILE] dump internal NDR data tree to file [BASENAME.ndr]
|
|
||||||
--dump-idl regenerate IDL file
|
|
||||||
--diff run diff on original IDL and dumped output
|
|
||||||
--typelib print type information
|
|
||||||
|
|
||||||
Samba 4 output:
|
|
||||||
--header[=OUTFILE] create generic header file [BASENAME.h]
|
|
||||||
--ndr-parser[=OUTFILE] create a C NDR parser [ndr_BASENAME.c]
|
|
||||||
--client[=OUTFILE] create a C NDR client [ndr_BASENAME_c.c]
|
|
||||||
--tdr-parser[=OUTFILE] create a C TDR parser [tdr_BASENAME.c]
|
|
||||||
--python[=OUTFILE] create python wrapper file [py_BASENAME.c]
|
|
||||||
--server[=OUTFILE] create server boilerplate [ndr_BASENAME_s.c]
|
|
||||||
--template print a template for a pipe
|
|
||||||
--dcom-proxy[=OUTFILE] create DCOM proxy [ndr_BASENAME_p.c]
|
|
||||||
--com-header[=OUTFILE] create header for COM [com_BASENAME.h]
|
|
||||||
|
|
||||||
Samba 3 output:
|
|
||||||
--samba3-ndr-client[=OUTF] create client calls for Samba3
|
|
||||||
using Samba4's NDR code [cli_BASENAME.c]
|
|
||||||
--samba3-ndr-server[=OUTF] create server call wrapper for Samba3
|
|
||||||
using Samba4's NDR code [srv_BASENAME.c]
|
|
||||||
--samba3-template print a template for a pipe
|
|
||||||
|
|
||||||
Wireshark parsers:
|
|
||||||
--ws-parser[=OUTFILE] create Wireshark parser and header
|
|
||||||
\n";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#########################################
|
|
||||||
# Display version
|
|
||||||
sub ShowVersion()
|
|
||||||
{
|
|
||||||
print "perl IDL version $VERSION\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
# main program
|
|
||||||
my $result = GetOptions (
|
|
||||||
'help|h|?' => \$opt_help,
|
|
||||||
'version' => \$opt_version,
|
|
||||||
'outputdir=s' => \$opt_outputdir,
|
|
||||||
'dump-idl' => \$opt_dump_idl,
|
|
||||||
'dump-idl-tree:s' => \$opt_dump_idl_tree,
|
|
||||||
'parse-idl-tree' => \$opt_parse_idl_tree,
|
|
||||||
'dump-ndr-tree:s' => \$opt_dump_ndr_tree,
|
|
||||||
'samba3-ndr-client:s' => \$opt_samba3_ndr_client,
|
|
||||||
'samba3-ndr-server:s' => \$opt_samba3_ndr_server,
|
|
||||||
'samba3-template' => \$opt_samba3_template,
|
|
||||||
'header:s' => \$opt_header,
|
|
||||||
'server:s' => \$opt_server,
|
|
||||||
'typelib:s' => \$opt_typelib,
|
|
||||||
'tdr-parser:s' => \$opt_tdr_parser,
|
|
||||||
'template' => \$opt_template,
|
|
||||||
'ndr-parser:s' => \$opt_ndr_parser,
|
|
||||||
'client:s' => \$opt_client,
|
|
||||||
'ws-parser:s' => \$opt_ws_parser,
|
|
||||||
'python' => \$opt_python,
|
|
||||||
'diff' => \$opt_diff,
|
|
||||||
'dcom-proxy:s' => \$opt_dcom_proxy,
|
|
||||||
'com-header:s' => \$opt_com_header,
|
|
||||||
'quiet' => \$opt_quiet,
|
|
||||||
'verbose' => \$opt_verbose,
|
|
||||||
'warn-compat' => \$opt_warn_compat,
|
|
||||||
'includedir=s@' => \@opt_incdirs
|
|
||||||
);
|
|
||||||
|
|
||||||
if (not $result) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_help) {
|
|
||||||
ShowHelp();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_version) {
|
|
||||||
ShowVersion();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub process_file($)
|
|
||||||
{
|
|
||||||
my $idl_file = shift;
|
|
||||||
my $outputdir = $opt_outputdir;
|
|
||||||
my $pidl;
|
|
||||||
my $ndr;
|
|
||||||
|
|
||||||
my $basename = basename($idl_file, ".idl");
|
|
||||||
|
|
||||||
unless ($opt_quiet) { print "Compiling $idl_file\n"; }
|
|
||||||
|
|
||||||
if ($opt_parse_idl_tree) {
|
|
||||||
$pidl = LoadStructure($idl_file);
|
|
||||||
defined $pidl || die "Failed to load $idl_file";
|
|
||||||
} else {
|
|
||||||
require Parse::Pidl::IDL;
|
|
||||||
|
|
||||||
$pidl = Parse::Pidl::IDL::parse_file($idl_file, \@opt_incdirs);
|
|
||||||
defined $pidl || die "Failed to parse $idl_file";
|
|
||||||
}
|
|
||||||
|
|
||||||
require Parse::Pidl::Typelist;
|
|
||||||
Parse::Pidl::Typelist::LoadIdl($pidl, $basename);
|
|
||||||
|
|
||||||
if (defined($opt_dump_idl_tree)) {
|
|
||||||
my($pidl_file) = ($opt_dump_idl_tree or "$outputdir/$basename.pidl");
|
|
||||||
SaveStructure($pidl_file, $pidl) or die "Failed to save $pidl_file\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_dump_idl) {
|
|
||||||
require Parse::Pidl::Dump;
|
|
||||||
print Parse::Pidl::Dump($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_diff) {
|
|
||||||
my($tempfile) = "$outputdir/$basename.tmp";
|
|
||||||
FileSave($tempfile, IdlDump::Dump($pidl));
|
|
||||||
system("diff -wu $idl_file $tempfile");
|
|
||||||
unlink($tempfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
|
|
||||||
if (defined($opt_com_header)) {
|
|
||||||
require Parse::Pidl::Samba4::COM::Header;
|
|
||||||
my $res = Parse::Pidl::Samba4::COM::Header::Parse($pidl,"$outputdir/ndr_$basename.h");
|
|
||||||
if ($res) {
|
|
||||||
FileSave($comh_filename, $res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_dcom_proxy)) {
|
|
||||||
require Parse::Pidl::Samba4::COM::Proxy;
|
|
||||||
my $res = Parse::Pidl::Samba4::COM::Proxy::Parse($pidl,$comh_filename);
|
|
||||||
if ($res) {
|
|
||||||
my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
|
|
||||||
FileSave($client, $res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_warn_compat) {
|
|
||||||
require Parse::Pidl::Compat;
|
|
||||||
Parse::Pidl::Compat::Check($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
$pidl = Parse::Pidl::ODL::ODL2IDL($pidl, dirname($idl_file), \@opt_incdirs);
|
|
||||||
|
|
||||||
if (defined($opt_ws_parser)) {
|
|
||||||
require Parse::Pidl::Wireshark::NDR;
|
|
||||||
|
|
||||||
my $cnffile = $idl_file;
|
|
||||||
$cnffile =~ s/\.idl$/\.cnf/;
|
|
||||||
|
|
||||||
my $generator = new Parse::Pidl::Wireshark::NDR();
|
|
||||||
$generator->Initialize($cnffile);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (defined($opt_ws_parser) or
|
|
||||||
defined($opt_client) or
|
|
||||||
defined($opt_server) or
|
|
||||||
defined($opt_header) or
|
|
||||||
defined($opt_ndr_parser) or
|
|
||||||
defined($opt_python) or
|
|
||||||
defined($opt_dump_ndr_tree) or
|
|
||||||
defined($opt_samba3_header) or
|
|
||||||
defined($opt_samba3_parser) or
|
|
||||||
defined($opt_samba3_server) or
|
|
||||||
defined($opt_samba3_ndr_client) or
|
|
||||||
defined($opt_samba3_ndr_server)) {
|
|
||||||
require Parse::Pidl::NDR;
|
|
||||||
$ndr = Parse::Pidl::NDR::Parse($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_dump_ndr_tree)) {
|
|
||||||
my($ndr_file) = ($opt_dump_ndr_tree or "$outputdir/$basename.ndr");
|
|
||||||
SaveStructure($ndr_file, $ndr) or die "Failed to save $ndr_file\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $gen_header = ($opt_header or "$outputdir/$basename.h");
|
|
||||||
if (defined($opt_header)) {
|
|
||||||
require Parse::Pidl::Samba4::Header;
|
|
||||||
FileSave($gen_header, Parse::Pidl::Samba4::Header::Parse($ndr));
|
|
||||||
}
|
|
||||||
|
|
||||||
my $h_filename = "$outputdir/ndr_$basename.h";
|
|
||||||
my $c_header = "$outputdir/ndr_$basename\_c.h";
|
|
||||||
if (defined($opt_client) or defined($opt_samba3_ndr_client)) {
|
|
||||||
require Parse::Pidl::Samba4::NDR::Client;
|
|
||||||
my ($c_client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
|
|
||||||
$c_header = $c_client;
|
|
||||||
$c_header =~ s/\.c$/.h/;
|
|
||||||
|
|
||||||
my $generator = new Parse::Pidl::Samba4::NDR::Client();
|
|
||||||
my ($srcd,$hdrd) = $generator->Parse(
|
|
||||||
$ndr,$gen_header,$h_filename,$c_header);
|
|
||||||
|
|
||||||
FileSave($c_client, $srcd);
|
|
||||||
FileSave($c_header, $hdrd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_python)) {
|
|
||||||
require Parse::Pidl::Samba4::Python;
|
|
||||||
my $generator = new Parse::Pidl::Samba4::Python();
|
|
||||||
my ($prsr) = $generator->Parse($basename, $ndr,
|
|
||||||
"$outputdir/ndr_$basename\_c.h", $h_filename);
|
|
||||||
FileSave("$outputdir/py_$basename.c", $prsr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_server)) {
|
|
||||||
require Parse::Pidl::Samba4::NDR::Server;
|
|
||||||
|
|
||||||
FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba4::NDR::Server::Parse($ndr,$h_filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_ndr_parser)) {
|
|
||||||
my $parser_fname = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
|
|
||||||
require Parse::Pidl::Samba4::NDR::Parser;
|
|
||||||
my $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
|
||||||
my ($header,$parser) = $generator->Parse($ndr, $gen_header, $h_filename);
|
|
||||||
|
|
||||||
FileSave($parser_fname, $parser);
|
|
||||||
FileSave($h_filename, $header);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_ws_parser)) {
|
|
||||||
require Parse::Pidl::Wireshark::NDR;
|
|
||||||
my($eparser) = ($opt_ws_parser or "$outputdir/packet-dcerpc-$basename.c");
|
|
||||||
my $eheader = $eparser;
|
|
||||||
$eheader =~ s/\.c$/\.h/;
|
|
||||||
my $cnffile = $idl_file;
|
|
||||||
$cnffile =~ s/\.idl$/\.cnf/;
|
|
||||||
|
|
||||||
my $generator = new Parse::Pidl::Wireshark::NDR();
|
|
||||||
my ($dp, $dh) = $generator->Parse($ndr, $idl_file, $eheader, $cnffile);
|
|
||||||
FileSave($eparser, $dp) if defined($dp);
|
|
||||||
FileSave($eheader, $dh) if defined($dh);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_tdr_parser)) {
|
|
||||||
my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
|
|
||||||
my $tdr_header = $tdr_parser;
|
|
||||||
$tdr_header =~ s/\.c$/\.h/;
|
|
||||||
require Parse::Pidl::Samba4::TDR;
|
|
||||||
my $generator = new Parse::Pidl::Samba4::TDR();
|
|
||||||
my ($hdr,$prsr) = $generator->Parser($pidl, $tdr_header, $gen_header);
|
|
||||||
FileSave($tdr_parser, $prsr);
|
|
||||||
FileSave($tdr_header, $hdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_typelib)) {
|
|
||||||
my $typelib = ($opt_typelib or "$outputdir/$basename.tlb");
|
|
||||||
require Parse::Pidl::Typelist;
|
|
||||||
FileSave($typelib, Parse::Pidl::Typelist::GenerateTypeLib());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_template) {
|
|
||||||
require Parse::Pidl::Samba4::Template;
|
|
||||||
print Parse::Pidl::Samba4::Template::Parse($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($opt_samba3_template) {
|
|
||||||
require Parse::Pidl::Samba3::Template;
|
|
||||||
print Parse::Pidl::Samba3::Template::Parse($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_samba3_ndr_client)) {
|
|
||||||
my $client = ($opt_samba3_ndr_client or "$outputdir/cli_$basename.c");
|
|
||||||
my $header = $client; $header =~ s/\.c$/\.h/;
|
|
||||||
require Parse::Pidl::Samba3::ClientNDR;
|
|
||||||
my $generator = new Parse::Pidl::Samba3::ClientNDR();
|
|
||||||
my ($c_code,$h_code) = $generator->Parse($ndr, $header, $c_header);
|
|
||||||
FileSave($client, $c_code);
|
|
||||||
FileSave($header, $h_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($opt_samba3_ndr_server)) {
|
|
||||||
my $server = ($opt_samba3_ndr_server or "$outputdir/srv_$basename.c");
|
|
||||||
my $header = $server; $header =~ s/\.c$/\.h/;
|
|
||||||
require Parse::Pidl::Samba3::ServerNDR;
|
|
||||||
my ($c_code,$h_code) = Parse::Pidl::Samba3::ServerNDR::Parse($ndr, $header, $h_filename);
|
|
||||||
FileSave($server, $c_code);
|
|
||||||
FileSave($header, $h_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scalar(@ARGV) == 0) {
|
|
||||||
print "$Script: no input files\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
process_file($_) foreach (@ARGV);
|
|
|
@ -1,181 +0,0 @@
|
||||||
# Some simple utility functions for pidl tests
|
|
||||||
# Copyright (C) 2005-2006 Jelmer Vernooij
|
|
||||||
# Published under the GNU General Public License
|
|
||||||
|
|
||||||
package Util;
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
@ISA = qw(Exporter);
|
|
||||||
@EXPORT = qw(test_samba4_ndr test_warnings test_errors);
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin/../lib";
|
|
||||||
|
|
||||||
use Parse::Pidl::Samba4 qw(is_intree);
|
|
||||||
|
|
||||||
use Parse::Pidl;
|
|
||||||
my $warnings = "";
|
|
||||||
undef &Parse::Pidl::warning;
|
|
||||||
*Parse::Pidl::warning = sub {
|
|
||||||
my ($e, $l) = @_;
|
|
||||||
if (defined($e)) {
|
|
||||||
$warnings .= "$e->{FILE}:$e->{LINE}: $l\n";
|
|
||||||
} else {
|
|
||||||
$warnings .= "$l\n";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
my $errors = "";
|
|
||||||
undef &Parse::Pidl::error;
|
|
||||||
*Parse::Pidl::error = sub {
|
|
||||||
my ($e, $l) = @_;
|
|
||||||
if (defined($e)) {
|
|
||||||
$errors .= "$e->{FILE}:$e->{LINE}: $l\n";
|
|
||||||
} else {
|
|
||||||
$errors .= "$l\n";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
use Test::More;
|
|
||||||
use Parse::Pidl::IDL;
|
|
||||||
use Parse::Pidl::NDR;
|
|
||||||
use Parse::Pidl::Samba4::NDR::Parser;
|
|
||||||
use Parse::Pidl::Samba4::Header;
|
|
||||||
|
|
||||||
# Generate a Samba4 parser for an IDL fragment and run it with a specified
|
|
||||||
# piece of code to check whether the parser works as expected
|
|
||||||
sub test_samba4_ndr
|
|
||||||
{
|
|
||||||
my ($name,$idl,$c,$extra) = @_;
|
|
||||||
|
|
||||||
$extra = "" unless defined($extra);
|
|
||||||
|
|
||||||
my $pidl = Parse::Pidl::IDL::parse_string("interface echo { $idl }; ", "<$name>");
|
|
||||||
ok(defined($pidl), "($name) parse idl");
|
|
||||||
|
|
||||||
my $pndr = Parse::Pidl::NDR::Parse($pidl);
|
|
||||||
ok(defined($pndr), "($name) generate NDR tree");
|
|
||||||
|
|
||||||
my $header = Parse::Pidl::Samba4::Header::Parse($pndr);
|
|
||||||
ok(defined($header), "($name) generate generic header");
|
|
||||||
|
|
||||||
my $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
|
||||||
my ($ndrheader,$ndrparser) = $generator->Parse($pndr, undef, undef);
|
|
||||||
ok(defined($ndrparser), "($name) generate NDR parser");
|
|
||||||
ok(defined($ndrheader), "($name) generate NDR header");
|
|
||||||
|
|
||||||
SKIP: {
|
|
||||||
|
|
||||||
my $flags;
|
|
||||||
if (system("pkg-config --exists ndr") == 0 and !is_intree()) {
|
|
||||||
$flags = `pkg-config --libs --cflags ndr`;
|
|
||||||
} else {
|
|
||||||
skip "no samba environment available, skipping compilation", 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $main = "
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <util/data_blob.h>
|
|
||||||
|
|
||||||
/* header start */
|
|
||||||
$header
|
|
||||||
/* header end */
|
|
||||||
|
|
||||||
/* ndrheader start */
|
|
||||||
$ndrheader
|
|
||||||
/* ndrheader end */
|
|
||||||
|
|
||||||
/* extra start */
|
|
||||||
$extra
|
|
||||||
/* extra end */
|
|
||||||
|
|
||||||
/* ndrparser start */
|
|
||||||
$ndrparser
|
|
||||||
/* ndrparser end */
|
|
||||||
|
|
||||||
/* main start */
|
|
||||||
int main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
TALLOC_CTX *mem_ctx = talloc_init(NULL);
|
|
||||||
|
|
||||||
$c
|
|
||||||
|
|
||||||
talloc_free(mem_ctx);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* main end */
|
|
||||||
\n";
|
|
||||||
|
|
||||||
my $main_debug = "# ".join("\n# ", split("\n", $main));
|
|
||||||
|
|
||||||
my $test_data_prefix = $ENV{TEST_DATA_PREFIX};
|
|
||||||
my $outfile;
|
|
||||||
if (defined($test_data_prefix)) {
|
|
||||||
$outfile = "$test_data_prefix/test-$name";
|
|
||||||
} else {
|
|
||||||
$outfile = "./test-$name";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $cflags = $ENV{CFLAGS};
|
|
||||||
unless (defined($cflags)) {
|
|
||||||
$cflags = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $ldflags = $ENV{LDFLAGS};
|
|
||||||
unless (defined($ldflags)) {
|
|
||||||
$ldflags = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $cc = $ENV{CC};
|
|
||||||
unless (defined($cc)) {
|
|
||||||
$cc = "cc";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $cmd = "$cc $cflags -x c - -o $outfile $flags $ldflags";
|
|
||||||
$cmd =~ s/\n//g;
|
|
||||||
open CC, "|$cmd";
|
|
||||||
print CC $main;
|
|
||||||
close CC;
|
|
||||||
|
|
||||||
ok(-f $outfile, "($name) compile");
|
|
||||||
|
|
||||||
my $ret = system($outfile, ()) >> 8;
|
|
||||||
print "# code:\n#\n$main_debug\n" if ($ret != 0);
|
|
||||||
print "# cmd: $cmd\n" if ($ret != 0);
|
|
||||||
print "# return code: $ret\n" if ($ret != 0);
|
|
||||||
|
|
||||||
ok($ret == 0, "($name) run");
|
|
||||||
|
|
||||||
ok(unlink($outfile), "($name) remove");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub test_warnings($$)
|
|
||||||
{
|
|
||||||
my ($exp, $code) = @_;
|
|
||||||
|
|
||||||
$warnings = "";
|
|
||||||
|
|
||||||
$code->();
|
|
||||||
|
|
||||||
is($warnings, $exp);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub test_errors($$)
|
|
||||||
{
|
|
||||||
my ($exp, $code) = @_;
|
|
||||||
$errors = "";
|
|
||||||
$code->();
|
|
||||||
|
|
||||||
is($errors, $exp);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -1,21 +0,0 @@
|
||||||
#!/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 => 7;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util;
|
|
||||||
use Parse::Pidl::Util qw(MyDumper);
|
|
||||||
use Parse::Pidl::CUtil qw(get_pointer_to get_value_of);
|
|
||||||
|
|
||||||
is("&foo", get_pointer_to("foo"));
|
|
||||||
is("&(&foo)", get_pointer_to(get_pointer_to("foo")));
|
|
||||||
is("*foo", get_pointer_to("**foo"));
|
|
||||||
is("foo", get_pointer_to("*foo"));
|
|
||||||
|
|
||||||
is("foo", get_value_of("&foo"));
|
|
||||||
is("*foo", get_value_of("foo"));
|
|
||||||
is("**foo", get_value_of("*foo"));
|
|
|
@ -1,15 +0,0 @@
|
||||||
#!/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 => 1;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util;
|
|
||||||
use Parse::Pidl::Dump qw(DumpStruct);
|
|
||||||
|
|
||||||
is (DumpStruct({ NAME => "foo", ELEMENTS => []}),
|
|
||||||
"struct foo {\n}");
|
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
#!/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 => 27;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util;
|
|
||||||
use Parse::Pidl::Util qw(MyDumper);
|
|
||||||
use Parse::Pidl::Samba4::Header qw(
|
|
||||||
GenerateFunctionInEnv GenerateFunctionOutEnv GenerateStructEnv
|
|
||||||
EnvSubstituteValue);
|
|
||||||
use Parse::Pidl::IDL qw(parse_string);
|
|
||||||
use Parse::Pidl::NDR;
|
|
||||||
|
|
||||||
sub parse_idl($)
|
|
||||||
{
|
|
||||||
my $text = shift;
|
|
||||||
my $idl = Parse::Pidl::IDL::parse_string($text, "nofile");
|
|
||||||
my $ndr = Parse::Pidl::NDR::Parse($idl);
|
|
||||||
return Parse::Pidl::Samba4::Header::Parse($ndr);
|
|
||||||
}
|
|
||||||
|
|
||||||
like(parse_idl(""), qr/\/\* header auto-generated by pidl \*\/\n/sm, "includes work");
|
|
||||||
like(parse_idl("interface x {}"), qr/\/\* header auto-generated by pidl \*\/\n/sm, "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");
|
|
||||||
like(parse_idl("interface p { struct x { int y; }; };"),
|
|
||||||
qr/struct x.*{.*int32_t y;.*}.*;/sm, "interface member generated properly");
|
|
||||||
|
|
||||||
like(parse_idl("interface p { struct x { struct y z; }; };"),
|
|
||||||
qr/struct x.*{.*struct y z;.*}.*;/sm, "tagged type struct member");
|
|
||||||
|
|
||||||
like(parse_idl("interface p { struct x { union y z; }; };"),
|
|
||||||
qr/struct x.*{.*union y z;.*}.*;/sm, "tagged type union member");
|
|
||||||
|
|
||||||
like(parse_idl("interface p { struct x { }; };"),
|
|
||||||
qr/struct x.*{.*char _empty_;.*}.*;/sm, "empty struct");
|
|
||||||
|
|
||||||
like(parse_idl("interface p { struct x; };"),
|
|
||||||
qr/struct x;/sm, "struct declaration");
|
|
||||||
|
|
||||||
like(parse_idl("interface p { typedef struct x { int p; } x; };"),
|
|
||||||
qr/struct x.*{.*int32_t p;.*};/sm, "double struct declaration");
|
|
||||||
|
|
||||||
like(parse_idl("cpp_quote(\"some-foo\")"),
|
|
||||||
qr/some-foo/sm, "cpp quote");
|
|
||||||
|
|
||||||
# Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
|
|
||||||
my $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));
|
|
||||||
|
|
||||||
$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
|
|
||||||
is_deeply({ foo => "r->foo", bar => "r->bar", this => "r" },
|
|
||||||
GenerateStructEnv($fn, "r"));
|
|
||||||
|
|
||||||
$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
|
|
||||||
is_deeply({ foo => "some->complex.variable->foo",
|
|
||||||
bar => "some->complex.variable->bar",
|
|
||||||
this => "some->complex.variable" },
|
|
||||||
GenerateStructEnv($fn, "some->complex.variable"));
|
|
||||||
|
|
||||||
$fn = { ELEMENTS => [ { NAME => "foo", PROPERTIES => { value => 3 }} ] };
|
|
||||||
|
|
||||||
my $env = GenerateStructEnv($fn, "r");
|
|
||||||
EnvSubstituteValue($env, $fn);
|
|
||||||
is_deeply($env, { foo => 3, this => "r" });
|
|
||||||
|
|
||||||
$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
|
|
||||||
$env = GenerateStructEnv($fn, "r");
|
|
||||||
EnvSubstituteValue($env, $fn);
|
|
||||||
is_deeply($env, { foo => 'r->foo', bar => 'r->bar', this => "r" });
|
|
||||||
|
|
||||||
$fn = { ELEMENTS => [ { NAME => "foo", PROPERTIES => { value => 0 }} ] };
|
|
||||||
|
|
||||||
$env = GenerateStructEnv($fn, "r");
|
|
||||||
EnvSubstituteValue($env, $fn);
|
|
||||||
is_deeply($env, { foo => 0, this => "r" });
|
|
||||||
|
|
||||||
|
|
|
@ -1,561 +0,0 @@
|
||||||
#!/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 => 47;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util;
|
|
||||||
use Parse::Pidl::Util qw(MyDumper);
|
|
||||||
use Parse::Pidl::NDR qw(GetElementLevelTable ParseElement align_type mapToScalar ParseType can_contain_deferred);
|
|
||||||
|
|
||||||
# Case 1
|
|
||||||
|
|
||||||
my $e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {},
|
|
||||||
'POINTERS' => 0,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'STRUCT' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 0,
|
|
||||||
'LEVEL_INDEX' => 0,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
my $ne = ParseElement($e, "unique", 0);
|
|
||||||
is($ne->{ORIGINAL}, $e);
|
|
||||||
is($ne->{NAME}, "v");
|
|
||||||
is($ne->{ALIGN}, 1);
|
|
||||||
is($ne->{TYPE}, "uint8");
|
|
||||||
is_deeply($ne->{LEVELS}, [
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 0,
|
|
||||||
'LEVEL_INDEX' => 0,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# Case 2 : pointers
|
|
||||||
#
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"unique" => 1},
|
|
||||||
'POINTERS' => 1,
|
|
||||||
'PARENT' => { TYPE => 'STRUCT' },
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 0,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 0,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 1,
|
|
||||||
'LEVEL_INDEX' => 1,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# Case 3 : double pointers
|
|
||||||
#
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"unique" => 1},
|
|
||||||
'POINTERS' => 2,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'STRUCT' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 0,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 0,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 1,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 1,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 1,
|
|
||||||
'LEVEL_INDEX' => 2,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# Case 3 : ref pointers
|
|
||||||
#
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"ref" => 1},
|
|
||||||
'POINTERS' => 1,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'STRUCT' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 0,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 0,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 1,
|
|
||||||
'LEVEL_INDEX' => 1,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# Case 3 : ref pointers
|
|
||||||
#
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"ref" => 1},
|
|
||||||
'POINTERS' => 3,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'STRUCT' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 0,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 0,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 1,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 1,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 2,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 2,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 1,
|
|
||||||
'LEVEL_INDEX' => 3,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# Case 3 : ref pointers
|
|
||||||
#
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"ref" => 1},
|
|
||||||
'POINTERS' => 3,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'STRUCT' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "ref", 0), [
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 0,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 0,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 1,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 1,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 2,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 2,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 1,
|
|
||||||
'LEVEL_INDEX' => 3,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# Case 4 : top-level ref pointers
|
|
||||||
#
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"ref" => 1},
|
|
||||||
'POINTERS' => 1,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'FUNCTION' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 0,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 0,
|
|
||||||
LEVEL => 'TOP'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 0,
|
|
||||||
'LEVEL_INDEX' => 1,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# Case 4 : top-level ref pointers, triple with pointer_default("unique")
|
|
||||||
#
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"ref" => 1},
|
|
||||||
'POINTERS' => 3,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'FUNCTION' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 0,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 0,
|
|
||||||
LEVEL => 'TOP'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 1,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 1,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 2,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 2,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 1,
|
|
||||||
'LEVEL_INDEX' => 3,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# Case 4 : top-level unique pointers, triple with pointer_default("unique")
|
|
||||||
#
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"unique" => 1, "in" => 1},
|
|
||||||
'POINTERS' => 3,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'FUNCTION' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 0,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 0,
|
|
||||||
LEVEL => 'TOP'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 1,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 1,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 2,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 2,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 1,
|
|
||||||
'LEVEL_INDEX' => 3,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# Case 4 : top-level unique pointers, triple with pointer_default("ref")
|
|
||||||
#
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"unique" => 1, "in" => 1},
|
|
||||||
'POINTERS' => 3,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'FUNCTION' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "ref", 0), [
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 0,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "unique",
|
|
||||||
POINTER_INDEX => 0,
|
|
||||||
LEVEL => 'TOP'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 1,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 1,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 2,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 2,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 1,
|
|
||||||
'LEVEL_INDEX' => 3,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# Case 4 : top-level ref pointers, triple with pointer_default("ref")
|
|
||||||
#
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"ref" => 1},
|
|
||||||
'POINTERS' => 3,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'FUNCTION' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
is_deeply(GetElementLevelTable($e, "ref", 0), [
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 0,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 0,
|
|
||||||
LEVEL => 'TOP'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 1,
|
|
||||||
IS_DEFERRED => 0,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 1,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
LEVEL_INDEX => 2,
|
|
||||||
IS_DEFERRED => 1,
|
|
||||||
TYPE => 'POINTER',
|
|
||||||
POINTER_TYPE => "ref",
|
|
||||||
POINTER_INDEX => 2,
|
|
||||||
LEVEL => 'EMBEDDED'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'IS_DEFERRED' => 1,
|
|
||||||
'LEVEL_INDEX' => 3,
|
|
||||||
'DATA_TYPE' => 'uint8',
|
|
||||||
'CONTAINS_DEFERRED' => 0,
|
|
||||||
'TYPE' => 'DATA',
|
|
||||||
'IS_SURROUNDING' => 0,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
# representation_type
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => { represent_as => "bar" },
|
|
||||||
'POINTERS' => 0,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'STRUCT' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
$ne = ParseElement($e, undef, 0);
|
|
||||||
is($ne->{REPRESENTATION_TYPE}, "bar");
|
|
||||||
|
|
||||||
# representation_type
|
|
||||||
$e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => { },
|
|
||||||
'POINTERS' => 0,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'STRUCT' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
$ne = ParseElement($e, undef, 0);
|
|
||||||
is($ne->{REPRESENTATION_TYPE}, "uint8");
|
|
||||||
|
|
||||||
is(align_type("hyper"), 8);
|
|
||||||
is(align_type("double"), 8);
|
|
||||||
is(align_type("uint32"), 4);
|
|
||||||
is(align_type("uint16"), 2);
|
|
||||||
is(align_type("uint8"), 1);
|
|
||||||
is(align_type({ TYPE => "STRUCT", "NAME" => "bla",
|
|
||||||
ELEMENTS => [ { TYPE => "uint16" } ] }), 4);
|
|
||||||
is(align_type({ TYPE => "STRUCT",
|
|
||||||
ELEMENTS => [ { TYPE => "hyper" } ] }), 8);
|
|
||||||
is(align_type({ TYPE => "TYPEDEF", DATA => {
|
|
||||||
TYPE => "STRUCT",
|
|
||||||
ELEMENTS => [ { TYPE => "hyper" } ] }}), 8);
|
|
||||||
# typedef of struct without body
|
|
||||||
is(align_type({ TYPE => "TYPEDEF", DATA => {
|
|
||||||
TYPE => "STRUCT", ELEMENTS => undef }}), 4);
|
|
||||||
# struct without body
|
|
||||||
is(align_type({ TYPE => "STRUCT", ELEMENTS => undef }), 4);
|
|
||||||
# empty struct
|
|
||||||
is(align_type({ TYPE => "STRUCT", ELEMENTS => [] }), 1);
|
|
||||||
is(align_type({ TYPE => "STRUCT", "NAME" => "bla",
|
|
||||||
ELEMENTS => [ { TYPE => "uint8" } ] }), 4);
|
|
||||||
|
|
||||||
is(mapToScalar("someverymuchnotexistingtype"), undef);
|
|
||||||
is(mapToScalar("uint32"), "uint32");
|
|
||||||
is(mapToScalar({TYPE => "ENUM", PARENT => { PROPERTIES => { enum8bit => 1 } } }), "uint8");
|
|
||||||
is(mapToScalar({TYPE => "BITMAP", PROPERTIES => { bitmap64bit => 1 } }),
|
|
||||||
"hyper");
|
|
||||||
is(mapToScalar({TYPE => "TYPEDEF", DATA => {TYPE => "ENUM", PARENT => { PROPERTIES => { enum8bit => 1 } } }}), "uint8");
|
|
||||||
|
|
||||||
my $t;
|
|
||||||
$t = {
|
|
||||||
TYPE => "STRUCT",
|
|
||||||
NAME => "foo",
|
|
||||||
SURROUNDING_ELEMENT => undef,
|
|
||||||
ELEMENTS => undef,
|
|
||||||
PROPERTIES => undef,
|
|
||||||
ORIGINAL => {
|
|
||||||
TYPE => "STRUCT",
|
|
||||||
NAME => "foo"
|
|
||||||
},
|
|
||||||
ALIGN => undef
|
|
||||||
};
|
|
||||||
is_deeply(ParseType($t->{ORIGINAL}, "ref", 0), $t);
|
|
||||||
|
|
||||||
$t = {
|
|
||||||
TYPE => "UNION",
|
|
||||||
NAME => "foo",
|
|
||||||
SWITCH_TYPE => "uint32",
|
|
||||||
ELEMENTS => undef,
|
|
||||||
PROPERTIES => undef,
|
|
||||||
HAS_DEFAULT => 0,
|
|
||||||
IS_MS_UNION => 0,
|
|
||||||
ORIGINAL => {
|
|
||||||
TYPE => "UNION",
|
|
||||||
NAME => "foo"
|
|
||||||
},
|
|
||||||
ALIGN => undef
|
|
||||||
};
|
|
||||||
is_deeply(ParseType($t->{ORIGINAL}, "ref", 0), $t);
|
|
||||||
|
|
||||||
ok(not can_contain_deferred("uint32"));
|
|
||||||
ok(can_contain_deferred("some_unknown_type"));
|
|
||||||
ok(can_contain_deferred({ TYPE => "STRUCT",
|
|
||||||
ELEMENTS => [ { TYPE => "uint32", POINTERS => 40 } ]}));
|
|
||||||
ok(can_contain_deferred({ TYPE => "TYPEDEF",
|
|
||||||
DATA => { TYPE => "STRUCT",
|
|
||||||
ELEMENTS => [ { TYPE => "uint32", POINTERS => 40 } ]}}));
|
|
||||||
ok(not can_contain_deferred({ TYPE => "STRUCT",
|
|
||||||
ELEMENTS => [ { TYPE => "uint32" } ]}));
|
|
||||||
ok(not can_contain_deferred({ TYPE => "TYPEDEF",
|
|
||||||
DATA => { TYPE => "STRUCT",
|
|
||||||
ELEMENTS => [ { TYPE => "uint32" } ]}}));
|
|
||||||
ok(can_contain_deferred({ TYPE => "STRUCT",
|
|
||||||
ELEMENTS => [ { TYPE => "someunknowntype" } ]}));
|
|
||||||
# Make sure the elements for a enum without body aren't filled in
|
|
||||||
ok(not defined(ParseType({TYPE => "ENUM", NAME => "foo" }, "ref", 0)->{ELEMENTS}));
|
|
||||||
# Make sure the elements for a bitmap without body aren't filled in
|
|
||||||
ok(not defined(ParseType({TYPE => "BITMAP", NAME => "foo" }, "ref", 0)->{ELEMENTS}));
|
|
||||||
# Make sure the elements for a union without body aren't filled in
|
|
||||||
ok(not defined(ParseType({TYPE => "UNION", NAME => "foo" }, "ref", 0)->{ELEMENTS}));
|
|
|
@ -1,143 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# NDR alignment tests
|
|
||||||
# (C) 2005 Jelmer Vernooij. Published under the GNU GPL
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 5 * 8;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util qw(test_samba4_ndr);
|
|
||||||
|
|
||||||
test_samba4_ndr('align-uint8-uint16',
|
|
||||||
'
|
|
||||||
typedef [public] struct {
|
|
||||||
uint8 x;
|
|
||||||
uint16 y;
|
|
||||||
} bla;
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct bla r;
|
|
||||||
uint8_t expected[] = { 0x0D, 0x00, 0xef, 0xbe };
|
|
||||||
DATA_BLOB expected_blob = { expected, 4 };
|
|
||||||
DATA_BLOB result_blob;
|
|
||||||
r.x = 13;
|
|
||||||
r.y = 0xbeef;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
result_blob = ndr_push_blob(ndr);
|
|
||||||
|
|
||||||
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
|
||||||
return 2;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr('align-uint8-uint32',
|
|
||||||
'
|
|
||||||
typedef [public] struct {
|
|
||||||
uint8 x;
|
|
||||||
uint32 y;
|
|
||||||
} bla;
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct bla r;
|
|
||||||
uint8_t expected[] = { 0x0D, 0x00, 0x00, 0x00, 0xef, 0xbe, 0xef, 0xbe };
|
|
||||||
DATA_BLOB expected_blob = { expected, 8 };
|
|
||||||
DATA_BLOB result_blob;
|
|
||||||
r.x = 13;
|
|
||||||
r.y = 0xbeefbeef;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
result_blob = ndr_push_blob(ndr);
|
|
||||||
|
|
||||||
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
|
||||||
return 2;
|
|
||||||
');
|
|
||||||
|
|
||||||
|
|
||||||
test_samba4_ndr('align-uint8-hyper',
|
|
||||||
'
|
|
||||||
typedef [public] struct {
|
|
||||||
uint8 x;
|
|
||||||
hyper y;
|
|
||||||
} bla;
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct bla r;
|
|
||||||
uint8_t expected[] = { 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe };
|
|
||||||
DATA_BLOB expected_blob = { expected, 16 };
|
|
||||||
DATA_BLOB result_blob;
|
|
||||||
r.x = 13;
|
|
||||||
r.y = 0xbeefbeefbeefbeefLLU;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
result_blob = ndr_push_blob(ndr);
|
|
||||||
|
|
||||||
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
|
||||||
return 2;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr('noalignflag-uint8-uint16',
|
|
||||||
'
|
|
||||||
typedef [public] struct {
|
|
||||||
uint8 x;
|
|
||||||
uint16 y;
|
|
||||||
} bla;
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct bla r;
|
|
||||||
uint8_t expected[] = { 0x0D, 0xef, 0xbe };
|
|
||||||
DATA_BLOB expected_blob = { expected, 3 };
|
|
||||||
DATA_BLOB result_blob;
|
|
||||||
ndr->flags |= LIBNDR_FLAG_NOALIGN;
|
|
||||||
|
|
||||||
r.x = 13;
|
|
||||||
r.y = 0xbeef;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
result_blob = ndr_push_blob(ndr);
|
|
||||||
|
|
||||||
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
|
||||||
return 2;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr('align-blob-align2',
|
|
||||||
'
|
|
||||||
typedef [public] struct {
|
|
||||||
uint8 x;
|
|
||||||
[flag(LIBNDR_FLAG_ALIGN2)] DATA_BLOB data;
|
|
||||||
uint8 y;
|
|
||||||
} blie;
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct blie r;
|
|
||||||
uint8_t data[] = { 0x01, 0x02 };
|
|
||||||
uint8_t expected[] = { 0x0D, 0x00, 0x0E };
|
|
||||||
DATA_BLOB expected_blob = { expected, 3 };
|
|
||||||
DATA_BLOB result_blob;
|
|
||||||
|
|
||||||
r.x = 13;
|
|
||||||
r.y = 14;
|
|
||||||
r.data.data = data;
|
|
||||||
r.data.length = 2;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_blie(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
result_blob = ndr_push_blob(ndr);
|
|
||||||
|
|
||||||
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
|
||||||
return 2;
|
|
||||||
');
|
|
|
@ -1,118 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# NDR allocation tests
|
|
||||||
# (C) 2005 Jelmer Vernooij. Published under the GNU GPL
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 5 * 8;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util qw(test_samba4_ndr);
|
|
||||||
|
|
||||||
# Check that an outgoing scalar pointer is allocated correctly
|
|
||||||
|
|
||||||
test_samba4_ndr("alloc-scalar",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint8 *x;
|
|
||||||
} bla;
|
|
||||||
|
|
||||||
[public] void TestAlloc([in] bla foo);
|
|
||||||
','
|
|
||||||
uint8_t data[] = { 0xde, 0xad, 0xbe, 0xef, 0x03 };
|
|
||||||
DATA_BLOB b = { data, 5 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
|
||||||
struct TestAlloc r;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (r.in.foo.x == NULL)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (*r.in.foo.x != 0x03)
|
|
||||||
return 3;
|
|
||||||
'
|
|
||||||
);
|
|
||||||
|
|
||||||
# Check that an outgoing buffer pointer is allocated correctly
|
|
||||||
test_samba4_ndr("alloc-buffer",
|
|
||||||
'
|
|
||||||
typedef struct { uint8 data; } blie;
|
|
||||||
typedef struct { blie *x; } bla;
|
|
||||||
|
|
||||||
[public] void TestAlloc([in] bla foo);
|
|
||||||
','
|
|
||||||
uint8_t data[] = { 0xde, 0xad, 0xbe, 0xef, 0x03 };
|
|
||||||
DATA_BLOB b = { data, 5 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
|
||||||
struct TestAlloc r;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (r.in.foo.x == NULL)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (r.in.foo.x->data != 0x03)
|
|
||||||
return 3;
|
|
||||||
'
|
|
||||||
);
|
|
||||||
|
|
||||||
# Check that ref pointers aren't allocated by default
|
|
||||||
test_samba4_ndr("ref-noalloc-null",
|
|
||||||
'
|
|
||||||
[public] void TestAlloc([in,ref] uint8 *t);
|
|
||||||
','
|
|
||||||
uint8_t data[] = { 0x03 };
|
|
||||||
DATA_BLOB b = { data, 1 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
|
||||||
struct TestAlloc r;
|
|
||||||
r.in.t = NULL;
|
|
||||||
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
'
|
|
||||||
);
|
|
||||||
|
|
||||||
# Check that ref pointers aren't allocated by default
|
|
||||||
test_samba4_ndr("ref-noalloc",
|
|
||||||
'
|
|
||||||
[public] void TestAlloc([in,ref] uint8 *t);
|
|
||||||
','
|
|
||||||
uint8_t data[] = { 0x03 };
|
|
||||||
DATA_BLOB b = { data, 1 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
|
||||||
struct TestAlloc r;
|
|
||||||
uint8_t x;
|
|
||||||
r.in.t = &x;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (*r.in.t != 0x03)
|
|
||||||
return 2;
|
|
||||||
'
|
|
||||||
);
|
|
||||||
|
|
||||||
# Check that an outgoing ref pointer is allocated correctly
|
|
||||||
test_samba4_ndr("ref-alloc",
|
|
||||||
'
|
|
||||||
[public] void TestAlloc([in,ref] uint8 *t);
|
|
||||||
','
|
|
||||||
uint8_t data[] = { 0x03 };
|
|
||||||
DATA_BLOB b = { data, 1 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
|
||||||
struct TestAlloc r;
|
|
||||||
ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
|
|
||||||
r.in.t = NULL;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (r.in.t == NULL)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (*r.in.t != 0x03)
|
|
||||||
return 3;
|
|
||||||
'
|
|
||||||
);
|
|
|
@ -1,37 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# Array testing
|
|
||||||
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
# Published under the GNU General Public License
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 8;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util qw(test_samba4_ndr);
|
|
||||||
|
|
||||||
test_samba4_ndr(
|
|
||||||
'Fixed-Array',
|
|
||||||
|
|
||||||
'[public] void Test([in] uint8 x[10]);',
|
|
||||||
|
|
||||||
'
|
|
||||||
uint8_t data[] = {1,2,3,4,5,6,7,8,9,10};
|
|
||||||
int i;
|
|
||||||
DATA_BLOB b;
|
|
||||||
struct ndr_pull *ndr;
|
|
||||||
struct Test r;
|
|
||||||
|
|
||||||
b.data = data;
|
|
||||||
b.length = 10;
|
|
||||||
ndr = ndr_pull_init_blob(&b, mem_ctx, NULL);
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_Test(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 10)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
|
||||||
if (r.in.x[i] != i+1) return 3;
|
|
||||||
}
|
|
||||||
');
|
|
|
@ -1,21 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
# Published under the GNU General Public License
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 2;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util;
|
|
||||||
use Parse::Pidl;
|
|
||||||
use Parse::Pidl::IDL;
|
|
||||||
|
|
||||||
sub parse_idl($)
|
|
||||||
{
|
|
||||||
my $idl = shift;
|
|
||||||
my $pidl = Parse::Pidl::IDL::parse_string("interface echo { $idl }; ", "nofile");
|
|
||||||
Parse::Pidl::NDR::Parse($pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
test_warnings("", sub {parse_idl("void x();"); });
|
|
||||||
test_warnings("nofile:0: top-level [out] pointer `x' is not a [ref] pointer\n", sub {parse_idl("void x([out,unique] int *x);"); });
|
|
|
@ -1,26 +0,0 @@
|
||||||
#!/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 => 1;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util;
|
|
||||||
use Parse::Pidl::Util qw(MyDumper);
|
|
||||||
use Parse::Pidl::NDR qw(ValidElement);
|
|
||||||
|
|
||||||
# Case 1
|
|
||||||
|
|
||||||
my $e = {
|
|
||||||
'FILE' => 'foo.idl',
|
|
||||||
'NAME' => 'v',
|
|
||||||
'PROPERTIES' => {"subcontext" => 1},
|
|
||||||
'POINTERS' => 0,
|
|
||||||
'TYPE' => 'uint8',
|
|
||||||
'PARENT' => { TYPE => 'STRUCT' },
|
|
||||||
'LINE' => 42 };
|
|
||||||
|
|
||||||
test_warnings("foo.idl:42: subcontext() is deprecated. Use represent_as() or transmit_as() instead\n",
|
|
||||||
sub { ValidElement($e); });
|
|
|
@ -1,44 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# Simple tests for unique pointers
|
|
||||||
# (C) 2006 Jelmer Vernooij <jelmer@samba.org>.
|
|
||||||
# Published under the GNU General Public License.
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 1 * 8;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util qw(test_samba4_ndr);
|
|
||||||
|
|
||||||
SKIP: {
|
|
||||||
skip "full pointers not supported yet", 8;
|
|
||||||
|
|
||||||
test_samba4_ndr("fullptr-push-dup",
|
|
||||||
'
|
|
||||||
[public] uint16 echo_TestFull([in,ptr] uint32 *x, [in,ptr] uint32 *y);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
uint32_t v = 13;
|
|
||||||
struct echo_TestFull r;
|
|
||||||
r.in.x = &v;
|
|
||||||
r.in.y = &v;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestFull(ndr, NDR_IN, &r))) {
|
|
||||||
fprintf(stderr, "push failed\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ndr->offset != 12) {
|
|
||||||
fprintf(stderr, "Offset(%d) != 12\n", ndr->offset);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ndr->data[0] != ndr->data[8] ||
|
|
||||||
ndr->data[1] != ndr->data[9] ||
|
|
||||||
ndr->data[2] != ndr->data[10] ||
|
|
||||||
ndr->data[3] != ndr->data[11]) {
|
|
||||||
fprintf(stderr, "Data incorrect\n");
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
');
|
|
||||||
}
|
|
|
@ -1,526 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# Simple tests for pidl's handling of ref pointers, based
|
|
||||||
# on tridge's ref_notes.txt
|
|
||||||
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>.
|
|
||||||
# Published under the GNU General Public License.
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 22 * 8;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util qw(test_samba4_ndr);
|
|
||||||
|
|
||||||
test_samba4_ndr("noptr-push",
|
|
||||||
' typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in] xstruct foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
uint16_t v = 13;
|
|
||||||
struct echo_TestRef r;
|
|
||||||
r.in.foo.x = v;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r))) {
|
|
||||||
fprintf(stderr, "push failed\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ndr->offset != 2) {
|
|
||||||
fprintf(stderr, "Offset(%d) != 2\n", ndr->offset);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ndr->data[0] != 13 || ndr->data[1] != 0) {
|
|
||||||
fprintf(stderr, "Data incorrect\n");
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("ptr-embedded-push",
|
|
||||||
' typedef struct {
|
|
||||||
uint16 *x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in] xstruct foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint16_t v = 13;
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
r.in.foo.x = &v;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 6)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
|
|
||||||
ndr->data[2] == 0 && ndr->data[3] == 0)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
if (ndr->data[4] != 13 || ndr->data[5] != 0)
|
|
||||||
return 4;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("ptr-embedded-push-null",
|
|
||||||
' typedef struct {
|
|
||||||
uint16 *x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in] xstruct foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
r.in.foo.x = NULL;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 4)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
|
|
||||||
ndr->data[2] != 0 || ndr->data[3] != 0)
|
|
||||||
return 3;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("refptr-embedded-push",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
[ref] uint16 *x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in] xstruct foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint16_t v = 13;
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
r.in.foo.x = &v;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 6)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
|
|
||||||
ndr->data[2] == 0 && ndr->data[3] == 0)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
if (ndr->data[4] != 13 || ndr->data[5] != 0)
|
|
||||||
return 4;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("refptr-embedded-push-null",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
[ref] uint16 *x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in] xstruct foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
r.in.foo.x = NULL;
|
|
||||||
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
/* Windows gives [client runtime error 0x6f4] */
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("ptr-top-push",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in] xstruct *foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
struct xstruct s;
|
|
||||||
s.x = 13;
|
|
||||||
r.in.foo = &s;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 2)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] != 13 || ndr->data[1] != 0)
|
|
||||||
return 3;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("ptr-top-push-null",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in] xstruct *foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
r.in.foo = NULL;
|
|
||||||
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Windows gives [client runtime error 0x6f4] */
|
|
||||||
');
|
|
||||||
|
|
||||||
|
|
||||||
test_samba4_ndr("refptr-top-push",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in,ref] xstruct *foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
struct xstruct s;
|
|
||||||
s.x = 13;
|
|
||||||
r.in.foo = &s;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 2)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] != 13 || ndr->data[1] != 0)
|
|
||||||
return 3;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("refptr-top-push-null",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in,ref] xstruct *foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
r.in.foo = NULL;
|
|
||||||
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Windows gives [client runtime error 0x6f4] */
|
|
||||||
');
|
|
||||||
|
|
||||||
|
|
||||||
test_samba4_ndr("uniqueptr-top-push",
|
|
||||||
' typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in,unique] xstruct *foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
struct xstruct s;
|
|
||||||
s.x = 13;
|
|
||||||
r.in.foo = &s;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 6)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
|
|
||||||
ndr->data[2] == 0 && ndr->data[3] == 0)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
if (ndr->data[4] != 13 || ndr->data[5] != 0)
|
|
||||||
return 4;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("uniqueptr-top-push-null",
|
|
||||||
' typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] uint16 echo_TestRef([in,unique] xstruct *foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
r.in.foo = NULL;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 4)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
|
|
||||||
ndr->data[2] != 0 || ndr->data[3] != 0)
|
|
||||||
return 3;
|
|
||||||
');
|
|
||||||
|
|
||||||
|
|
||||||
test_samba4_ndr("ptr-top-out-pull",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] void echo_TestRef([out] xstruct *foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t data[] = { 0x0D, 0x00 };
|
|
||||||
DATA_BLOB b = { data, 2 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
|
||||||
struct xstruct s;
|
|
||||||
struct echo_TestRef r;
|
|
||||||
|
|
||||||
r.out.foo = &s;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!r.out.foo)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (r.out.foo->x != 13)
|
|
||||||
return 3;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("ptr-top-out-pull-null",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] void echo_TestRef([out] xstruct *foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t data[] = { 0x0D, 0x00 };
|
|
||||||
DATA_BLOB b = { data, 2 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
|
|
||||||
r.out.foo = NULL;
|
|
||||||
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Windows gives [client runtime error 0x6f4] */
|
|
||||||
');
|
|
||||||
|
|
||||||
|
|
||||||
test_samba4_ndr("refptr-top-out-pull",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] void echo_TestRef([out,ref] xstruct *foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t data[] = { 0x0D, 0x00 };
|
|
||||||
DATA_BLOB b = { data, 2 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
|
||||||
struct xstruct s;
|
|
||||||
struct echo_TestRef r;
|
|
||||||
|
|
||||||
r.out.foo = &s;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!r.out.foo)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (r.out.foo->x != 13)
|
|
||||||
return 3;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("refptr-top-out-pull-null",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint16 x;
|
|
||||||
} xstruct;
|
|
||||||
|
|
||||||
[public] void echo_TestRef([out,ref] xstruct *foo);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t data[] = { 0x0D, 0x00 };
|
|
||||||
DATA_BLOB b = { data, 2 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
|
|
||||||
r.out.foo = NULL;
|
|
||||||
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Windows gives [client runtime error 0x6f4] */
|
|
||||||
');
|
|
||||||
|
|
||||||
|
|
||||||
test_samba4_ndr("ptr-top-push-double",
|
|
||||||
'
|
|
||||||
[public] void echo_TestRef([in] uint16 **foo);
|
|
||||||
',
|
|
||||||
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
uint16_t v = 13;
|
|
||||||
uint16_t *pv = &v;
|
|
||||||
r.in.foo = &pv;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 6)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
|
|
||||||
ndr->data[2] == 0 && ndr->data[3] == 0)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
if (ndr->data[4] != 0x0D || ndr->data[5] != 0x00)
|
|
||||||
return 4;
|
|
||||||
');
|
|
||||||
|
|
||||||
SKIP: {
|
|
||||||
skip "ptr-top-push-double-sndnull is known to fail", 8;
|
|
||||||
|
|
||||||
test_samba4_ndr("ptr-top-push-double-sndnull",
|
|
||||||
'
|
|
||||||
[public] void echo_TestRef([in] uint16 **foo);
|
|
||||||
',
|
|
||||||
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
uint16_t *pv = NULL;
|
|
||||||
r.in.foo = &pv;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 4)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
|
|
||||||
ndr->data[2] != 0 || ndr->data[3] != 0)
|
|
||||||
return 3;
|
|
||||||
');
|
|
||||||
}
|
|
||||||
|
|
||||||
test_samba4_ndr("ptr-top-push-double-fstnull",
|
|
||||||
'
|
|
||||||
[public] void echo_TestRef([in] uint16 **foo);
|
|
||||||
',
|
|
||||||
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
r.in.foo = NULL;
|
|
||||||
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Windows gives [client runtime error 0x6f4] */
|
|
||||||
|
|
||||||
');
|
|
||||||
|
|
||||||
|
|
||||||
test_samba4_ndr("refptr-top-push-double",
|
|
||||||
'
|
|
||||||
[public] void echo_TestRef([in,ref] uint16 **foo);
|
|
||||||
',
|
|
||||||
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
uint16_t v = 13;
|
|
||||||
uint16_t *pv = &v;
|
|
||||||
r.in.foo = &pv;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 6)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
|
|
||||||
ndr->data[2] == 0 && ndr->data[3] == 0)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
if (ndr->data[4] != 0x0D || ndr->data[5] != 0x00)
|
|
||||||
return 4;
|
|
||||||
');
|
|
||||||
|
|
||||||
SKIP: {
|
|
||||||
|
|
||||||
skip "refptr-top-push-double-sndnull is known to fail", 8;
|
|
||||||
|
|
||||||
test_samba4_ndr("refptr-top-push-double-sndnull",
|
|
||||||
'
|
|
||||||
[public] void echo_TestRef([in,ref] uint16 **foo);
|
|
||||||
',
|
|
||||||
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
uint16_t *pv = NULL;
|
|
||||||
r.in.foo = &pv;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 4)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
|
|
||||||
ndr->data[2] != 0 || ndr->data[3] != 0)
|
|
||||||
return 3;
|
|
||||||
');
|
|
||||||
}
|
|
||||||
|
|
||||||
test_samba4_ndr("refptr-top-push-double-fstnull",
|
|
||||||
'
|
|
||||||
[public] void echo_TestRef([in,ref] uint16 **foo);
|
|
||||||
',
|
|
||||||
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
r.in.foo = NULL;
|
|
||||||
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Windows gives [client runtime error 0x6f4] */
|
|
||||||
|
|
||||||
');
|
|
||||||
|
|
||||||
SKIP: {
|
|
||||||
skip "ignore-ptrs are not supported yet", 8;
|
|
||||||
test_samba4_ndr("ignore-ptr",
|
|
||||||
'
|
|
||||||
[public] void echo_TestRef([in,ignore] uint16 *foo, [in] uint16 *bar);
|
|
||||||
',
|
|
||||||
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct echo_TestRef r;
|
|
||||||
uint16_t v = 10;
|
|
||||||
r.in.foo = &v;
|
|
||||||
r.in.bar = &v;
|
|
||||||
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ndr->offset != 4)
|
|
||||||
return 2;
|
|
||||||
');
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# NDR represent_as() / transmit_as() tests
|
|
||||||
# (C) 2006 Jelmer Vernooij. Published under the GNU GPL
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 2 * 8;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util qw(test_samba4_ndr);
|
|
||||||
|
|
||||||
test_samba4_ndr('represent_as-simple',
|
|
||||||
'
|
|
||||||
void bla([in,represent_as(uint32)] uint8 x);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t expected[] = { 0x0D };
|
|
||||||
DATA_BLOB in_blob = { expected, 1 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&in_blob, NULL, NULL);
|
|
||||||
struct bla r;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (r.in.x != 13)
|
|
||||||
return 2;
|
|
||||||
',
|
|
||||||
'
|
|
||||||
enum ndr_err_code ndr_uint8_to_uint32(uint8_t from, uint32_t *to)
|
|
||||||
{
|
|
||||||
*to = from;
|
|
||||||
return NDR_ERR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ndr_err_code ndr_uint32_to_uint8(uint32_t from, uint8_t *to)
|
|
||||||
{
|
|
||||||
*to = from;
|
|
||||||
return NDR_ERR_SUCCESS;
|
|
||||||
}
|
|
||||||
'
|
|
||||||
);
|
|
||||||
|
|
||||||
test_samba4_ndr('transmit_as-simple',
|
|
||||||
'
|
|
||||||
void bla([in,transmit_as(uint32)] uint8 x);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t expected[] = { 0x0D };
|
|
||||||
DATA_BLOB in_blob = { expected, 1 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&in_blob, NULL, NULL);
|
|
||||||
struct bla r;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (r.in.x != 13)
|
|
||||||
return 2;
|
|
||||||
',
|
|
||||||
'
|
|
||||||
enum ndr_err_code ndr_uint8_to_uint32(uint8_t from, uint32_t *to)
|
|
||||||
{
|
|
||||||
*to = from;
|
|
||||||
return NDR_ERR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ndr_err_code ndr_uint32_to_uint8(uint32_t from, uint8_t *to)
|
|
||||||
{
|
|
||||||
*to = from;
|
|
||||||
return NDR_ERR_SUCCESS;
|
|
||||||
}
|
|
||||||
'
|
|
||||||
);
|
|
|
@ -1,28 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# Some simple tests for pidl
|
|
||||||
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
# Published under the GNU General Public License
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 8;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util qw(test_samba4_ndr);
|
|
||||||
|
|
||||||
test_samba4_ndr("simple", "void Test(); ",
|
|
||||||
"
|
|
||||||
uint8_t data[] = { 0x02 };
|
|
||||||
uint8_t result;
|
|
||||||
DATA_BLOB b;
|
|
||||||
struct ndr_pull *ndr;
|
|
||||||
|
|
||||||
b.data = data;
|
|
||||||
b.length = 1;
|
|
||||||
ndr = ndr_pull_init_blob(&b, mem_ctx, NULL);
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_uint8(ndr, NDR_SCALARS, &result)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (result != 0x02)
|
|
||||||
return 2;
|
|
||||||
");
|
|
|
@ -1,192 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# String tests for pidl
|
|
||||||
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
# Published under the GNU General Public License
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 6 * 8;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util qw(test_samba4_ndr);
|
|
||||||
|
|
||||||
test_samba4_ndr("string-pull-empty",
|
|
||||||
' [public] void TestString([in,flag(STR_ASCII|LIBNDR_FLAG_STR_SIZE4)] string data);',
|
|
||||||
'
|
|
||||||
uint8_t data[] = { 0x00, 0x00, 0x00, 0x00 };
|
|
||||||
DATA_BLOB b = { data, 4 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
|
||||||
struct TestString r;
|
|
||||||
r.in.data = NULL;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (r.in.data == NULL)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (r.in.data[0] != 0)
|
|
||||||
return 3;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("string-ascii-pull",
|
|
||||||
'
|
|
||||||
[public] void TestString([in,flag(STR_ASCII|LIBNDR_FLAG_STR_SIZE4)] string data);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t data[] = { 0x03, 0x00, 0x00, 0x00,
|
|
||||||
\'f\', \'o\', \'o\', 0 };
|
|
||||||
DATA_BLOB b = { data, 8 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
|
||||||
struct TestString r;
|
|
||||||
r.in.data = NULL;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (r.in.data == NULL)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (strncmp(r.in.data, "foo", 3) != 0)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
if (r.in.data[4] != 0)
|
|
||||||
return 4;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("string-wchar-fixed-array-01",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint32 l1;
|
|
||||||
[string,charset(UTF16)] uint16 str[6];
|
|
||||||
uint32 l2;
|
|
||||||
} TestStringStruct;
|
|
||||||
|
|
||||||
[public] void TestString([in,ref] TestStringStruct *str);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t data[] = { 0x01, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x04, 0x00, 0x00, 0x00,
|
|
||||||
\'f\', 0x00, \'o\', 0x00,
|
|
||||||
\'o\', 0x00, 0x00, 0x00,
|
|
||||||
0x02, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
DATA_BLOB b = { data, sizeof(data) };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
|
||||||
struct TestString r;
|
|
||||||
struct TestStringStruct str;
|
|
||||||
r.in.str = &str;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (r.in.str == NULL)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (r.in.str->l1 != 0x00000001)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
if (strncmp(str.str, "foo", 3) != 0)
|
|
||||||
return 4;
|
|
||||||
|
|
||||||
if (r.in.str->str[4] != 0)
|
|
||||||
return 5;
|
|
||||||
|
|
||||||
if (r.in.str->l2 != 0x00000002)
|
|
||||||
return 6;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("string-wchar-fixed-array-02",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint32 l1;
|
|
||||||
[string,charset(UTF16)] uint16 str[6];
|
|
||||||
uint32 l2;
|
|
||||||
} TestStringStruct;
|
|
||||||
|
|
||||||
[public] void TestString([in,ref] TestStringStruct *str);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t data[] = { 0x01, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x06, 0x00, 0x00, 0x00,
|
|
||||||
\'f\', 0x00, \'o\', 0x00,
|
|
||||||
\'o\', 0x00, \'b\', 0x00,
|
|
||||||
\'a\', 0x00, \'r\', 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x02, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
DATA_BLOB b = { data, sizeof(data) };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
|
||||||
struct TestString r;
|
|
||||||
struct TestStringStruct str;
|
|
||||||
r.in.str = &str;
|
|
||||||
|
|
||||||
/* the string terminator is wrong */
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr("string-wchar-fixed-array-03",
|
|
||||||
'
|
|
||||||
typedef struct {
|
|
||||||
uint32 l1;
|
|
||||||
[string,charset(UTF16)] uint16 str[6];
|
|
||||||
uint32 l2;
|
|
||||||
} TestStringStruct;
|
|
||||||
|
|
||||||
[public] void TestString([in,ref] TestStringStruct *str);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t data[] = { 0x01, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x07, 0x00, 0x00, 0x00,
|
|
||||||
\'f\', 0x00, \'o\', 0x00,
|
|
||||||
\'o\', 0x00, \'b\', 0x00,
|
|
||||||
\'a\', 0x00, \'r\', 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x02, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
DATA_BLOB b = { data, sizeof(data) };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
|
||||||
struct TestString r;
|
|
||||||
struct TestStringStruct str;
|
|
||||||
r.in.str = &str;
|
|
||||||
|
|
||||||
/* the length 0x07 is to large */
|
|
||||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
');
|
|
||||||
|
|
||||||
SKIP: {
|
|
||||||
skip "doesn't seem to work yet", 8;
|
|
||||||
|
|
||||||
test_samba4_ndr("string-out",
|
|
||||||
'
|
|
||||||
[public] void TestString([out,string,charset(UNIX)] uint8 **data);
|
|
||||||
',
|
|
||||||
'
|
|
||||||
uint8_t data[] = { 0x03, 0x00, 0x00, 0x00,
|
|
||||||
\'f\', \'o\', \'o\', 0 };
|
|
||||||
DATA_BLOB b = { data, 8 };
|
|
||||||
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
|
||||||
struct TestString r;
|
|
||||||
char *str = NULL;
|
|
||||||
r.out.data = &str;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (r.out.data == NULL)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (*r.out.data == NULL)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
if (strncmp(r.out.data, "foo", 3) != 0)
|
|
||||||
return 4;
|
|
||||||
|
|
||||||
if (r.out.data[4] != 0)
|
|
||||||
return 5;
|
|
||||||
');
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# Support for tagged types
|
|
||||||
# (C) 2005 Jelmer Vernooij. Published under the GNU GPL
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 3 * 8;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util qw(test_samba4_ndr);
|
|
||||||
|
|
||||||
test_samba4_ndr('struct-notypedef', '[public] struct bla { uint8 x; }; ',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct bla r;
|
|
||||||
uint8_t expected[] = { 0x0D };
|
|
||||||
DATA_BLOB expected_blob = { expected, 1 };
|
|
||||||
DATA_BLOB result_blob;
|
|
||||||
r.x = 13;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_STRUCT_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
result_blob = ndr_push_blob(ndr);
|
|
||||||
|
|
||||||
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
|
||||||
return 2;
|
|
||||||
');
|
|
||||||
|
|
||||||
test_samba4_ndr('struct-notypedef-used', '[public] struct bla { uint8 x; };
|
|
||||||
[public] void myfn([in] struct bla r); ',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct myfn fn;
|
|
||||||
uint8_t expected[] = { 0x0D };
|
|
||||||
DATA_BLOB expected_blob = { expected, 1 };
|
|
||||||
DATA_BLOB result_blob;
|
|
||||||
fn.in.r.x = 13;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_myfn(ndr, NDR_IN, &fn)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
result_blob = ndr_push_blob(ndr);
|
|
||||||
|
|
||||||
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
|
||||||
return 2;
|
|
||||||
');
|
|
||||||
|
|
||||||
|
|
||||||
test_samba4_ndr('struct-notypedef-embedded', 'struct bla { uint8 x; };
|
|
||||||
[public] struct myst { struct bla r; }; ',
|
|
||||||
'
|
|
||||||
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
|
||||||
struct myst st;
|
|
||||||
uint8_t expected[] = { 0x0D };
|
|
||||||
DATA_BLOB expected_blob = { expected, 1 };
|
|
||||||
DATA_BLOB result_blob;
|
|
||||||
st.r.x = 13;
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_STRUCT_myst(ndr, NDR_IN, &st)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
result_blob = ndr_push_blob(ndr);
|
|
||||||
|
|
||||||
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
|
||||||
return 2;
|
|
||||||
');
|
|
|
@ -1,243 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
# Some simple tests for pidls parsing routines
|
|
||||||
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
|
||||||
# Published under the GNU General Public License
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::More tests => 65 * 2 + 7;
|
|
||||||
use FindBin qw($RealBin);
|
|
||||||
use lib "$RealBin";
|
|
||||||
use Util qw(test_errors);
|
|
||||||
use Parse::Pidl::IDL;
|
|
||||||
use Parse::Pidl::NDR;
|
|
||||||
|
|
||||||
sub testok($$)
|
|
||||||
{
|
|
||||||
my ($name, $data) = @_;
|
|
||||||
|
|
||||||
test_errors("", sub {
|
|
||||||
my $pidl = Parse::Pidl::IDL::parse_string($data, "<$name>");
|
|
||||||
ok (defined($pidl), $name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sub testfail($$$)
|
|
||||||
{
|
|
||||||
my ($name, $data, $error) = @_;
|
|
||||||
|
|
||||||
test_errors($error, sub {
|
|
||||||
my $pidl = Parse::Pidl::IDL::parse_string($data, "<$name>");
|
|
||||||
|
|
||||||
ok ((not defined $pidl), $name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
testfail "unknowntag", "bla test {};",
|
|
||||||
"<unknowntag>:0: Syntax error near 'bla'\n";
|
|
||||||
testok "test1", "interface test { void Test(); }; ";
|
|
||||||
testok "voidtest", "interface test { int Testx(void); }; ";
|
|
||||||
testfail "voidtest", "interface test { Test(); }; ",
|
|
||||||
"<voidtest>:0: Syntax error near '('\n";
|
|
||||||
testok "argtest", "interface test { int Test(int a, long b, uint32 c); }; ";
|
|
||||||
testok "array1", "interface test { int Test(int a[]); };";
|
|
||||||
testok "array2", "interface test { int Test(int a[2]); };";
|
|
||||||
testok "array3", "interface test { int Test(int a[b]); };";
|
|
||||||
testfail "array4", "interface test { int Test(int[] a); };",
|
|
||||||
"<array4>:0: Syntax error near '['\n";
|
|
||||||
testok "ptr1", "interface test { int Test(int *a); };";
|
|
||||||
testok "ptr2", "interface test { int Test(int **a); };";
|
|
||||||
testok "ptr3", "interface test { int Test(int ***a); };";
|
|
||||||
testfail "empty1", "interface test { };", "<empty1>:0: Syntax error near '}'\n";
|
|
||||||
testfail "empty2", "", "";
|
|
||||||
testok "attr1", "[uuid(\"myuuid\"),attr] interface test { int Test(int ***a); };";
|
|
||||||
testok "attr2", "interface test { [public] int Test(); };";
|
|
||||||
testok "attr3", "[attr1] [attr2] interface test { [public] int Test(); };";
|
|
||||||
testok "multfn", "interface test { int test1(); int test2(); };";
|
|
||||||
testok "multif", "interface test { int test1(); }; interface test2 { int test2(); };";
|
|
||||||
testok "tdstruct1", "interface test { typedef struct { } foo; };";
|
|
||||||
testok "tdstruct2", "interface test { typedef struct { int a; } foo; };";
|
|
||||||
testok "tdstruct3", "interface test { typedef struct { int a; int b; } foo; };";
|
|
||||||
testfail "tdstruct4", "interface test { typedef struct { int a, int b; } foo; };",
|
|
||||||
"<tdstruct4>:0: Syntax error near ','\n";
|
|
||||||
testok "struct1", "interface test { struct x { }; };";
|
|
||||||
testok "struct2", "interface test { struct x { int a; }; };";
|
|
||||||
testok "struct3", "interface test { struct x { int a; int b; }; };";
|
|
||||||
testfail "struct4", "interface test { struct x { int a, int b; }; };",
|
|
||||||
"<struct4>:0: Syntax error near ','\n";
|
|
||||||
testfail "struct5", "interface test { struct { int a; } x; };",
|
|
||||||
"<struct5>:0: Syntax error near 'x'\n";
|
|
||||||
testok "tdunion1", "interface test { typedef union { } a; };";
|
|
||||||
testok "tdunion2", "interface test { typedef union { int a; } a; };";
|
|
||||||
testok "union1", "interface test { union a { }; };";
|
|
||||||
testok "union2", "interface test { union x { int a; }; };";
|
|
||||||
testfail "union3", "interface test { union { int a; } x; };",
|
|
||||||
"<union3>:0: Syntax error near 'x'\n";
|
|
||||||
testok "typedef1", "interface test { typedef int a; };";
|
|
||||||
testfail "typedef2", "interface test { typedef x; };",
|
|
||||||
"<typedef2>:0: Syntax error near ';'\n";
|
|
||||||
testok "tdenum1", "interface test { typedef enum { A=1, B=2, C} a; };";
|
|
||||||
testok "enum1", "interface test { enum a { A=1, B=2, C}; };";
|
|
||||||
testfail "enum2", "interface test { enum { A=1, B=2, C} a; };",
|
|
||||||
"<enum2>:0: Syntax error near 'a'\n";
|
|
||||||
testok "nested1", "interface test { struct x { struct { int a; } z; }; };";
|
|
||||||
testok "nested2", "interface test { struct x { struct y { int a; } z; }; };";
|
|
||||||
testok "bitmap1", "interface test { bitmap x { a=1 }; };";
|
|
||||||
testok "unsigned", "interface test { struct x { unsigned short y; }; };";
|
|
||||||
testok "struct-property", "interface test { [public] struct x { short y; }; };";
|
|
||||||
testok "signed", "interface test { struct x { signed short y; }; };";
|
|
||||||
testok "declarg", "interface test { void test(struct { int x; } a); };";
|
|
||||||
testok "structarg", "interface test { void test(struct a b); };";
|
|
||||||
testfail "structargmissing", "interface test { void test(struct a); };",
|
|
||||||
"<structargmissing>:0: Syntax error near ')'\n";
|
|
||||||
testok "structqual", "interface test { struct x { struct y z; }; };";
|
|
||||||
testok "unionqual", "interface test { struct x { union y z; }; };";
|
|
||||||
testok "enumqual", "interface test { struct x { enum y z; }; };";
|
|
||||||
testok "bitmapqual", "interface test { struct x { bitmap y z; }; };";
|
|
||||||
testok "emptystructdecl", "interface test { struct x; };";
|
|
||||||
testok "emptyenumdecl", "interface test { enum x; };";
|
|
||||||
testok "emptytdstructdecl", "interface test { typedef struct x y; };";
|
|
||||||
testok "import", "import \"foo.idl\";";
|
|
||||||
testok "include", "include \"foo.h\";";
|
|
||||||
testfail "import-noquotes", "import foo.idl;",
|
|
||||||
"<import-noquotes>:0: Syntax error near 'foo'\n";
|
|
||||||
testfail "include-noquotes", "include foo.idl;",
|
|
||||||
"<include-noquotes>:0: Syntax error near 'foo'\n";
|
|
||||||
testok "importlib", "importlib \"foo.idl\";";
|
|
||||||
testfail "import-nosemicolon", "import \"foo.idl\"",
|
|
||||||
"<import-nosemicolon>:0: Syntax error near 'foo.idl'\n";
|
|
||||||
testok "import-multiple", "import \"foo.idl\", \"bar.idl\";";
|
|
||||||
testok "include-multiple", "include \"foo.idl\", \"bar.idl\";";
|
|
||||||
testok "empty-struct", "interface test { struct foo { }; }";
|
|
||||||
testok "typedef-double", "interface test { typedef struct foo { } foo; }";
|
|
||||||
testok "cpp-quote", "cpp_quote(\"bla\")";
|
|
||||||
|
|
||||||
my $x = Parse::Pidl::IDL::parse_string("interface foo { struct x {}; }", "<foo>");
|
|
||||||
|
|
||||||
is_deeply($x, [ {
|
|
||||||
'TYPE' => 'INTERFACE',
|
|
||||||
'NAME' => 'foo',
|
|
||||||
'DATA' => [ {
|
|
||||||
'TYPE' => 'STRUCT',
|
|
||||||
'NAME' => 'x',
|
|
||||||
'ELEMENTS' => [],
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
} ],
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
}]);
|
|
||||||
|
|
||||||
$x = Parse::Pidl::IDL::parse_string("interface foo { struct x; }", "<foo>");
|
|
||||||
is_deeply($x, [ {
|
|
||||||
'TYPE' => 'INTERFACE',
|
|
||||||
'NAME' => 'foo',
|
|
||||||
'DATA' => [ {
|
|
||||||
'TYPE' => 'STRUCT',
|
|
||||||
'NAME' => 'x',
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
} ],
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
}]);
|
|
||||||
|
|
||||||
$x = Parse::Pidl::IDL::parse_string("cpp_quote(\"foobar\")", "<quote>");
|
|
||||||
is_deeply($x, [ {
|
|
||||||
'TYPE' => 'CPP_QUOTE',
|
|
||||||
'DATA' => '"foobar"',
|
|
||||||
'FILE' => '<quote>',
|
|
||||||
'LINE' => 0
|
|
||||||
}]);
|
|
||||||
|
|
||||||
# A typedef of a struct without body
|
|
||||||
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef struct x y; }", "<foo>");
|
|
||||||
|
|
||||||
is_deeply($x, [ {
|
|
||||||
'TYPE' => 'INTERFACE',
|
|
||||||
'NAME' => 'foo',
|
|
||||||
'DATA' => [ {
|
|
||||||
'TYPE' => 'TYPEDEF',
|
|
||||||
'NAME' => 'y',
|
|
||||||
'POINTERS' => 0,
|
|
||||||
'DATA' => {
|
|
||||||
'TYPE' => 'STRUCT',
|
|
||||||
'NAME' => 'x',
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0,
|
|
||||||
},
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0,
|
|
||||||
} ],
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
}]);
|
|
||||||
|
|
||||||
# A typedef of a struct with empty body
|
|
||||||
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef struct {} y; }", "<foo>");
|
|
||||||
|
|
||||||
is_deeply($x, [ {
|
|
||||||
'TYPE' => 'INTERFACE',
|
|
||||||
'NAME' => 'foo',
|
|
||||||
'DATA' => [ {
|
|
||||||
'TYPE' => 'TYPEDEF',
|
|
||||||
'NAME' => 'y',
|
|
||||||
'POINTERS' => 0,
|
|
||||||
'DATA' => {
|
|
||||||
'TYPE' => 'STRUCT',
|
|
||||||
'ELEMENTS' => [],
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
},
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
} ],
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
}]);
|
|
||||||
|
|
||||||
# A typedef of a bitmap with no body
|
|
||||||
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef bitmap x y; }", "<foo>");
|
|
||||||
|
|
||||||
is_deeply($x, [ {
|
|
||||||
'TYPE' => 'INTERFACE',
|
|
||||||
'NAME' => 'foo',
|
|
||||||
'DATA' => [ {
|
|
||||||
'TYPE' => 'TYPEDEF',
|
|
||||||
'NAME' => 'y',
|
|
||||||
'POINTERS' => 0,
|
|
||||||
'DATA' => {
|
|
||||||
'TYPE' => 'BITMAP',
|
|
||||||
'NAME' => 'x',
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
},
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
} ],
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
}]);
|
|
||||||
|
|
||||||
|
|
||||||
# A typedef of a union with no body
|
|
||||||
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef union x y; }", "<foo>");
|
|
||||||
|
|
||||||
is_deeply($x, [ {
|
|
||||||
'TYPE' => 'INTERFACE',
|
|
||||||
'NAME' => 'foo',
|
|
||||||
'DATA' => [ {
|
|
||||||
'TYPE' => 'TYPEDEF',
|
|
||||||
'NAME' => 'y',
|
|
||||||
'POINTERS' => 0,
|
|
||||||
'DATA' => {
|
|
||||||
'TYPE' => 'UNION',
|
|
||||||
'NAME' => 'x',
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
},
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
} ],
|
|
||||||
'FILE' => '<foo>',
|
|
||||||
'LINE' => 0
|
|
||||||
}]);
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue