[Pkg-cli-libs-commits] [dbus-sharp-legacy] 01/02: Imported Upstream version 0.7.0
Jo Shields
directhex at moszumanska.debian.org
Thu Mar 13 00:22:37 UTC 2014
This is an automated email from the git hooks/post-receive script.
directhex pushed a commit to branch master
in repository dbus-sharp-legacy.
commit a5669f9da968700f5859f87030de6406ef5b88d3
Author: Jo Shields <directhex at apebox.org>
Date: Thu Mar 13 00:15:43 2014 +0000
Imported Upstream version 0.7.0
---
AUTHORS | 1 +
COPYING | 21 +
ChangeLog | 0
INSTALL | 365 ++++
Makefile.am | 22 +
Makefile.in | 722 ++++++++
NEWS | 0
README | 44 +
aclocal.m4 | 835 +++++++++
configure | 3786 +++++++++++++++++++++++++++++++++++++++
configure.ac | 59 +
dbus-sharp-1.0.pc.in | 11 +
dbus-sharp.snk | Bin 0 -> 596 bytes
examples/Makefile.am | 6 +
examples/Makefile.in | 314 ++++
examples/Notifications.cs | 31 +
examples/Test.cs | 49 +
examples/TestExportInterface.cs | 305 ++++
examples/TestNotifications.cs | 39 +
examples/TestSample.cs | 54 +
install-sh | 520 ++++++
missing | 376 ++++
src/Address.cs | 188 ++
src/AssemblyInfo.cs.in | 27 +
src/Authentication.cs | 538 ++++++
src/Bus.cs | 179 ++
src/BusObject.cs | 402 +++++
src/Connection.cs | 507 ++++++
src/DBus.cs | 98 +
src/DProxy.cs | 79 +
src/ExportObject.cs | 199 ++
src/Introspection.cs | 316 ++++
src/Makefile.am | 68 +
src/Makefile.in | 382 ++++
src/Mapper.cs | 389 ++++
src/MatchRule.cs | 319 ++++
src/Message.cs | 499 ++++++
src/MessageFilter.cs | 58 +
src/MessageReader.cs | 494 +++++
src/MessageWriter.cs | 570 ++++++
src/PendingCall.cs | 111 ++
src/Protocol.cs | 525 ++++++
src/Signature.cs | 897 ++++++++++
src/SocketTransport.cs | 70 +
src/Transport.cs | 383 ++++
src/TypeImplementer.cs | 909 ++++++++++
src/TypeRental.cs | 504 ++++++
src/Unix.cs | 484 +++++
src/UnixNativeTransport.cs | 180 ++
src/UnixTransport.cs | 29 +
src/Wrapper.cs | 158 ++
src/dbus-sharp.dll.config | 3 +
tools/Introspect.cs | 35 +
tools/Makefile.am | 3 +
tools/Makefile.in | 311 ++++
tools/Monitor.cs | 239 +++
56 files changed, 17713 insertions(+)
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..d6b9e4c
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Alp Toker <alp at atoker.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..0dfc23e
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,21 @@
+Copyright 2006 Alp Toker <alp at atoker.com>
+Copyright 2010 Other Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..7d1c323
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,365 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved. This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+ Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package. Some packages provide this
+`INSTALL' file but do not implement all of the features documented
+below. The lack of an optional feature in a given package is not
+necessarily a bug. More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+ The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package, generally using the just-built uninstalled binaries.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation. When installing into a prefix owned by root, it is
+ recommended that the package be configured and built as a regular
+ user, and only the `make install' phase executed with root
+ privileges.
+
+ 5. Optionally, type `make installcheck' to repeat any self-tests, but
+ this time using the binaries in their final installed location.
+ This target does not install anything. Running this target as a
+ regular user, particularly if the prior `make install' required
+ root privileges, verifies that the installation completed
+ correctly.
+
+ 6. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 7. Often, you can also type `make uninstall' to remove the installed
+ files again. In practice, not all packages have tested that
+ uninstallation works correctly, even though it is required by the
+ GNU Coding Standards.
+
+ 8. Some packages, particularly those that use Automake, provide `make
+ distcheck', which can by used by developers to test that all other
+ targets like `make install' and `make uninstall' work correctly.
+ This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'. This
+is known as a "VPATH" build.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them. In general, the
+default for these options is expressed in terms of `${prefix}', so that
+specifying just `--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+ The most portable way to affect installation locations is to pass the
+correct locations to `configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+`make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+ The first method involves providing an override variable for each
+affected directory. For example, `make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+`${prefix}'. Any directories that were specified during `configure',
+but not in terms of `${prefix}', must each be overridden at install
+time for the entire installation to be relocated. The approach of
+makefile variable overrides for each directory variable is required by
+the GNU Coding Standards, and ideally causes no recompilation.
+However, some platforms have known limitations with the semantics of
+shared libraries that end up requiring recompilation when using this
+method, particularly noticeable in packages that use GNU Libtool.
+
+ The second method involves providing the `DESTDIR' variable. For
+example, `make install DESTDIR=/alternate/directory' will prepend
+`/alternate/directory' before all installation names. The approach of
+`DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters. On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of `${prefix}'
+at `configure' time.
+
+Optional Features
+=================
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+ Some packages offer the ability to configure how verbose the
+execution of `make' will be. For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with `make V=0'.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file. The option `-nodtk' can be used as
+a workaround. If GNU CC is not installed, it is therefore recommended
+to try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+ On Solaris, don't put `/usr/ucb' early in your `PATH'. This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+ On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+ Print a summary of the options unique to this package's
+ `configure', and exit. The `short' variant lists options used
+ only in the top level, while the `recursive' variant lists options
+ also present in any nested packages.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+ Use DIR as the installation prefix. *note Installation Names::
+ for more details, including other options available for fine-tuning
+ the installation locations.
+
+`--no-create'
+`-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..f4f4f01
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,22 @@
+SUBDIRS = src tools examples
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = dbus-sharp-1.0.pc
+
+EXTRA_DIST = \
+ dbus-sharp-1.0.pc.in \
+ dbus-sharp.snk
+
+DISTCLEANFILES = \
+ dbus-sharp-1.0.pc
+
+MAINTAINERCLEANFILES = \
+ INSTALL \
+ Makefile.in \
+ aclocal.m4 \
+ config.guess \
+ config.sub \
+ configure \
+ install-sh \
+ missing
+
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..d2b5c93
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,722 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/dbus-sharp-1.0.pc.in \
+ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
+ install-sh missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES = dbus-sharp-1.0.pc
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(pkgconfigdir)"
+DATA = $(pkgconfig_DATA)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir dist dist-all distcheck
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d "$(distdir)" \
+ || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr "$(distdir)"; }; }
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+API_VERSION = @API_VERSION@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+GACUTIL = @GACUTIL@
+GMCS = @GMCS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MONO_CFLAGS = @MONO_CFLAGS@
+MONO_LIBS = @MONO_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+am__leading_dot = @am__leading_dot@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = src tools examples
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = dbus-sharp-1.0.pc
+EXTRA_DIST = \
+ dbus-sharp-1.0.pc.in \
+ dbus-sharp.snk
+
+DISTCLEANFILES = \
+ dbus-sharp-1.0.pc
+
+MAINTAINERCLEANFILES = \
+ INSTALL \
+ Makefile.in \
+ aclocal.m4 \
+ config.guess \
+ config.sub \
+ configure \
+ install-sh \
+ missing
+
+all: all-recursive
+
+.SUFFIXES:
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+dbus-sharp-1.0.pc: $(top_builddir)/config.status $(srcdir)/dbus-sharp-1.0.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+install-pkgconfigDATA: $(pkgconfig_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
+ @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+ done
+
+uninstall-pkgconfigDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d "$(distdir)" || mkdir "$(distdir)"
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -test -n "$(am__skip_mode_fix)" \
+ || find "$(distdir)" -type d ! -perm -755 \
+ -exec chmod u+rwx,go+rx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-xz: distdir
+ tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.xz*) \
+ xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ test -d $(distdir)/_build || exit 0; \
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && am__cwd=`pwd` \
+ && $(am__cd) $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+ && cd "$$am__cwd" \
+ || exit 1
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @$(am__cd) '$(distuninstallcheck_dir)' \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(DATA)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(pkgconfigdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-pkgconfigDATA
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-pkgconfigDATA
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am am--refresh check check-am clean clean-generic \
+ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
+ dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \
+ distclean distclean-generic distclean-tags distcleancheck \
+ distdir distuninstallcheck dvi dvi-am html html-am info \
+ info-am install install-am install-data install-data-am \
+ install-dvi install-dvi-am install-exec install-exec-am \
+ install-html install-html-am install-info install-info-am \
+ install-man install-pdf install-pdf-am install-pkgconfigDATA \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-pkgconfigDATA
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644
index 0000000..066e2ea
--- /dev/null
+++ b/README
@@ -0,0 +1,44 @@
+D-Bus for .NET
+==============
+
+This is a fork of ndesk-dbus, which is a C# implementation of D-Bus. It's
+often referred to as "managed D-Bus" to avoid confusion with existing
+bindings (which wrap libdbus).
+
+See http://mono.github.com/dbus-sharp/ for our fork
+ - Tarball download: http://github.com/mono/dbus-sharp/downloads
+ - GitHub repository: http://www.github.com/mono/dbus-sharp
+ - Reporting bugs: http://github.com/mono/dbus-sharp/issues
+
+See http://www.ndesk.org/DBusSharp for Alp Toker's original project
+
+D-Bus is an inter-process communication framework that lets applications
+interface with the system event bus as well as allowing them to talk to
+one another in a peer-to-peer configuration.
+
+See http://www.freedesktop.org/wiki/Software/dbus for general
+information on the D-Bus IPC mechanism.
+
+This software is under active development but is already used by a wide
+range of applications for tasks as simple as maintaining a single
+instance of the GUI to whole instant messaging frameworks and hardware
+detection APIs.
+
+It provides a tested, high-performance bridge to and from all systems
+that are exposed via D-Bus, regardless of programming language, UI
+toolkit or license. The source code is MIT X11 licensed (Free
+Software/Open Source), allowing integration into other projects with
+very few restrictions.
+
+The code was written by Alp Toker <alp at atoker.com> and others, and is
+maintained by the dbus-sharp team.
+
+It is a clean-room implementation based on the D-Bus Specification
+Version 0.11 and study of the wire protocol of existing tools.
+
+It aims for compatibility with Mono and Microsoft .NET frameworks
+supporting the 2.0 profile. Backward compatibility with 1.0 will not be
+a consideration.
+
+--
+Alp Toker <alp at atoker.com> and others
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..e6daac9
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,835 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.67],,
+[m4_warning([this file was generated for autoconf 2.67.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
+#
+# Copyright © 2004 Scott James Remnant <scott at netsplit.com>.
+#
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_default([$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ AC_MSG_RESULT([no])
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+ ])
+elif test $pkg_failed = untried; then
+ AC_MSG_RESULT([no])
+ m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])dnl
+ ])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ $3
+fi[]dnl
+])# PKG_CHECK_MODULES
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.11.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless `enable' is passed literally.
+# For symmetry, `disable' may be passed as well. Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+ [enable], [m4_define([am_maintainer_other], [disable])],
+ [disable], [m4_define([am_maintainer_other], [enable])],
+ [m4_define([am_maintainer_other], [enable])
+ m4_warn([syntax], [unexpected argument to AM@&t at _MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
+ dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+ AC_ARG_ENABLE([maintainer-mode],
+[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer],
+ [USE_MAINTAINER_MODE=$enableval],
+ [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+ AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+ AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+ MAINT=$MAINTAINER_MODE_TRUE
+ AC_SUBST([MAINT])dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
diff --git a/configure b/configure
new file mode 100755
index 0000000..4d6c178
--- /dev/null
+++ b/configure
@@ -0,0 +1,3786 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.67.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf at gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="src/DBus.cs"
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+GACUTIL
+GMCS
+MONO_LIBS
+MONO_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+VERSION
+API_VERSION
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_maintainer_mode
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+MONO_CFLAGS
+MONO_LIBS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer
+
+Some influential environment variables:
+ PKG_CONFIG path to pkg-config utility
+ PKG_CONFIG_PATH
+ directories to add to pkg-config's search path
+ PKG_CONFIG_LIBDIR
+ path overriding pkg-config's built-in search path
+ MONO_CFLAGS C compiler flags for MONO, overriding pkg-config
+ MONO_LIBS linker flags for MONO, overriding pkg-config
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.67
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.67. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+API_VERSION=1.0
+#VERSION=$API_VERSION.0
+VERSION=0.7.0
+
+
+
+
+am__api_version='1.11'
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+ if test "${ac_cv_path_mkdir+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+ done
+IFS=$as_save_IFS
+
+fi
+
+ test -d ./--version && rmdir ./--version
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE=dbus-sharp
+ VERSION=$VERSION
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+ # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+ enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+ USE_MAINTAINER_MODE=no
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINTAINER_MODE_TRUE=
+ MAINTAINER_MODE_FALSE='#'
+else
+ MAINTAINER_MODE_TRUE='#'
+ MAINTAINER_MODE_FALSE=
+fi
+
+ MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+
+
+# Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "x$PKG_CONFIG" = "xno"; then
+ as_fn_error $? "You need to install pkg-config" "$LINENO" 5
+fi
+
+
+MONO_REQ_VERSION=1.1.13
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+ ac_pt_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_pt_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKG_CONFIG=$ac_pt_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=0.9.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ PKG_CONFIG=""
+ fi
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MONO" >&5
+$as_echo_n "checking for MONO... " >&6; }
+
+if test -n "$MONO_CFLAGS"; then
+ pkg_cv_MONO_CFLAGS="$MONO_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"mono >= \$MONO_REQ_VERSION\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "mono >= $MONO_REQ_VERSION") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_MONO_CFLAGS=`$PKG_CONFIG --cflags "mono >= $MONO_REQ_VERSION" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$MONO_LIBS"; then
+ pkg_cv_MONO_LIBS="$MONO_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"mono >= \$MONO_REQ_VERSION\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "mono >= $MONO_REQ_VERSION") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_MONO_LIBS=`$PKG_CONFIG --libs "mono >= $MONO_REQ_VERSION" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ MONO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "mono >= $MONO_REQ_VERSION" 2>&1`
+ else
+ MONO_PKG_ERRORS=`$PKG_CONFIG --print-errors "mono >= $MONO_REQ_VERSION" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$MONO_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (mono >= $MONO_REQ_VERSION) were not met:
+
+$MONO_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables MONO_CFLAGS
+and MONO_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables MONO_CFLAGS
+and MONO_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ MONO_CFLAGS=$pkg_cv_MONO_CFLAGS
+ MONO_LIBS=$pkg_cv_MONO_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+# Extract the first word of "gmcs", so it can be a program name with args.
+set dummy gmcs; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_GMCS+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $GMCS in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_GMCS="$GMCS" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_GMCS="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_GMCS" && ac_cv_path_GMCS="no"
+ ;;
+esac
+fi
+GMCS=$ac_cv_path_GMCS
+if test -n "$GMCS"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMCS" >&5
+$as_echo "$GMCS" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "x$GMCS" = "xno"; then
+ as_fn_error $? "You need to install gmcs" "$LINENO" 5
+fi
+
+
+# Extract the first word of "gacutil", so it can be a program name with args.
+set dummy gacutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_GACUTIL+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $GACUTIL in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_GACUTIL="$GACUTIL" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_GACUTIL="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_GACUTIL" && ac_cv_path_GACUTIL="no"
+ ;;
+esac
+fi
+GACUTIL=$ac_cv_path_GACUTIL
+if test -n "$GACUTIL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GACUTIL" >&5
+$as_echo "$GACUTIL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "x$GACUTIL" = "xno"; then
+ as_fn_error $? "You need to install gacutil" "$LINENO" 5
+fi
+
+
+required_assemblies="Mono.Posix"
+
+for asm in $required_assemblies; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $asm.dll" >&5
+$as_echo_n "checking for $asm.dll... " >&6; }
+ if test -n "`$GACUTIL /l $asm.dll | grep ^$asm.dll`"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+ as_fn_error $? "missing required assembly in the GAC: $asm.dll" "$LINENO" 5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+ fi
+done
+
+ac_config_files="$ac_config_files Makefile dbus-sharp-1.0.pc src/AssemblyInfo.cs src/Makefile tools/Makefile examples/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+ as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.67. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.67,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "dbus-sharp-1.0.pc") CONFIG_FILES="$CONFIG_FILES dbus-sharp-1.0.pc" ;;
+ "src/AssemblyInfo.cs") CONFIG_FILES="$CONFIG_FILES src/AssemblyInfo.cs" ;;
+ "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+ "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
+ "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out" && rm -f "$tmp/out";;
+ *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..e589e2b
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,59 @@
+AC_INIT(src/DBus.cs)
+
+AC_PREREQ(2.13)
+
+API_VERSION=1.0
+#VERSION=$API_VERSION.0
+VERSION=0.7.0
+
+AC_SUBST(API_VERSION)
+AC_SUBST(VERSION)
+
+AM_INIT_AUTOMAKE(dbus-sharp, $VERSION)
+
+AM_MAINTAINER_MODE
+
+AC_PROG_INSTALL
+
+AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+if test "x$PKG_CONFIG" = "xno"; then
+ AC_MSG_ERROR([You need to install pkg-config])
+fi
+AC_SUBST(PKG_CONFIG)
+
+MONO_REQ_VERSION=1.1.13
+PKG_CHECK_MODULES(MONO, mono >= $MONO_REQ_VERSION)
+
+AC_PATH_PROG(GMCS, gmcs, no)
+if test "x$GMCS" = "xno"; then
+ AC_MSG_ERROR([You need to install gmcs])
+fi
+AC_SUBST(GMCS)
+
+AC_PATH_PROG(GACUTIL, gacutil, no)
+if test "x$GACUTIL" = "xno"; then
+ AC_MSG_ERROR([You need to install gacutil])
+fi
+AC_SUBST(GACUTIL)
+
+required_assemblies="Mono.Posix"
+
+for asm in $required_assemblies; do
+ AC_MSG_CHECKING([for $asm.dll])
+ if test -n "`$GACUTIL /l $asm.dll | grep ^$asm.dll`"; then
+ AC_MSG_RESULT([not found])
+ AC_MSG_ERROR([missing required assembly in the GAC: $asm.dll])
+ else
+ AC_MSG_RESULT([found])
+ fi
+done
+
+AC_OUTPUT([
+Makefile
+dbus-sharp-1.0.pc
+src/AssemblyInfo.cs
+src/Makefile
+tools/Makefile
+examples/Makefile
+])
+
diff --git a/dbus-sharp-1.0.pc.in b/dbus-sharp-1.0.pc.in
new file mode 100644
index 0000000..7e1b657
--- /dev/null
+++ b/dbus-sharp-1.0.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+datadir=${prefix}/share
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+session_bus_services_dir=${datadir}/dbus-1/services
+
+Name: Managed DBus
+Description: Managed D-Bus IPC protocol library and CLR binding
+Version: @VERSION@
+URL: http://mono.github.com/dbus-sharp/
+Libs: -r:${libdir}/mono/@PACKAGE at -@API_VERSION@/dbus-sharp.dll
diff --git a/dbus-sharp.snk b/dbus-sharp.snk
new file mode 100644
index 0000000..fddb426
Binary files /dev/null and b/dbus-sharp.snk differ
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..b0e4a39
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,6 @@
+EXTRA_DIST = \
+ Test.cs \
+ TestExportInterface.cs \
+ Notifications.cs \
+ TestNotifications.cs \
+ TestSample.cs
diff --git a/examples/Makefile.in b/examples/Makefile.in
new file mode 100644
index 0000000..c2d15f5
--- /dev/null
+++ b/examples/Makefile.in
@@ -0,0 +1,314 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = examples
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+API_VERSION = @API_VERSION@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+GACUTIL = @GACUTIL@
+GMCS = @GMCS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MONO_CFLAGS = @MONO_CFLAGS@
+MONO_LIBS = @MONO_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+am__leading_dot = @am__leading_dot@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ Test.cs \
+ TestExportInterface.cs \
+ Notifications.cs \
+ TestNotifications.cs \
+ TestSample.cs
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu examples/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/examples/Notifications.cs b/examples/Notifications.cs
new file mode 100644
index 0000000..b57bb80
--- /dev/null
+++ b/examples/Notifications.cs
@@ -0,0 +1,31 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+
+using DBus;
+using org.freedesktop.DBus;
+
+// Hand-written interfaces for bootstrapping
+
+namespace org.freedesktop
+{
+ public struct ServerInformation
+ {
+ public string Name;
+ public string Vendor;
+ public string Version;
+ public string SpecVersion;
+ }
+
+ [Interface ("org.freedesktop.Notifications")]
+ public interface Notifications : Introspectable, Properties
+ {
+ ServerInformation GetServerInformation ();
+ string[] GetCapabilities ();
+ void CloseNotification (uint id);
+ uint Notify (string app_name, uint id, string icon, string summary, string body, string[] actions, IDictionary<string,object> hints, int timeout);
+ }
+}
diff --git a/examples/Test.cs b/examples/Test.cs
new file mode 100644
index 0000000..93e5233
--- /dev/null
+++ b/examples/Test.cs
@@ -0,0 +1,49 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using DBus;
+using org.freedesktop.DBus;
+
+public class ManagedDBusTest
+{
+ public static void Main (string[] args)
+ {
+ Connection conn;
+
+ if (args.Length == 0)
+ conn = Bus.Session;
+ else {
+ if (args[0] == "--session")
+ conn = Bus.Session;
+ else if (args[0] == "--system")
+ conn = Bus.System;
+ else
+ conn = Connection.Open (args[0]);
+ }
+
+ ObjectPath opath = new ObjectPath ("/org/freedesktop/DBus");
+ string name = "org.freedesktop.DBus";
+
+ IBus bus = conn.GetObject<IBus> (name, opath);
+
+ bus.NameAcquired += delegate (string acquired_name) {
+ Console.WriteLine ("NameAcquired: " + acquired_name);
+ };
+
+ Console.WriteLine ();
+ string xmlData = bus.Introspect ();
+ Console.WriteLine ("xmlData: " + xmlData);
+
+ Console.WriteLine ();
+ foreach (string n in bus.ListNames ())
+ Console.WriteLine (n);
+
+ Console.WriteLine ();
+ foreach (string n in bus.ListNames ())
+ Console.WriteLine ("Name " + n + " has owner: " + bus.NameHasOwner (n));
+
+ Console.WriteLine ();
+ }
+}
diff --git a/examples/TestExportInterface.cs b/examples/TestExportInterface.cs
new file mode 100644
index 0000000..f46132d
--- /dev/null
+++ b/examples/TestExportInterface.cs
@@ -0,0 +1,305 @@
+// Copyright 2007 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using DBus;
+using org.freedesktop.DBus;
+
+public class ManagedDBusTestExport
+{
+ public static void Main ()
+ {
+ Bus bus = Bus.Session;
+
+ string bus_name = "org.ndesk.test";
+ ObjectPath path = new ObjectPath ("/org/ndesk/test");
+
+ IDemoOne demo;
+
+ if (bus.RequestName (bus_name) == RequestNameReply.PrimaryOwner) {
+ //create a new instance of the object to be exported
+ demo = new Demo ();
+ bus.Register (path, demo);
+
+ //run the main loop
+ while (true)
+ bus.Iterate ();
+ } else {
+ //import a remote to a local proxy
+ //demo = bus.GetObject<IDemo> (bus_name, path);
+ demo = bus.GetObject<DemoProx> (bus_name, path);
+ }
+
+ Console.WriteLine ();
+ demo.SomeEvent += HandleSomeEventA;
+ demo.FireOffSomeEvent ();
+
+ Console.WriteLine ();
+ demo.SomeEvent -= HandleSomeEventA;
+ demo.FireOffSomeEvent ();
+
+ Console.WriteLine ();
+ demo.SomeEvent += delegate (string arg1, object arg2, double arg3, MyTuple mt) {Console.WriteLine ("SomeEvent handler: " + arg1 + ", " + arg2 + ", " + arg3 + ", " + mt.A + ", " + mt.B);};
+ demo.SomeEvent += delegate (string arg1, object arg2, double arg3, MyTuple mt) {Console.WriteLine ("SomeEvent handler two: " + arg1 + ", " + arg2 + ", " + arg3 + ", " + mt.A + ", " + mt.B);};
+ demo.FireOffSomeEvent ();
+
+ Console.WriteLine ();
+
+ Console.WriteLine (demo.GetSomeVariant ());
+
+ Console.WriteLine ();
+
+ demo.Say2 ("demo.Say2");
+ ((IDemoTwo)demo).Say2 ("((IDemoTwo)demo).Say2");
+
+ demo.SayEnum (DemoEnum.Bar, DemoEnum.Foo);
+
+ uint n;
+ string ostr;
+ demo.WithOutParameters (out n, "21", out ostr);
+ Console.WriteLine ("n: " + n);
+ Console.WriteLine ("ostr: " + ostr);
+
+ uint[] a1, a2, a3;
+ demo.WithOutParameters2 (out a1, out a2, out a3);
+ Console.WriteLine ("oparam2: " + a2[1]);
+
+ uint[] @contacts = new uint[] { 2 };
+ IDictionary<uint,SimplePresence> presence;
+ demo.GetPresences (contacts, out presence);
+ Console.WriteLine ("pres: " + presence[2].Status);
+
+ MyTuple2 cpx = new MyTuple2 ();
+ cpx.A = "a";
+ cpx.B = "b";
+ cpx.C = new Dictionary<int,MyTuple> ();
+ cpx.C[3] = new MyTuple("foo", "bar");
+ object cpxRet = demo.ComplexAsVariant (cpx, 12);
+ MyTuple2 mt2ret = (MyTuple2)Convert.ChangeType (cpxRet, typeof (MyTuple2));
+ Console.WriteLine ("mt2ret.C[3].B " + mt2ret.C[3].B);
+
+ /*
+ IDemoOne[] objs = demo.GetObjArr ();
+ foreach (IDemoOne obj in objs)
+ obj.Say ("Some obj");
+ */
+
+ Console.WriteLine("SomeProp: " + demo.SomeProp);
+ demo.SomeProp = 321;
+
+ DemoProx demoProx = demo as DemoProx;
+ if (demoProx != null)
+ demoProx.SayRepeatedly(5, "Repetition");
+
+ demo.ThrowSomeException ();
+ }
+
+ public static void HandleSomeEventA (string arg1, object arg2, double arg3, MyTuple mt)
+ {
+ Console.WriteLine ("SomeEvent handler A: " + arg1 + ", " + arg2 + ", " + arg3 + ", " + mt.A + ", " + mt.B);
+ }
+
+ public static void HandleSomeEventB (string arg1, object arg2, double arg3, MyTuple mt)
+ {
+ Console.WriteLine ("SomeEvent handler B: " + arg1 + ", " + arg2 + ", " + arg3 + ", " + mt.A + ", " + mt.B);
+ }
+}
+
+[Interface ("org.ndesk.test")]
+public interface IDemoOne
+{
+ event SomeEventHandler SomeEvent;
+ void FireOffSomeEvent ();
+ void Say (object var);
+ void SayEnum (DemoEnum a, DemoEnum b);
+ void Say2 (string str);
+ object GetSomeVariant ();
+ void ThrowSomeException ();
+ void WithOutParameters (out uint n, string str, out string ostr);
+ void WithOutParameters2 (out uint[] a1, out uint[] a2, out uint[] a3);
+ void GetPresences (uint[] @contacts, out IDictionary<uint,SimplePresence> @presence);
+ object ComplexAsVariant (object v, int num);
+
+ IDemoOne[] GetEmptyObjArr ();
+ IDemoOne[] GetObjArr ();
+ int SomeProp { get; set; }
+}
+
+[Interface ("org.ndesk.test2")]
+public interface IDemoTwo
+{
+ int Say (string str);
+ void Say2 (string str);
+}
+
+public interface IDemo : IDemoOne, IDemoTwo
+{
+}
+
+public abstract class DemoProx : DemoBase
+{
+ public virtual void SayRepeatedly (int count, string str)
+ {
+ for (int i = 0 ; i != count ; i++)
+ Say2(str);
+ }
+}
+
+public class Demo : DemoBase
+{
+ public override void Say2 (string str)
+ {
+ Console.WriteLine ("Subclassed IDemoOne.Say2: " + str);
+ }
+}
+
+public class DemoBase : IDemo
+{
+ public event SomeEventHandler SomeEvent;
+
+ public void Say (object var)
+ {
+ Console.WriteLine ("variant: " + var);
+ }
+
+ public int Say (string str)
+ {
+ Console.WriteLine ("string: " + str);
+ return str.Length;
+ }
+
+ public void SayEnum (DemoEnum a, DemoEnum b)
+ {
+ Console.WriteLine ("SayEnum: " + a + ", " + b);
+ }
+
+ public virtual void Say2 (string str)
+ {
+ Console.WriteLine ("IDemoOne.Say2: " + str);
+ }
+
+ void IDemoTwo.Say2 (string str)
+ {
+ Console.WriteLine ("IDemoTwo.Say2: " + str);
+ }
+
+ public void FireOffSomeEvent ()
+ {
+ Console.WriteLine ("Asked to fire off SomeEvent");
+
+ MyTuple mt;
+ mt.A = "a";
+ mt.B = "b";
+
+ if (SomeEvent != null) {
+ SomeEvent ("some string", 21, 19.84, mt);
+ Console.WriteLine ("Fired off SomeEvent");
+ }
+ }
+
+ public object GetSomeVariant ()
+ {
+ Console.WriteLine ("GetSomeVariant()");
+
+ return new byte[0];
+ }
+
+ public void ThrowSomeException ()
+ {
+ throw new Exception ("Some exception");
+ }
+
+ public void WithOutParameters (out uint n, string str, out string ostr)
+ {
+ n = UInt32.Parse (str);
+ ostr = "." + str + ".";
+ }
+
+ public void WithOutParameters2 (out uint[] a1, out uint[] a2, out uint[] a3)
+ {
+ a1 = new uint[] { };
+ a2 = new uint[] { 21, 23, 16 };
+ a3 = new uint[] { 21, 23 };
+ }
+
+ public void GetPresences (uint[] @contacts, out IDictionary<uint,SimplePresence> @presence)
+ {
+ Dictionary<uint,SimplePresence> presences = new Dictionary<uint,SimplePresence>();
+ presences[2] = new SimplePresence { Type = ConnectionPresenceType.Offline, Status = "offline", StatusMessage = "" };
+ presence = presences;
+ }
+
+ public object ComplexAsVariant (object v, int num)
+ {
+ Console.WriteLine ("v: " + v);
+ Console.WriteLine ("v null? " + (v == null));
+
+ MyTuple2 mt2 = (MyTuple2)Convert.ChangeType (v, typeof (MyTuple2));
+ Console.WriteLine ("mt2.C[3].B " + mt2.C[3].B);
+ Console.WriteLine ("num: " + num);
+
+ return v;
+ }
+
+ public IDemoOne[] GetEmptyObjArr ()
+ {
+ return new Demo[] {};
+ }
+
+ public IDemoOne[] GetObjArr ()
+ {
+ return new IDemoOne[] {this};
+ }
+
+ public int SomeProp
+ {
+ get {
+ return 123;
+ } set {
+ Console.WriteLine ("Set SomeProp: " + value);
+ }
+ }
+}
+
+public enum DemoEnum : byte
+{
+ Foo,
+ Bar,
+}
+
+
+public struct MyTuple
+{
+ public MyTuple (string a, string b)
+ {
+ A = a;
+ B = b;
+ }
+
+ public string A;
+ public string B;
+}
+
+public struct MyTuple2
+{
+ public string A;
+ public string B;
+ public IDictionary<int,MyTuple> C;
+}
+
+public delegate void SomeEventHandler (string arg1, object arg2, double arg3, MyTuple mt);
+
+public enum ConnectionPresenceType : uint
+{
+ Unset = 0, Offline = 1, Available = 2, Away = 3, ExtendedAway = 4, Hidden = 5, Busy = 6, Unknown = 7, Error = 8,
+}
+
+public struct SimplePresence
+{
+ public ConnectionPresenceType Type;
+ public string Status;
+ public string StatusMessage;
+}
+
diff --git a/examples/TestNotifications.cs b/examples/TestNotifications.cs
new file mode 100644
index 0000000..e44681d
--- /dev/null
+++ b/examples/TestNotifications.cs
@@ -0,0 +1,39 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+
+using DBus;
+using org.freedesktop;
+using org.freedesktop.DBus;
+
+// Just for fun. A more complete implementation would cover the API at:
+// http://www.galago-project.org/docs/api/libnotify/notification_8h.html
+public class ManagedDBusTestNotifications
+{
+ public static void Main ()
+ {
+ Bus bus = Bus.Session;
+
+ Notifications nf = bus.GetObject<Notifications> ("org.freedesktop.Notifications", new ObjectPath ("/org/freedesktop/Notifications"));
+
+ Console.WriteLine ();
+ Console.WriteLine ("Capabilities:");
+ foreach (string cap in nf.GetCapabilities ())
+ Console.WriteLine ("\t" + cap);
+
+ ServerInformation si = nf.GetServerInformation ();
+
+ //TODO: ability to pass null
+ Dictionary<string,object> hints = new Dictionary<string,object> ();
+
+ string message = String.Format ("Brought to you using {0} {1} (implementing spec version {2}) from {3}.", si.Name, si.Version, si.SpecVersion, si.Vendor);
+
+ uint handle = nf.Notify ("D-Bus# Notifications Demo", 0, "warning", "Managed D-Bus# says 'Hello'!", message, new string[0], hints, 0);
+
+ Console.WriteLine ();
+ Console.WriteLine ("Got handle " + handle);
+ }
+}
diff --git a/examples/TestSample.cs b/examples/TestSample.cs
new file mode 100644
index 0000000..0b6c555
--- /dev/null
+++ b/examples/TestSample.cs
@@ -0,0 +1,54 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using DBus;
+using org.freedesktop.DBus;
+
+public class ManagedDBusTestSample
+{
+ public static void Main ()
+ {
+ Bus bus = Bus.Session;
+
+ SampleInterface sample = bus.GetObject<SampleInterface> ("com.example.SampleService", new ObjectPath ("/SomeObject"));
+
+ Console.WriteLine ();
+ string xmlData = sample.Introspect ();
+ Console.WriteLine ("xmlData: " + xmlData);
+
+ //object obj = sample.HelloWorld ("Hello from example-client.py!");
+ string[] vals = sample.HelloWorld ("Hello from example-client.py!");
+ foreach (string val in vals)
+ Console.WriteLine (val);
+
+ Console.WriteLine ();
+ MyTuple tup = sample.GetTuple ();
+ Console.WriteLine (tup.A);
+ Console.WriteLine (tup.B);
+
+ Console.WriteLine ();
+ IDictionary<string,string> dict = sample.GetDict ();
+ foreach (KeyValuePair<string,string> pair in dict)
+ Console.WriteLine (pair.Key + ": " + pair.Value);
+ }
+}
+
+[Interface ("com.example.SampleInterface")]
+public interface SampleInterface : Introspectable
+{
+ //void HelloWorld (object hello_message);
+ //object HelloWorld (object hello_message);
+ string[] HelloWorld (object hello_message);
+ MyTuple GetTuple ();
+ IDictionary<string,string> GetDict ();
+}
+
+//(ss)
+public struct MyTuple
+{
+ public string A;
+ public string B;
+}
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..6781b98
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,520 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2009-04-28.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/missing b/missing
new file mode 100755
index 0000000..28055d2
--- /dev/null
+++ b/missing
@@ -0,0 +1,376 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+# 2008, 2009 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
+
+# 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 2, 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/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ autom4te touch the output file, or create a stub one
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
+\`g' are ignored when checking the name.
+
+Send bug reports to <bug-automake at gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# normalize program name to check for.
+program=`echo "$1" | sed '
+ s/^gnu-//; t
+ s/^gnu//; t
+ s/^g//; t'`
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program). This is about non-GNU programs, so use $1 not
+# $program.
+case $1 in
+ lex*|yacc*)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar*)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $program in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case $f in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te*)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison*|yacc*)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f y.tab.h; then
+ echo >y.tab.h
+ fi
+ if test ! -f y.tab.c; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex*|flex*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f lex.yy.c; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit $?
+ fi
+ ;;
+
+ makeinfo*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '
+ /^@setfilename/{
+ s/.* \([^ ]*\) *$/\1/
+ p
+ q
+ }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar*)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case $firstarg in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case $firstarg in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/src/Address.cs b/src/Address.cs
new file mode 100644
index 0000000..a73c1bb
--- /dev/null
+++ b/src/Address.cs
@@ -0,0 +1,188 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Text;
+using System.Collections.Generic;
+
+namespace DBus
+{
+ // Subclass obsolete BadAddressException to avoid ABI break
+#pragma warning disable 0618
+ //public class InvalidAddressException : Exception
+ public class InvalidAddressException : BadAddressException
+ {
+ public InvalidAddressException (string reason) : base (reason) {}
+ }
+#pragma warning restore 0618
+
+ [Obsolete ("Use InvalidAddressException")]
+ public class BadAddressException : Exception
+ {
+ public BadAddressException (string reason) : base (reason) {}
+ }
+
+ class AddressEntry
+ {
+ public string Method;
+ public readonly IDictionary<string,string> Properties = new Dictionary<string,string> ();
+ public UUID GUID = UUID.Zero;
+
+ public override string ToString ()
+ {
+ StringBuilder sb = new StringBuilder ();
+ sb.Append (Method);
+ sb.Append (':');
+
+ bool first = true;
+ foreach (KeyValuePair<string,string> prop in Properties) {
+ if (first)
+ first = false;
+ else
+ sb.Append (',');
+
+ sb.Append (prop.Key);
+ sb.Append ('=');
+ sb.Append (Escape (prop.Value));
+ }
+
+ if (GUID != UUID.Zero) {
+ if (Properties.Count != 0)
+ sb.Append (',');
+ sb.Append ("guid");
+ sb.Append ('=');
+ sb.Append (GUID.ToString ());
+ }
+
+ return sb.ToString ();
+ }
+
+ static string Escape (string str)
+ {
+ if (str == null)
+ return String.Empty;
+
+ StringBuilder sb = new StringBuilder ();
+ int len = str.Length;
+
+ for (int i = 0 ; i != len ; i++) {
+ char c = str[i];
+
+ //everything other than the optionally escaped chars _must_ be escaped
+ if (Char.IsLetterOrDigit (c) || c == '-' || c == '_' || c == '/' || c == '\\' || c == '.')
+ sb.Append (c);
+ else
+ sb.Append (Uri.HexEscape (c));
+ }
+
+ return sb.ToString ();
+ }
+
+ static string Unescape (string str)
+ {
+ if (str == null)
+ return String.Empty;
+
+ StringBuilder sb = new StringBuilder ();
+ int len = str.Length;
+ int i = 0;
+ while (i != len) {
+ if (Uri.IsHexEncoding (str, i))
+ sb.Append (Uri.HexUnescape (str, ref i));
+ else
+ sb.Append (str[i++]);
+ }
+
+ return sb.ToString ();
+ }
+
+
+ public static AddressEntry Parse (string s)
+ {
+ AddressEntry entry = new AddressEntry ();
+
+ string[] parts = s.Split (':');
+
+ if (parts.Length < 2)
+ throw new InvalidAddressException ("No colon found");
+ if (parts.Length > 2)
+ throw new InvalidAddressException ("Too many colons found");
+
+ entry.Method = parts[0];
+
+ foreach (string propStr in parts[1].Split (',')) {
+ parts = propStr.Split ('=');
+
+ if (parts.Length < 2)
+ throw new InvalidAddressException ("No equals sign found");
+ if (parts.Length > 2)
+ throw new InvalidAddressException ("Too many equals signs found");
+
+ if (parts[0] == "guid") {
+ try {
+ entry.GUID = UUID.Parse (parts[1]);
+ } catch {
+ throw new InvalidAddressException ("Invalid guid specified");
+ }
+ continue;
+ }
+
+ entry.Properties[parts[0]] = Unescape (parts[1]);
+ }
+
+ return entry;
+ }
+ }
+
+ static class Address
+ {
+ //(unix:(path|abstract)=.*,guid=.*|tcp:host=.*(,port=.*)?);? ...
+ public static AddressEntry[] Parse (string addresses)
+ {
+ if (addresses == null)
+ throw new ArgumentNullException (addresses);
+
+ List<AddressEntry> entries = new List<AddressEntry> ();
+
+ foreach (string entryStr in addresses.Split (';'))
+ entries.Add (AddressEntry.Parse (entryStr));
+
+ return entries.ToArray ();
+ }
+
+ const string SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket";
+ public static string System
+ {
+ get {
+ string addr = Environment.GetEnvironmentVariable ("DBUS_SYSTEM_BUS_ADDRESS");
+
+ if (String.IsNullOrEmpty (addr))
+ addr = SYSTEM_BUS_ADDRESS;
+
+ return addr;
+ }
+ }
+
+ public static string Session
+ {
+ get {
+ return Environment.GetEnvironmentVariable ("DBUS_SESSION_BUS_ADDRESS");
+ }
+ }
+
+ public static string Starter
+ {
+ get {
+ return Environment.GetEnvironmentVariable ("DBUS_STARTER_ADDRESS");
+ }
+ }
+
+ public static string StarterBusType
+ {
+ get {
+ return Environment.GetEnvironmentVariable ("DBUS_STARTER_BUS_TYPE");
+ }
+ }
+ }
+}
diff --git a/src/AssemblyInfo.cs.in b/src/AssemblyInfo.cs.in
new file mode 100644
index 0000000..42f9ec0
--- /dev/null
+++ b/src/AssemblyInfo.cs.in
@@ -0,0 +1,27 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyFileVersion("@VERSION@")]
+[assembly: AssemblyInformationalVersion("@VERSION@")]
+[assembly: AssemblyVersion("@API_VERSION@")]
+[assembly: AssemblyTitle ("dbus-sharp")]
+[assembly: AssemblyDescription ("D-Bus IPC protocol library and CLR binding")]
+[assembly: AssemblyCopyright ("Copyright (C) Alp Toker and others")]
+
+#if STRONG_NAME
+[assembly: InternalsVisibleTo ("dbus-sharp-tests, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")]
+[assembly: InternalsVisibleTo ("dbus-monitor, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")]
+[assembly: InternalsVisibleTo ("dbus-daemon, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")]
+[assembly: InternalsVisibleTo ("dbus-sharp-glib, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")]
+[assembly: InternalsVisibleTo ("dbus-sharp-proxies, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")]
+#else
+[assembly: InternalsVisibleTo ("dbus-sharp-tests")]
+[assembly: InternalsVisibleTo ("dbus-monitor")]
+[assembly: InternalsVisibleTo ("dbus-daemon")]
+[assembly: InternalsVisibleTo ("dbus-sharp-glib")]
+[assembly: InternalsVisibleTo ("dbus-sharp-proxies")]
+#endif
diff --git a/src/Authentication.cs b/src/Authentication.cs
new file mode 100644
index 0000000..cd23945
--- /dev/null
+++ b/src/Authentication.cs
@@ -0,0 +1,538 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Globalization;
+
+namespace DBus
+{
+ using Authentication;
+
+ //using System.Runtime.InteropServices;
+ //[StructLayout (LayoutKind.Sequential)]
+ unsafe struct UUID
+ {
+ private int a, b, c, d;
+ const int ByteLength = 16;
+
+ public static readonly UUID Zero = new UUID ();
+
+ public static bool operator == (UUID a, UUID b)
+ {
+ if (a.a == b.a && a.b == b.b && a.c == b.c && a.d == b.d)
+ return true;
+ else
+ return false;
+ }
+
+ public static bool operator != (UUID a, UUID b)
+ {
+ return !(a == b);
+ }
+
+ public override bool Equals (object o)
+ {
+ if (o == null)
+ return false;
+
+ if (!(o is UUID))
+ return false;
+
+ return this == (UUID)o;
+ }
+
+ public override int GetHashCode ()
+ {
+ return a ^ b ^ c ^ d;
+ }
+
+ public override string ToString ()
+ {
+ StringBuilder sb = new StringBuilder (ByteLength * 2);
+
+ fixed (int* p = &a) {
+ byte* bp = (byte*)p;
+ for (int i = 0 ; i != ByteLength ; i++)
+ sb.Append (bp[i].ToString ("x2", CultureInfo.InvariantCulture));
+ }
+
+ return sb.ToString ();
+ }
+
+ public static UUID Parse (string hex)
+ {
+ if (hex.Length != ByteLength * 2)
+ throw new Exception ("Cannot parse UUID/GUID of invalid length");
+
+ UUID id = new UUID ();
+
+ byte* result = (byte*)&id.a;
+ int n = 0, i = 0;
+ while (n < ByteLength) {
+ result[n] = (byte)(Sasl.FromHexChar (hex[i++]) << 4);
+ result[n++] += Sasl.FromHexChar (hex[i++]);
+ }
+
+ return id;
+ }
+
+ static Random rand = new Random ();
+ static byte[] buf = new byte[12];
+ public static UUID Generate (DateTime timestamp)
+ {
+ UUID id = new UUID ();
+
+ lock (buf) {
+ rand.NextBytes (buf);
+ fixed (byte* bp = &buf[0]) {
+ int* p = (int*)bp;
+ id.a = p[0];
+ id.b = p[1];
+ id.c = p[2];
+ }
+ }
+
+ //id.d is assigned to by Timestamp
+ id.Timestamp = timestamp;
+
+ return id;
+ }
+
+ public static UUID Generate ()
+ {
+ return Generate (DateTime.Now);
+ }
+
+ public uint UnixTimestamp
+ {
+ get {
+ uint unixTime;
+
+ fixed (int* ip = &d) {
+ if (BitConverter.IsLittleEndian) {
+ byte* p = (byte*)ip;
+ byte* bp = (byte*)&unixTime;
+ bp[0] = p[3];
+ bp[1] = p[2];
+ bp[2] = p[1];
+ bp[3] = p[0];
+ } else {
+ unixTime = *(uint*)ip;
+ }
+ }
+
+ return unixTime;
+ } set {
+ uint unixTime = value;
+
+ fixed (int* ip = &d) {
+ if (BitConverter.IsLittleEndian) {
+ byte* p = (byte*)&unixTime;
+ byte* bp = (byte*)ip;
+ bp[0] = p[3];
+ bp[1] = p[2];
+ bp[2] = p[1];
+ bp[3] = p[0];
+ } else {
+ *(uint*)ip = unixTime;
+ }
+ }
+ }
+ }
+
+ public DateTime Timestamp
+ {
+ get {
+ return Sasl.UnixToDateTime (UnixTimestamp);
+ } set {
+ UnixTimestamp = (uint)Sasl.DateTimeToUnix (value);
+ }
+ }
+ }
+}
+
+namespace DBus.Authentication
+{
+ enum ClientState
+ {
+ WaitingForData,
+ WaitingForOK,
+ WaitingForReject,
+ }
+
+ enum ServerState
+ {
+ WaitingForAuth,
+ WaitingForData,
+ WaitingForBegin,
+ }
+
+ class AuthCommand
+ {
+ /*
+ public AuthCommand (string value)
+ {
+ //this.Value = value;
+ this.Value = value.Trim ();
+ }
+ */
+
+
+ public AuthCommand (string value)
+ {
+ //this.Value = value;
+ this.Value = value.Trim ();
+ Args.AddRange (Value.Split (' '));
+ }
+
+ readonly List<string> Args = new List<string> ();
+
+ public string this[int index]
+ {
+ get {
+ if (index >= Args.Count)
+ return String.Empty;
+ return Args[index];
+ }
+ }
+
+ /*
+ public AuthCommand (string value, params string[] args)
+ {
+ if (args.Length == 0)
+ this.Value = value;
+ else
+ this.Value = value + " " + String.Join (" ", args);
+ }
+ */
+
+ public readonly string Value;
+ }
+
+ class SaslPeer : IEnumerable<AuthCommand>
+ {
+ //public Connection conn;
+ public SaslPeer Peer;
+
+ public Stream stream = null;
+ public bool UseConsole = false;
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
+ {
+ return GetEnumerator ();
+ }
+
+ internal bool isFinalRead = false;
+
+ public virtual IEnumerator<AuthCommand> GetEnumerator ()
+ {
+ // Read the mandatory null credentials byte
+ /*
+ if (!UseConsole)
+ if (conn.Transport.Stream.ReadByte () != 0)
+ yield break;
+ */
+
+ TextReader sr;
+ sr = UseConsole ? Console.In : new StreamReader (stream, Encoding.ASCII);
+
+ while (true) {
+ string ln;
+ bool isEnd = false;
+ if (!UseConsole && isFinalRead) {
+ StringBuilder sb = new StringBuilder ();
+
+ while (true) {
+ //MemoryStream ms = new MemoryStream ();
+ // TODO: Use char instead? Check for -1?
+ int a = stream.ReadByte ();
+
+ if (a == -1) {
+ isEnd = true;
+ break;
+ }
+
+ if (a == '\r') {
+ int b = stream.ReadByte ();
+ if (b != '\n')
+ throw new Exception ();
+ break;
+ }
+
+ sb.Append ((char)a);
+ }
+
+ ln = sb.ToString ();
+ //isFinalRead = false;
+ } else {
+ ln = sr.ReadLine ();
+ }
+
+ //if (isEnd && ln == string.Empty)
+ // yield break;
+ if (ln == null)
+ yield break;
+ if (ln != String.Empty)
+ yield return new AuthCommand (ln);
+ if (isEnd)
+ yield break;
+ }
+ }
+
+ public bool Authenticate ()
+ {
+ return Run (this);
+ }
+
+ public bool AuthenticateSelf ()
+ {
+ //IEnumerator<AuthCommand> a = Peer.GetEnumerator ();
+ IEnumerator<AuthCommand> b = GetEnumerator ();
+ //bool ret = b.MoveNext ();
+ while (b.MoveNext ()) {
+ if (b.Current.Value == "BEGIN")
+ return true;
+ }
+ return false;
+ }
+
+ public virtual bool Run (IEnumerable<AuthCommand> commands)
+ {
+ TextWriter sw;
+ sw = UseConsole ? Console.Out : new StreamWriter (stream, Encoding.ASCII);
+ if (!UseConsole)
+ sw.NewLine = "\r\n";
+
+ foreach (AuthCommand command in commands) {
+ if (command == null) {
+ // Disconnect here?
+ return false;
+ }
+ sw.WriteLine (command.Value);
+ sw.Flush ();
+ }
+
+ return true;
+ }
+ }
+
+ class SaslClient : SaslPeer
+ {
+ public string Identity = String.Empty;
+
+ //static Regex rejectedRegex = new Regex (@"^REJECTED(\s+(\w+))*$");
+
+ // This enables simple support for multiple AUTH schemes
+ enum AuthMech
+ {
+ External,
+ Anonymous,
+ None,
+ }
+
+ public override IEnumerator<AuthCommand> GetEnumerator ()
+ {
+ IEnumerator<AuthCommand> replies = Peer.GetEnumerator ();
+
+ AuthMech currMech = AuthMech.External;
+
+ while (true) {
+ Peer.isFinalRead = false;
+
+ if (currMech == AuthMech.External) {
+ string str = Identity;
+ byte[] bs = Encoding.ASCII.GetBytes (str);
+ string initialData = Sasl.ToHex (bs);
+ yield return new AuthCommand ("AUTH EXTERNAL " + initialData);
+ currMech = AuthMech.Anonymous;
+ } else if (currMech == AuthMech.Anonymous) {
+ yield return new AuthCommand ("AUTH ANONYMOUS");
+ currMech = AuthMech.None;
+ } else {
+ throw new Exception ("Authentication failure");
+ }
+
+ Peer.isFinalRead = true;
+
+ AuthCommand reply;
+ if (!replies.MoveNext ())
+ yield break;
+ reply = replies.Current;
+
+ if (reply[0] == "REJECTED") {
+ continue;
+ }
+
+ /*
+ Match m = rejectedRegex.Match (reply.Value);
+ if (m.Success) {
+ string[] mechanisms = m.Groups[1].Value.Split (' ');
+ //yield return new AuthCommand ("CANCEL");
+ continue;
+ }
+ */
+
+ if (reply[0] != "OK") {
+ yield return new AuthCommand ("ERROR");
+ continue;
+ }
+
+ if (reply[1] == String.Empty)
+ ActualId = UUID.Zero;
+ else
+ ActualId = UUID.Parse (reply[1]);
+
+ yield return new AuthCommand ("BEGIN");
+ yield break;
+ }
+
+ }
+
+ public UUID ActualId = UUID.Zero;
+ }
+
+ class SaslServer : SaslPeer
+ {
+ //public int MaxFailures = 10;
+ public UUID Guid = UUID.Zero;
+
+ public long uid = 0;
+
+ static Regex authRegex = new Regex (@"^AUTH\s+(\w+)(?:\s+(.*))?$");
+ static string[] supportedMechanisms = {"EXTERNAL"};
+
+ public override IEnumerator<AuthCommand> GetEnumerator ()
+ {
+ IEnumerator<AuthCommand> replies = Peer.GetEnumerator ();
+
+ while (true) {
+ Peer.isFinalRead = false;
+
+ AuthCommand reply;
+ if (!replies.MoveNext ()) {
+ yield return null;
+ yield break;
+ //continue;
+ }
+ reply = replies.Current;
+
+ Match m = authRegex.Match (reply.Value);
+ if (!m.Success) {
+ yield return new AuthCommand ("ERROR");
+ continue;
+ }
+
+ string mechanism = m.Groups[1].Value;
+ string initialResponse = m.Groups[2].Value;
+
+ if (mechanism == "EXTERNAL") {
+ try {
+ byte[] bs = Sasl.FromHex (initialResponse);
+ string authStr = Encoding.ASCII.GetString (bs);
+ uid = UInt32.Parse (authStr);
+ } catch {
+ uid = 0;
+ }
+ //return RunExternal (Run (), initialResponse);
+ } else {
+ yield return new AuthCommand ("REJECTED " + String.Join (" ", supportedMechanisms));
+ continue;
+ }
+
+ if (Guid == UUID.Zero)
+ yield return new AuthCommand ("OK");
+ else
+ yield return new AuthCommand ("OK " + Guid.ToString ());
+
+ Peer.isFinalRead = true;
+
+ if (!replies.MoveNext ()) {
+ /*
+ yield break;
+ continue;
+ */
+ yield return null;
+ yield break;
+ }
+
+ reply = replies.Current;
+ if (reply.Value != "BEGIN") {
+ yield return new AuthCommand ("ERROR");
+ continue;
+ }
+
+ yield break;
+ }
+ }
+ }
+
+ static class Sasl
+ {
+ //From Mono.Unix.Native.NativeConvert
+ //should these methods use long or (u)int?
+ public static DateTime UnixToDateTime (long time)
+ {
+ DateTime LocalUnixEpoch = new DateTime (1970, 1, 1);
+ TimeSpan LocalUtcOffset = TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.UtcNow);
+ return LocalUnixEpoch.AddSeconds ((double) time + LocalUtcOffset.TotalSeconds);
+ }
+
+ public static long DateTimeToUnix (DateTime time)
+ {
+ DateTime LocalUnixEpoch = new DateTime (1970, 1, 1);
+ TimeSpan LocalUtcOffset = TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.UtcNow);
+ TimeSpan unixTime = time.Subtract (LocalUnixEpoch) - LocalUtcOffset;
+
+ return (long) unixTime.TotalSeconds;
+ }
+
+ //From Mono.Security.Cryptography
+ //Modified to output lowercase hex
+ static public string ToHex (byte[] input)
+ {
+ if (input == null)
+ return null;
+
+ StringBuilder sb = new StringBuilder (input.Length * 2);
+ foreach (byte b in input) {
+ sb.Append (b.ToString ("x2", CultureInfo.InvariantCulture));
+ }
+ return sb.ToString ();
+ }
+
+ //From Mono.Security.Cryptography
+ static public byte FromHexChar (char c)
+ {
+ if ((c >= 'a') && (c <= 'f'))
+ return (byte) (c - 'a' + 10);
+ if ((c >= 'A') && (c <= 'F'))
+ return (byte) (c - 'A' + 10);
+ if ((c >= '0') && (c <= '9'))
+ return (byte) (c - '0');
+ throw new ArgumentException ("Invalid hex char");
+ }
+
+ //From Mono.Security.Cryptography
+ static public byte[] FromHex (string hex)
+ {
+ if (hex == null)
+ return null;
+ if ((hex.Length & 0x1) == 0x1)
+ throw new ArgumentException ("Length must be a multiple of 2");
+
+ byte[] result = new byte [hex.Length >> 1];
+ int n = 0;
+ int i = 0;
+ while (n < result.Length) {
+ result [n] = (byte) (FromHexChar (hex [i++]) << 4);
+ result [n++] += FromHexChar (hex [i++]);
+ }
+ return result;
+ }
+ }
+}
diff --git a/src/Bus.cs b/src/Bus.cs
new file mode 100644
index 0000000..0b44b10
--- /dev/null
+++ b/src/Bus.cs
@@ -0,0 +1,179 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using org.freedesktop.DBus;
+
+namespace DBus
+{
+ public sealed class Bus : Connection
+ {
+ static Bus systemBus = null;
+ public static Bus System
+ {
+ get {
+ if (systemBus == null) {
+ try {
+ if (Address.StarterBusType == "system")
+ systemBus = Starter;
+ else
+ systemBus = Bus.Open (Address.System);
+ } catch (Exception e) {
+ throw new Exception ("Unable to open the system message bus.", e);
+ }
+ }
+
+ return systemBus;
+ }
+ }
+
+ static Bus sessionBus = null;
+ public static Bus Session
+ {
+ get {
+ if (sessionBus == null) {
+ try {
+ if (Address.StarterBusType == "session")
+ sessionBus = Starter;
+ else
+ sessionBus = Bus.Open (Address.Session);
+ } catch (Exception e) {
+ throw new Exception ("Unable to open the session message bus.", e);
+ }
+ }
+
+ return sessionBus;
+ }
+ }
+
+ //TODO: parsing of starter bus type, or maybe do this another way
+ static Bus starterBus = null;
+ public static Bus Starter
+ {
+ get {
+ if (starterBus == null) {
+ try {
+ starterBus = Bus.Open (Address.Starter);
+ } catch (Exception e) {
+ throw new Exception ("Unable to open the starter message bus.", e);
+ }
+ }
+
+ return starterBus;
+ }
+ }
+
+ //public static readonly Bus Session = null;
+
+ //TODO: use the guid, not the whole address string
+ //TODO: consider what happens when a connection has been closed
+ static Dictionary<string,Bus> buses = new Dictionary<string,Bus> ();
+
+ //public static Connection Open (string address)
+ public static new Bus Open (string address)
+ {
+ if (address == null)
+ throw new ArgumentNullException ("address");
+
+ Bus bus;
+ if (buses.TryGetValue (address, out bus))
+ return bus;
+
+ bus = new Bus (address);
+ buses[address] = bus;
+
+ return bus;
+ }
+
+ IBus bus;
+
+ static readonly string DBusName = "org.freedesktop.DBus";
+ static readonly ObjectPath DBusPath = new ObjectPath ("/org/freedesktop/DBus");
+
+ public Bus (string address) : base (address)
+ {
+ bus = GetObject<IBus> (DBusName, DBusPath);
+
+ /*
+ bus.NameAcquired += delegate (string acquired_name) {
+ Console.WriteLine ("NameAcquired: " + acquired_name);
+ };
+ */
+ Register ();
+ }
+
+ //should this be public?
+ //as long as Bus subclasses Connection, having a Register with a completely different meaning is bad
+ void Register ()
+ {
+ if (unique_name != null)
+ throw new Exception ("Bus already has a unique name");
+
+ unique_name = bus.Hello ();
+ }
+
+ public ulong GetUnixUser (string name)
+ {
+ return bus.GetConnectionUnixUser (name);
+ }
+
+ public RequestNameReply RequestName (string name)
+ {
+ return RequestName (name, NameFlag.None);
+ }
+
+ public RequestNameReply RequestName (string name, NameFlag flags)
+ {
+ return bus.RequestName (name, flags);
+ }
+
+ public ReleaseNameReply ReleaseName (string name)
+ {
+ return bus.ReleaseName (name);
+ }
+
+ public bool NameHasOwner (string name)
+ {
+ return bus.NameHasOwner (name);
+ }
+
+ public StartReply StartServiceByName (string name)
+ {
+ return StartServiceByName (name, 0);
+ }
+
+ public StartReply StartServiceByName (string name, uint flags)
+ {
+ return bus.StartServiceByName (name, flags);
+ }
+
+ internal protected override void AddMatch (string rule)
+ {
+ bus.AddMatch (rule);
+ }
+
+ internal protected override void RemoveMatch (string rule)
+ {
+ bus.RemoveMatch (rule);
+ }
+
+ public string GetId ()
+ {
+ return bus.GetId ();
+ }
+
+ string unique_name = null;
+ public string UniqueName
+ {
+ get {
+ return unique_name;
+ } set {
+ if (unique_name != null)
+ throw new Exception ("Unique name can only be set once");
+ unique_name = value;
+ }
+ }
+ }
+}
diff --git a/src/BusObject.cs b/src/BusObject.cs
new file mode 100644
index 0000000..e12207e
--- /dev/null
+++ b/src/BusObject.cs
@@ -0,0 +1,402 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Collections.Generic;
+
+namespace DBus
+{
+ class BusObject
+ {
+ protected Connection conn;
+ string bus_name;
+ string alt_bus_name;
+ ObjectPath object_path;
+
+ //protected BusObject ()
+ public BusObject ()
+ {
+ }
+
+ public BusObject (Connection conn, string bus_name, ObjectPath object_path)
+ {
+ this.conn = conn;
+ this.bus_name = bus_name;
+ this.object_path = object_path;
+ }
+
+ public Connection Connection
+ {
+ get {
+ return conn;
+ }
+ }
+
+ public string BusName
+ {
+ get {
+ return bus_name;
+ }
+ }
+
+ public ObjectPath Path
+ {
+ get {
+ return object_path;
+ }
+ }
+
+ public void ToggleSignal (string iface, string member, Delegate dlg, bool adding)
+ {
+ MatchRule rule = new MatchRule ();
+ rule.MessageType = MessageType.Signal;
+ rule.Fields.Add (FieldCode.Interface, new MatchTest (iface));
+ rule.Fields.Add (FieldCode.Member, new MatchTest (member));
+ rule.Fields.Add (FieldCode.Path, new MatchTest (object_path));
+ rule.Fields.Add (FieldCode.Sender, new MatchTest (alt_bus_name ?? bus_name));
+
+ if (adding) {
+ if (conn.Handlers.ContainsKey (rule))
+ conn.Handlers[rule] = Delegate.Combine (conn.Handlers[rule], dlg);
+ else {
+ conn.Handlers[rule] = dlg;
+ conn.AddMatch (rule.ToString ());
+ }
+ } else if (conn.Handlers.ContainsKey (rule)) {
+ conn.Handlers[rule] = Delegate.Remove (conn.Handlers[rule], dlg);
+ if (conn.Handlers[rule] == null) {
+ conn.RemoveMatch (rule.ToString ());
+ conn.Handlers.Remove (rule);
+ }
+ }
+ }
+
+ public void SendSignal (string iface, string member, string inSigStr, MessageWriter writer, Type retType, out Exception exception)
+ {
+ exception = null;
+
+ //TODO: don't ignore retVal, exception etc.
+
+ Signature outSig = String.IsNullOrEmpty (inSigStr) ? Signature.Empty : new Signature (inSigStr);
+
+ Signal signal = new Signal (object_path, iface, member);
+ signal.message.Signature = outSig;
+
+ Message signalMsg = signal.message;
+ signalMsg.Body = writer.ToArray ();
+
+ conn.Send (signalMsg);
+ }
+
+ public object SendMethodCallOld (string iface, string member, string inSigStr, MessageWriter writer, Type retType, out Exception exception)
+ {
+ exception = null;
+
+ //TODO: don't ignore retVal, exception etc.
+
+ Signature inSig = String.IsNullOrEmpty (inSigStr) ? Signature.Empty : new Signature (inSigStr);
+
+ MethodCall method_call = new MethodCall (object_path, iface, member, bus_name, inSig);
+
+ Message callMsg = method_call.message;
+ callMsg.Body = writer.ToArray ();
+
+ //Invoke Code::
+
+ //TODO: complete out parameter support
+ /*
+ Type[] outParmTypes = Mapper.GetTypes (ArgDirection.Out, mi.GetParameters ());
+ Signature outParmSig = Signature.GetSig (outParmTypes);
+
+ if (outParmSig != Signature.Empty)
+ throw new Exception ("Out parameters not yet supported: out_signature='" + outParmSig.Value + "'");
+ */
+
+ Type[] outTypes = new Type[1];
+ outTypes[0] = retType;
+
+ //we default to always requiring replies for now, even though unnecessary
+ //this is to make sure errors are handled synchronously
+ //TODO: don't hard code this
+ bool needsReply = true;
+
+ //if (mi.ReturnType == typeof (void))
+ // needsReply = false;
+
+ callMsg.ReplyExpected = needsReply;
+ callMsg.Signature = inSig;
+
+ if (!needsReply) {
+ conn.Send (callMsg);
+ return null;
+ }
+
+#if PROTO_REPLY_SIGNATURE
+ if (needsReply) {
+ Signature outSig = Signature.GetSig (outTypes);
+ callMsg.Header[FieldCode.ReplySignature] = outSig;
+ }
+#endif
+
+ Message retMsg = conn.SendWithReplyAndBlock (callMsg);
+
+ object retVal = null;
+
+ //handle the reply message
+ switch (retMsg.Header.MessageType) {
+ case MessageType.MethodReturn:
+ object[] retVals = MessageHelper.GetDynamicValues (retMsg, outTypes);
+ if (retVals.Length != 0)
+ retVal = retVals[retVals.Length - 1];
+ break;
+ case MessageType.Error:
+ //TODO: typed exceptions
+ Error error = new Error (retMsg);
+ string errMsg = String.Empty;
+ if (retMsg.Signature.Value.StartsWith ("s")) {
+ MessageReader reader = new MessageReader (retMsg);
+ errMsg = reader.ReadString ();
+ }
+ exception = new Exception (error.ErrorName + ": " + errMsg);
+ break;
+ default:
+ throw new Exception ("Got unexpected message of type " + retMsg.Header.MessageType + " while waiting for a MethodReturn or Error");
+ }
+
+ return retVal;
+ }
+
+ public MessageReader SendMethodCall (string iface, string member, string inSigStr, MessageWriter writer, Type retType, out Exception exception)
+ {
+ exception = null;
+
+ //TODO: don't ignore retVal, exception etc.
+
+ Signature inSig = String.IsNullOrEmpty (inSigStr) ? Signature.Empty : new Signature (inSigStr);
+
+ MethodCall method_call = new MethodCall (object_path, iface, member, bus_name, inSig);
+
+ Message callMsg = method_call.message;
+ callMsg.Body = writer.ToArray ();
+
+ //Invoke Code::
+
+ //TODO: complete out parameter support
+ /*
+ Type[] outParmTypes = Mapper.GetTypes (ArgDirection.Out, mi.GetParameters ());
+ Signature outParmSig = Signature.GetSig (outParmTypes);
+
+ if (outParmSig != Signature.Empty)
+ throw new Exception ("Out parameters not yet supported: out_signature='" + outParmSig.Value + "'");
+ */
+
+ Type[] outTypes = new Type[1];
+ outTypes[0] = retType;
+
+ //we default to always requiring replies for now, even though unnecessary
+ //this is to make sure errors are handled synchronously
+ //TODO: don't hard code this
+ bool needsReply = true;
+
+ //if (mi.ReturnType == typeof (void))
+ // needsReply = false;
+
+ callMsg.ReplyExpected = needsReply;
+ callMsg.Signature = inSig;
+
+ if (!needsReply) {
+ conn.Send (callMsg);
+ return null;
+ }
+
+#if PROTO_REPLY_SIGNATURE
+ if (needsReply) {
+ Signature outSig = Signature.GetSig (outTypes);
+ callMsg.Header[FieldCode.ReplySignature] = outSig;
+ }
+#endif
+
+ Message retMsg = conn.SendWithReplyAndBlock (callMsg);
+
+ MessageReader retVal = null;
+
+ //handle the reply message
+ switch (retMsg.Header.MessageType) {
+ case MessageType.MethodReturn:
+ if ((string)retMsg.Header[FieldCode.Sender] != bus_name)
+ alt_bus_name = (string)retMsg.Header[FieldCode.Sender];
+ retVal = new MessageReader (retMsg);
+ break;
+ case MessageType.Error:
+ //TODO: typed exceptions
+ Error error = new Error (retMsg);
+ string errMsg = String.Empty;
+ if (retMsg.Signature.Value.StartsWith ("s")) {
+ MessageReader reader = new MessageReader (retMsg);
+ errMsg = reader.ReadString ();
+ }
+ exception = new Exception (error.ErrorName + ": " + errMsg);
+ break;
+ default:
+ throw new Exception ("Got unexpected message of type " + retMsg.Header.MessageType + " while waiting for a MethodReturn or Error");
+ }
+
+ return retVal;
+ }
+
+ public void Invoke (MethodBase methodBase, string methodName, object[] inArgs, out object[] outArgs, out object retVal, out Exception exception)
+ {
+ outArgs = new object[0];
+ retVal = null;
+ exception = null;
+
+ MethodInfo mi = methodBase as MethodInfo;
+
+ if (mi != null && mi.IsSpecialName && (methodName.StartsWith ("add_") || methodName.StartsWith ("remove_"))) {
+ string[] parts = methodName.Split (new char[]{'_'}, 2);
+ string ename = parts[1];
+ Delegate dlg = (Delegate)inArgs[0];
+
+ ToggleSignal (Mapper.GetInterfaceName (mi), ename, dlg, parts[0] == "add");
+
+ return;
+ }
+
+ Type[] inTypes = Mapper.GetTypes (ArgDirection.In, mi.GetParameters ());
+ Signature inSig = Signature.GetSig (inTypes);
+
+ MethodCall method_call;
+ Message callMsg;
+
+ //build the outbound method call message
+ {
+ //this bit is error-prone (no null checking) and will need rewriting when DProxy is replaced
+ string iface = null;
+ if (mi != null)
+ iface = Mapper.GetInterfaceName (mi);
+
+ //map property accessors
+ //TODO: this needs to be done properly, not with simple String.Replace
+ //note that IsSpecialName is also for event accessors, but we already handled those and returned
+ if (mi != null && mi.IsSpecialName) {
+ methodName = methodName.Replace ("get_", "Get");
+ methodName = methodName.Replace ("set_", "Set");
+ }
+
+ method_call = new MethodCall (object_path, iface, methodName, bus_name, inSig);
+
+ callMsg = method_call.message;
+
+ if (inArgs != null && inArgs.Length != 0) {
+ MessageWriter writer = new MessageWriter (Connection.NativeEndianness);
+ writer.connection = conn;
+
+ for (int i = 0 ; i != inTypes.Length ; i++)
+ writer.Write (inTypes[i], inArgs[i]);
+
+ callMsg.Body = writer.ToArray ();
+ }
+ }
+
+ //TODO: complete out parameter support
+ /*
+ Type[] outParmTypes = Mapper.GetTypes (ArgDirection.Out, mi.GetParameters ());
+ Signature outParmSig = Signature.GetSig (outParmTypes);
+
+ if (outParmSig != Signature.Empty)
+ throw new Exception ("Out parameters not yet supported: out_signature='" + outParmSig.Value + "'");
+ */
+
+ Type[] outTypes = new Type[1];
+ outTypes[0] = mi.ReturnType;
+
+ //we default to always requiring replies for now, even though unnecessary
+ //this is to make sure errors are handled synchronously
+ //TODO: don't hard code this
+ bool needsReply = true;
+
+ //if (mi.ReturnType == typeof (void))
+ // needsReply = false;
+
+ callMsg.ReplyExpected = needsReply;
+ callMsg.Signature = inSig;
+
+ if (!needsReply) {
+ conn.Send (callMsg);
+ return;
+ }
+
+#if PROTO_REPLY_SIGNATURE
+ if (needsReply) {
+ Signature outSig = Signature.GetSig (outTypes);
+ callMsg.Header[FieldCode.ReplySignature] = outSig;
+ }
+#endif
+
+ Message retMsg = conn.SendWithReplyAndBlock (callMsg);
+
+ //handle the reply message
+ switch (retMsg.Header.MessageType) {
+ case MessageType.MethodReturn:
+ object[] retVals = MessageHelper.GetDynamicValues (retMsg, outTypes);
+ if (retVals.Length != 0)
+ retVal = retVals[retVals.Length - 1];
+ break;
+ case MessageType.Error:
+ //TODO: typed exceptions
+ Error error = new Error (retMsg);
+ string errMsg = String.Empty;
+ if (retMsg.Signature.Value.StartsWith ("s")) {
+ MessageReader reader = new MessageReader (retMsg);
+ errMsg = reader.ReadString ();
+ }
+ exception = new Exception (error.ErrorName + ": " + errMsg);
+ break;
+ default:
+ throw new Exception ("Got unexpected message of type " + retMsg.Header.MessageType + " while waiting for a MethodReturn or Error");
+ }
+
+ return;
+ }
+
+ public static object GetObject (Connection conn, string bus_name, ObjectPath object_path, Type declType)
+ {
+ Type proxyType = TypeImplementer.Root.GetImplementation (declType);
+
+ //BusObject inst = (BusObject)Activator.CreateInstance (proxyType);
+ object instObj = Activator.CreateInstance (proxyType);
+ BusObject inst = GetBusObject (instObj);
+ inst.conn = conn;
+ inst.bus_name = bus_name;
+ inst.object_path = object_path;
+
+ return instObj;
+ }
+
+ static Dictionary<object,BusObject> boCache = new Dictionary<object,BusObject>();
+ public static BusObject GetBusObject (object instObj)
+ {
+ if (instObj is BusObject)
+ return (BusObject)instObj;
+
+ BusObject inst;
+ if (boCache.TryGetValue (instObj, out inst))
+ return inst;
+
+ inst = new BusObject ();
+ boCache[instObj] = inst;
+
+ return inst;
+ }
+
+ public Delegate GetHookupDelegate (EventInfo ei)
+ {
+ DynamicMethod hookupMethod = TypeImplementer.GetHookupMethod (ei);
+ Delegate d = hookupMethod.CreateDelegate (ei.EventHandlerType, this);
+ return d;
+ }
+ }
+}
diff --git a/src/Connection.cs b/src/Connection.cs
new file mode 100644
index 0000000..4ad1ce9
--- /dev/null
+++ b/src/Connection.cs
@@ -0,0 +1,507 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Reflection;
+
+namespace DBus
+{
+ using Authentication;
+ using Transports;
+
+ public partial class Connection
+ {
+ Transport transport;
+ internal Transport Transport {
+ get {
+ return transport;
+ } set {
+ transport = value;
+ transport.Connection = this;
+ }
+ }
+
+ protected Connection () {}
+
+ internal Connection (Transport transport)
+ {
+ this.transport = transport;
+ transport.Connection = this;
+ }
+
+ //should this be public?
+ internal Connection (string address)
+ {
+ OpenPrivate (address);
+ Authenticate ();
+ }
+
+ internal bool isConnected = false;
+ public bool IsConnected
+ {
+ get {
+ return isConnected;
+ }
+ }
+
+ // TODO: Complete disconnection support
+ internal bool isShared = false;
+ public void Close ()
+ {
+ if (isShared)
+ throw new Exception ("Cannot disconnect a shared Connection");
+
+ if (!IsConnected)
+ return;
+
+ transport.Disconnect ();
+ isConnected = false;
+ }
+
+ //should we do connection sharing here?
+ public static Connection Open (string address)
+ {
+ Connection conn = new Connection ();
+ conn.OpenPrivate (address);
+ conn.Authenticate ();
+
+ return conn;
+ }
+
+ internal void OpenPrivate (string address)
+ {
+ if (address == null)
+ throw new ArgumentNullException ("address");
+
+ AddressEntry[] entries = Address.Parse (address);
+ if (entries.Length == 0)
+ throw new Exception ("No addresses were found");
+
+ //TODO: try alternative addresses if needed
+ AddressEntry entry = entries[0];
+
+ Id = entry.GUID;
+ Transport = Transport.Create (entry);
+ isConnected = true;
+ }
+
+ internal UUID Id = UUID.Zero;
+
+ void Authenticate ()
+ {
+ if (transport != null)
+ transport.WriteCred ();
+
+ SaslClient auth = new SaslClient ();
+ auth.Identity = transport.AuthString ();
+ auth.stream = transport.Stream;
+ auth.Peer = new SaslPeer ();
+ auth.Peer.Peer = auth;
+ auth.Peer.stream = transport.Stream;
+
+ if (!auth.Authenticate ())
+ throw new Exception ("Authentication failure");
+
+ if (Id != UUID.Zero)
+ if (auth.ActualId != Id)
+ throw new Exception ("Authentication failure: Unexpected GUID");
+
+ if (Id == UUID.Zero)
+ Id = auth.ActualId;
+
+ isAuthenticated = true;
+ }
+
+ internal bool isAuthenticated = false;
+ internal bool IsAuthenticated
+ {
+ get {
+ return isAuthenticated;
+ }
+ }
+
+ //Interlocked.Increment() handles the overflow condition for uint correctly, so it's ok to store the value as an int but cast it to uint
+ int serial = 0;
+ internal uint GenerateSerial ()
+ {
+ return (uint)Interlocked.Increment (ref serial);
+ }
+
+ internal Message SendWithReplyAndBlock (Message msg)
+ {
+ PendingCall pending = SendWithReply (msg);
+ return pending.Reply;
+ }
+
+ internal PendingCall SendWithReply (Message msg)
+ {
+ msg.ReplyExpected = true;
+
+ if (msg.Header.Serial == 0)
+ msg.Header.Serial = GenerateSerial ();
+
+ // Should we throttle the maximum number of concurrent PendingCalls?
+ // Should we support timeouts?
+ PendingCall pending = new PendingCall (this);
+ lock (pendingCalls)
+ pendingCalls[msg.Header.Serial] = pending;
+
+ Send (msg);
+
+ return pending;
+ }
+
+ internal virtual uint Send (Message msg)
+ {
+ if (msg.Header.Serial == 0)
+ msg.Header.Serial = GenerateSerial ();
+
+ transport.WriteMessage (msg);
+
+ return msg.Header.Serial;
+ }
+
+ Queue<Message> Inbound = new Queue<Message> ();
+
+ //temporary hack
+ internal void DispatchSignals ()
+ {
+ lock (Inbound) {
+ while (Inbound.Count != 0) {
+ Message msg = Inbound.Dequeue ();
+ HandleSignal (msg);
+ }
+ }
+ }
+
+ internal Thread mainThread = Thread.CurrentThread;
+
+ //temporary hack
+ public void Iterate ()
+ {
+ mainThread = Thread.CurrentThread;
+
+ Message msg = transport.ReadMessage ();
+
+ HandleMessage (msg);
+ DispatchSignals ();
+ }
+
+ internal void Dispatch ()
+ {
+ while (transport.Inbound.Count != 0) {
+ Message msg = transport.Inbound.Dequeue ();
+ HandleMessage (msg);
+ }
+ DispatchSignals ();
+ }
+
+ internal virtual void HandleMessage (Message msg)
+ {
+ if (msg == null)
+ return;
+
+ //TODO: support disconnection situations properly and move this check elsewhere
+ if (msg == null)
+ throw new ArgumentNullException ("msg", "Cannot handle a null message; maybe the bus was disconnected");
+
+ //TODO: Restrict messages to Local ObjectPath?
+
+ {
+ object field_value = msg.Header[FieldCode.ReplySerial];
+ if (field_value != null) {
+ uint reply_serial = (uint)field_value;
+ PendingCall pending;
+
+ lock (pendingCalls) {
+ if (pendingCalls.TryGetValue (reply_serial, out pending)) {
+ if (pendingCalls.Remove (reply_serial))
+ pending.Reply = msg;
+
+ return;
+ }
+ }
+
+ //we discard reply messages with no corresponding PendingCall
+ if (Protocol.Verbose)
+ Console.Error.WriteLine ("Unexpected reply message received: MessageType='" + msg.Header.MessageType + "', ReplySerial=" + reply_serial);
+
+ return;
+ }
+ }
+
+ switch (msg.Header.MessageType) {
+ case MessageType.MethodCall:
+ MethodCall method_call = new MethodCall (msg);
+ HandleMethodCall (method_call);
+ break;
+ case MessageType.Signal:
+ //HandleSignal (msg);
+ lock (Inbound)
+ Inbound.Enqueue (msg);
+ break;
+ case MessageType.Error:
+ //TODO: better exception handling
+ Error error = new Error (msg);
+ string errMsg = String.Empty;
+ if (msg.Signature.Value.StartsWith ("s")) {
+ MessageReader reader = new MessageReader (msg);
+ errMsg = reader.ReadString ();
+ }
+ Console.Error.WriteLine ("Remote Error: Signature='" + msg.Signature.Value + "' " + error.ErrorName + ": " + errMsg);
+ break;
+ case MessageType.Invalid:
+ default:
+ throw new Exception ("Invalid message received: MessageType='" + msg.Header.MessageType + "'");
+ }
+ }
+
+ Dictionary<uint,PendingCall> pendingCalls = new Dictionary<uint,PendingCall> ();
+
+ //this might need reworking with MulticastDelegate
+ internal void HandleSignal (Message msg)
+ {
+ Signal signal = new Signal (msg);
+
+ //TODO: this is a hack, not necessary when MatchRule is complete
+ MatchRule rule = new MatchRule ();
+ rule.MessageType = MessageType.Signal;
+ rule.Fields.Add (FieldCode.Interface, new MatchTest (signal.Interface));
+ rule.Fields.Add (FieldCode.Member, new MatchTest (signal.Member));
+ rule.Fields.Add (FieldCode.Sender, new MatchTest (signal.Sender));
+ rule.Fields.Add (FieldCode.Path, new MatchTest (signal.Path));
+
+ Delegate dlg;
+ if (Handlers.TryGetValue (rule, out dlg) && dlg != null) {
+ MethodInfo mi = dlg.GetType ().GetMethod ("Invoke");
+
+ bool compatible = false;
+ Signature inSig, outSig;
+
+ if (TypeImplementer.SigsForMethod(mi, out inSig, out outSig))
+ if (outSig == Signature.Empty && inSig == msg.Signature)
+ compatible = true;
+
+ if (!compatible) {
+ if (Protocol.Verbose)
+ Console.Error.WriteLine ("Signal argument mismatch: " + signal.Interface + '.' + signal.Member);
+ return;
+ }
+
+ //signals have no return value
+ dlg.DynamicInvoke (MessageHelper.GetDynamicValues (msg, mi.GetParameters ()));
+ } else {
+ //TODO: how should we handle this condition? sending an Error may not be appropriate in this case
+ if (Protocol.Verbose)
+ Console.Error.WriteLine ("Warning: No signal handler for " + signal.Member);
+ }
+ }
+
+ internal Dictionary<MatchRule,Delegate> Handlers = new Dictionary<MatchRule,Delegate> ();
+
+ //very messy
+ internal void MaybeSendUnknownMethodError (MethodCall method_call)
+ {
+ Message msg = MessageHelper.CreateUnknownMethodError (method_call);
+ if (msg != null)
+ Send (msg);
+ }
+
+ //not particularly efficient and needs to be generalized
+ internal void HandleMethodCall (MethodCall method_call)
+ {
+ //TODO: Ping and Introspect need to be abstracted and moved somewhere more appropriate once message filter infrastructure is complete
+
+ //FIXME: these special cases are slightly broken for the case where the member but not the interface is specified in the message
+ if (method_call.Interface == "org.freedesktop.DBus.Peer") {
+ switch (method_call.Member) {
+ case "Ping":
+ Send (MessageHelper.ConstructReply (method_call));
+ return;
+ case "GetMachineId":
+ if (MachineId != UUID.Zero) {
+ Send (MessageHelper.ConstructReply (method_call, MachineId.ToString ()));
+ return;
+ } else {
+ // Might want to send back an error here?
+ }
+ break;
+ }
+ }
+
+ if (method_call.Interface == "org.freedesktop.DBus.Introspectable" && method_call.Member == "Introspect") {
+ Introspector intro = new Introspector ();
+ intro.root_path = method_call.Path;
+ intro.WriteStart ();
+
+ //FIXME: do this properly
+ //this is messy and inefficient
+ List<string> linkNodes = new List<string> ();
+ int depth = method_call.Path.Decomposed.Length;
+ foreach (ObjectPath pth in RegisteredObjects.Keys) {
+ if (pth.Value == (method_call.Path.Value)) {
+ ExportObject exo = (ExportObject)RegisteredObjects[pth];
+ exo.WriteIntrospect (intro);
+ } else {
+ for (ObjectPath cur = pth ; cur != null ; cur = cur.Parent) {
+ if (cur.Value == method_call.Path.Value) {
+ string linkNode = pth.Decomposed[depth];
+ if (!linkNodes.Contains (linkNode)) {
+ intro.WriteNode (linkNode);
+ linkNodes.Add (linkNode);
+ }
+ }
+ }
+ }
+ }
+
+ intro.WriteEnd ();
+
+ Message reply = MessageHelper.ConstructReply (method_call, intro.xml);
+ Send (reply);
+ return;
+ }
+
+ BusObject bo;
+ if (RegisteredObjects.TryGetValue (method_call.Path, out bo)) {
+ ExportObject eo = (ExportObject)bo;
+ eo.HandleMethodCall (method_call);
+ } else {
+ MaybeSendUnknownMethodError (method_call);
+ }
+ }
+
+ Dictionary<ObjectPath,BusObject> RegisteredObjects = new Dictionary<ObjectPath,BusObject> ();
+
+ //FIXME: this shouldn't be part of the core API
+ //that also applies to much of the other object mapping code
+
+ public object GetObject (Type type, string bus_name, ObjectPath path)
+ {
+ //if (type == null)
+ // return GetObject (bus_name, path);
+
+ //if the requested type is an interface, we can implement it efficiently
+ //otherwise we fall back to using a transparent proxy
+ if (type.IsInterface || type.IsAbstract) {
+ return BusObject.GetObject (this, bus_name, path, type);
+ } else {
+ if (Protocol.Verbose)
+ Console.Error.WriteLine ("Warning: Note that MarshalByRefObject use is not recommended; for best performance, define interfaces");
+
+ BusObject busObject = new BusObject (this, bus_name, path);
+ DProxy prox = new DProxy (busObject, type);
+ return prox.GetTransparentProxy ();
+ }
+ }
+
+ public T GetObject<T> (string bus_name, ObjectPath path)
+ {
+ return (T)GetObject (typeof (T), bus_name, path);
+ }
+
+ [Obsolete ("Use the overload of Register() which does not take a bus_name parameter")]
+ public void Register (string bus_name, ObjectPath path, object obj)
+ {
+ Register (path, obj);
+ }
+
+ [Obsolete ("Use the overload of Unregister() which does not take a bus_name parameter")]
+ public object Unregister (string bus_name, ObjectPath path)
+ {
+ return Unregister (path);
+ }
+
+ public void Register (ObjectPath path, object obj)
+ {
+ ExportObject eo = ExportObject.CreateExportObject (this, path, obj);
+ eo.Registered = true;
+
+ //TODO: implement some kind of tree data structure or internal object hierarchy. right now we are ignoring the name and putting all object paths in one namespace, which is bad
+ RegisteredObjects[path] = eo;
+ }
+
+ public object Unregister (ObjectPath path)
+ {
+ BusObject bo;
+
+ if (!RegisteredObjects.TryGetValue (path, out bo))
+ throw new Exception ("Cannot unregister " + path + " as it isn't registered");
+
+ RegisteredObjects.Remove (path);
+
+ ExportObject eo = (ExportObject)bo;
+ eo.Registered = false;
+
+ return eo.obj;
+ }
+
+ //these look out of place, but are useful
+ internal protected virtual void AddMatch (string rule)
+ {
+ }
+
+ internal protected virtual void RemoveMatch (string rule)
+ {
+ }
+
+ // Maybe we should use XDG/basedir or check an env var for this?
+ const string machineUuidFilename = @"/var/lib/dbus/machine-id";
+ static UUID? machineId = null;
+ private static object idReadLock = new object ();
+ internal static UUID MachineId
+ {
+ get {
+ lock (idReadLock) {
+ if (machineId != null)
+ return (UUID)machineId;
+ try {
+ machineId = ReadMachineId (machineUuidFilename);
+ } catch {
+ machineId = UUID.Zero;
+ }
+ return (UUID)machineId;
+ }
+ }
+ }
+
+ static UUID ReadMachineId (string fname)
+ {
+ using (FileStream fs = File.OpenRead (fname)) {
+ // Length is typically 33 (32 for the UUID, plus a linefeed)
+ //if (fs.Length < 32)
+ // return UUID.Zero;
+
+ byte[] data = new byte[32];
+
+ int pos = 0;
+ while (pos < data.Length) {
+ int read = fs.Read (data, pos, data.Length - pos);
+ if (read == 0)
+ break;
+ pos += read;
+ }
+
+ if (pos != data.Length)
+ //return UUID.Zero;
+ throw new Exception ("Insufficient data while reading GUID string");
+
+ return UUID.Parse (System.Text.Encoding.ASCII.GetString (data));
+ }
+ }
+
+ static Connection ()
+ {
+ if (BitConverter.IsLittleEndian)
+ NativeEndianness = EndianFlag.Little;
+ else
+ NativeEndianness = EndianFlag.Big;
+ }
+
+ internal static readonly EndianFlag NativeEndianness;
+ }
+}
diff --git a/src/DBus.cs b/src/DBus.cs
new file mode 100644
index 0000000..262f299
--- /dev/null
+++ b/src/DBus.cs
@@ -0,0 +1,98 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using DBus;
+
+namespace org.freedesktop.DBus
+{
+ [Flags]
+ public enum NameFlag : uint
+ {
+ None = 0,
+ AllowReplacement = 0x1,
+ ReplaceExisting = 0x2,
+ DoNotQueue = 0x4,
+ }
+
+ public enum RequestNameReply : uint
+ {
+ PrimaryOwner = 1,
+ InQueue,
+ Exists,
+ AlreadyOwner,
+ }
+
+ public enum ReleaseNameReply : uint
+ {
+ Released = 1,
+ NonExistent,
+ NotOwner,
+ }
+
+ public enum StartReply : uint
+ {
+ //The service was successfully started.
+ Success = 1,
+ //A connection already owns the given name.
+ AlreadyRunning,
+ }
+
+ public delegate void NameOwnerChangedHandler (string name, string old_owner, string new_owner);
+ public delegate void NameAcquiredHandler (string name);
+ public delegate void NameLostHandler (string name);
+
+ [Interface ("org.freedesktop.DBus.Peer")]
+ public interface Peer
+ {
+ void Ping ();
+ [return: Argument ("machine_uuid")]
+ string GetMachineId ();
+ }
+
+ [Interface ("org.freedesktop.DBus.Introspectable")]
+ public interface Introspectable
+ {
+ [return: Argument ("data")]
+ string Introspect ();
+ }
+
+ [Interface ("org.freedesktop.DBus.Properties")]
+ public interface Properties
+ {
+ [return: Argument ("value")]
+ object Get (string @interface, string propname);
+ void Set (string @interface, string propname, object value);
+ [return: Argument ("props")]
+ IDictionary<string,object> GetAll (string @interface);
+ }
+
+ [Interface ("org.freedesktop.DBus")]
+ public interface IBus
+ {
+ RequestNameReply RequestName (string name, NameFlag flags);
+ ReleaseNameReply ReleaseName (string name);
+ string Hello ();
+ string[] ListNames ();
+ string[] ListActivatableNames ();
+ bool NameHasOwner (string name);
+ event NameOwnerChangedHandler NameOwnerChanged;
+ event NameLostHandler NameLost;
+ event NameAcquiredHandler NameAcquired;
+ StartReply StartServiceByName (string name, uint flags);
+ void UpdateActivationEnvironment (IDictionary<string, string> environment);
+ string GetNameOwner (string name);
+ uint GetConnectionUnixUser (string connection_name);
+ void AddMatch (string rule);
+ void RemoveMatch (string rule);
+ string GetId ();
+
+ //undocumented in spec
+ string[] ListQueuedOwners (string name);
+ uint GetConnectionUnixProcessID (string connection_name);
+ byte[] GetConnectionSELinuxSecurityContext (string connection_name);
+ void ReloadConfig ();
+ }
+}
diff --git a/src/DProxy.cs b/src/DProxy.cs
new file mode 100644
index 0000000..8b0b7ab
--- /dev/null
+++ b/src/DProxy.cs
@@ -0,0 +1,79 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Reflection;
+using System.Runtime.Remoting.Proxies;
+using System.Runtime.Remoting.Messaging;
+
+namespace DBus
+{
+ //marked internal because this is really an implementation detail and needs to be replaced
+ internal class DProxy : RealProxy
+ {
+ protected BusObject busObject;
+
+ public DProxy (BusObject busObject, Type type) : base(type)
+ {
+ this.busObject = busObject;
+ }
+
+ static MethodInfo mi_GetHashCode = typeof (object).GetMethod ("GetHashCode");
+ static MethodInfo mi_Equals = typeof (object).GetMethod ("Equals", BindingFlags.Instance);
+ static MethodInfo mi_ToString = typeof (object).GetMethod ("ToString");
+ static MethodInfo mi_GetLifetimeService = typeof (MarshalByRefObject).GetMethod ("GetLifetimeService");
+
+ object GetDefaultReturn (MethodBase mi, object[] inArgs)
+ {
+ if (mi == mi_GetHashCode)
+ return busObject.Path.Value.GetHashCode ();
+ if (mi == mi_Equals)
+ return busObject.Path.Value == ((BusObject)((MarshalByRefObject)inArgs[0]).GetLifetimeService ()).Path.Value;
+ if (mi == mi_ToString)
+ return busObject.Path.Value;
+ if (mi == mi_GetLifetimeService)
+ return busObject;
+
+ return null;
+ }
+
+ public override IMessage Invoke (IMessage message)
+ {
+ IMethodCallMessage callMessage = (IMethodCallMessage) message;
+
+ object defaultRetVal = GetDefaultReturn (callMessage.MethodBase, callMessage.InArgs);
+ if (defaultRetVal != null) {
+ MethodReturnMessageWrapper defaultReturnMessage = new MethodReturnMessageWrapper ((IMethodReturnMessage) message);
+ defaultReturnMessage.ReturnValue = defaultRetVal;
+
+ return defaultReturnMessage;
+ }
+
+ object[] outArgs;
+ object retVal;
+ Exception exception;
+ busObject.Invoke (callMessage.MethodBase, callMessage.MethodName, callMessage.InArgs, out outArgs, out retVal, out exception);
+
+ MethodReturnMessageWrapper returnMessage = new MethodReturnMessageWrapper ((IMethodReturnMessage) message);
+ returnMessage.Exception = exception;
+ returnMessage.ReturnValue = retVal;
+
+ return returnMessage;
+ }
+
+ /*
+ public override ObjRef CreateObjRef (Type ServerType)
+ {
+ throw new System.NotImplementedException ();
+ }
+ */
+
+ ~DProxy ()
+ {
+ //FIXME: remove handlers/match rules here
+ if (Protocol.Verbose)
+ Console.Error.WriteLine ("Warning: Finalization of " + busObject.Path + " not yet supported");
+ }
+ }
+}
diff --git a/src/ExportObject.cs b/src/ExportObject.cs
new file mode 100644
index 0000000..6284ff5
--- /dev/null
+++ b/src/ExportObject.cs
@@ -0,0 +1,199 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
+
+using org.freedesktop.DBus;
+
+namespace DBus
+{
+ //TODO: perhaps ExportObject should not derive from BusObject
+ internal class ExportObject : BusObject, IDisposable //, Peer
+ {
+ public object obj;
+
+ public ExportObject (Connection conn, ObjectPath object_path, object obj) : base (conn, null, object_path)
+ {
+ this.obj = obj;
+ }
+
+ //maybe add checks to make sure this is not called more than once
+ //it's a bit silly as a property
+ bool isRegistered = false;
+ public virtual bool Registered
+ {
+ get {
+ return isRegistered;
+ }
+ set {
+ if (value == isRegistered)
+ return;
+
+ Type type = obj.GetType ();
+
+ foreach (MemberInfo mi in Mapper.GetPublicMembers (type)) {
+ EventInfo ei = mi as EventInfo;
+
+ if (ei == null)
+ continue;
+
+ Delegate dlg = GetHookupDelegate (ei);
+
+ if (value)
+ ei.AddEventHandler (obj, dlg);
+ else
+ ei.RemoveEventHandler (obj, dlg);
+ }
+
+ isRegistered = value;
+ }
+ }
+
+ internal virtual void WriteIntrospect (Introspector intro)
+ {
+ intro.WriteType (obj.GetType ());
+ }
+
+ internal static MethodCaller2 GetMCaller (MethodInfo mi)
+ {
+ MethodCaller2 mCaller;
+ if (!mCallers.TryGetValue (mi, out mCaller)) {
+ //mCaller = TypeImplementer.GenCaller (mi, obj);
+ mCaller = TypeImplementer.GenCaller2 (mi);
+ mCallers[mi] = mCaller;
+ }
+ return mCaller;
+ }
+
+ public static ExportObject CreateExportObject (Connection conn, ObjectPath object_path, object obj)
+ {
+#if DLR
+ Type type = obj.GetType ();
+ if (type.Name == "RubyObject" || type.FullName == "IronPython.Runtime.Types.OldInstance")
+ return new DynamicExportObject (conn, object_path, obj);
+#endif
+
+ return new ExportObject (conn, object_path, obj);
+ }
+
+ static internal readonly Dictionary<MethodInfo,MethodCaller2> mCallers = new Dictionary<MethodInfo,MethodCaller2> ();
+ public virtual void HandleMethodCall (MethodCall method_call)
+ {
+ Type type = obj.GetType ();
+
+ //object retObj = type.InvokeMember (msg.Member, BindingFlags.InvokeMethod, null, obj, MessageHelper.GetDynamicValues (msg));
+
+ //TODO: there is no member name mapping for properties etc. yet
+
+ // FIXME: Inefficient to do this on every call
+ MethodInfo mi = Mapper.GetMethod (type, method_call);
+
+ if (mi == null) {
+ conn.MaybeSendUnknownMethodError (method_call);
+ return;
+ }
+
+ MethodCaller2 mCaller;
+ if (!mCallers.TryGetValue (mi, out mCaller)) {
+ //mCaller = TypeImplementer.GenCaller (mi, obj);
+ mCaller = TypeImplementer.GenCaller2 (mi);
+ mCallers[mi] = mCaller;
+ }
+
+ Signature inSig, outSig;
+ TypeImplementer.SigsForMethod (mi, out inSig, out outSig);
+
+ Message msg = method_call.message;
+ MessageReader msgReader = new MessageReader (method_call.message);
+ MessageWriter retWriter = new MessageWriter ();
+
+ /*
+ MessageWriter retWriter = null;
+ if (msg.ReplyExpected)
+ retWriter = new MessageWriter ();
+ */
+
+ Exception raisedException = null;
+ try {
+ //mCaller (msgReader, method_call.message, retWriter);
+ mCaller (obj, msgReader, method_call.message, retWriter);
+ } catch (Exception e) {
+ raisedException = e;
+ }
+
+ if (!msg.ReplyExpected)
+ return;
+
+ Message replyMsg;
+
+ if (raisedException == null) {
+ MethodReturn method_return = new MethodReturn (msg.Header.Serial);
+ replyMsg = method_return.message;
+ replyMsg.Body = retWriter.ToArray ();
+ replyMsg.Signature = outSig;
+ } else {
+ Error error;
+ // BusException allows precisely formatted Error messages.
+ BusException busException = raisedException as BusException;
+ if (busException != null)
+ error = method_call.CreateError (busException.ErrorName, busException.ErrorMessage);
+ else if (raisedException is ArgumentException && raisedException.TargetSite.Name == mi.Name) {
+ // Name match trick above is a hack since we don't have the resolved MethodInfo.
+ ArgumentException argException = (ArgumentException)raisedException;
+ using (System.IO.StringReader sr = new System.IO.StringReader (argException.Message)) {
+ error = method_call.CreateError ("org.freedesktop.DBus.Error.InvalidArgs", sr.ReadLine ());
+ }
+ } else
+ error = method_call.CreateError (Mapper.GetInterfaceName (raisedException.GetType ()), raisedException.Message);
+
+ replyMsg = error.message;
+ }
+
+ if (method_call.Sender != null)
+ replyMsg.Header[FieldCode.Destination] = method_call.Sender;
+
+ conn.Send (replyMsg);
+ }
+
+ /*
+ public void Ping ()
+ {
+ }
+
+ public string GetMachineId ()
+ {
+ //TODO: implement this
+ return String.Empty;
+ }
+ */
+
+#region IDisposable
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+
+ ~ExportObject ()
+ {
+ Dispose (false);
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ if (disposing)
+ {
+ if (obj != null)
+ {
+ Registered = false;
+ obj = null;
+ }
+ }
+ }
+#endregion
+ }
+}
diff --git a/src/Introspection.cs b/src/Introspection.cs
new file mode 100644
index 0000000..acf34b4
--- /dev/null
+++ b/src/Introspection.cs
@@ -0,0 +1,316 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using System.Text;
+using System.Reflection;
+
+namespace DBus
+{
+ //TODO: complete this class
+ class Introspector
+ {
+ const string NAMESPACE = "http://www.freedesktop.org/standards/dbus";
+ const string PUBLIC_IDENTIFIER = "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN";
+ const string SYSTEM_IDENTIFIER = "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";
+
+ public StringBuilder sb;
+ public string xml;
+ public ObjectPath root_path = ObjectPath.Root;
+ public bool ExtendedAnnotations = false;
+
+ protected XmlWriter writer;
+
+ public Introspector ()
+ {
+ XmlWriterSettings settings = new XmlWriterSettings ();
+ settings.Indent = true;
+ settings.IndentChars = (" ");
+ settings.OmitXmlDeclaration = true;
+
+ sb = new StringBuilder ();
+
+ writer = XmlWriter.Create (sb, settings);
+ }
+
+ static string GetProductDescription ()
+ {
+ String version;
+
+ Assembly assembly = Assembly.GetExecutingAssembly ();
+ AssemblyName aname = assembly.GetName ();
+
+ AssemblyInformationalVersionAttribute iversion = Attribute.GetCustomAttribute (assembly, typeof (AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute;
+
+ if (iversion != null)
+ version = iversion.InformationalVersion;
+ else
+ version = aname.Version.ToString ();
+
+ return aname.Name + " " + version;
+ }
+
+ public void WriteStart ()
+ {
+ writer.WriteDocType ("node", PUBLIC_IDENTIFIER, SYSTEM_IDENTIFIER, null);
+
+ writer.WriteComment (" " + GetProductDescription () + " ");
+
+ //the root node element
+ writer.WriteStartElement ("node");
+ }
+
+ public void WriteNode (string name)
+ {
+ writer.WriteStartElement ("node");
+ writer.WriteAttributeString ("name", name);
+ writer.WriteEndElement ();
+ }
+
+ public void WriteEnd ()
+ {
+ /*
+ WriteEnum (typeof (org.freedesktop.DBus.NameFlag));
+ WriteEnum (typeof (org.freedesktop.DBus.NameReply));
+ WriteEnum (typeof (org.freedesktop.DBus.ReleaseNameReply));
+ WriteEnum (typeof (org.freedesktop.DBus.StartReply));
+ WriteInterface (typeof (org.freedesktop.DBus.IBus));
+ */
+
+ writer.WriteEndElement ();
+
+ writer.Flush ();
+ xml = sb.ToString ();
+ }
+
+ //public void WriteNode ()
+ public void WriteType (Type target_type)
+ {
+ //writer.WriteStartElement ("node");
+
+ //TODO: non-well-known introspection has paths as well, which we don't do yet. read the spec again
+ //hackishly just remove the root '/' to make the path relative for now
+ //writer.WriteAttributeString ("name", target_path.Value.Substring (1));
+ //writer.WriteAttributeString ("name", "test");
+
+ //reflect our own interface manually
+ WriteInterface (typeof (org.freedesktop.DBus.Introspectable));
+
+ //reflect the target interface
+ if (target_type != null) {
+ WriteInterface (target_type);
+
+ foreach (Type ifType in target_type.GetInterfaces ())
+ WriteInterface (ifType);
+ }
+
+ //TODO: review recursion of interfaces and inheritance hierarchy
+
+ //writer.WriteEndElement ();
+ }
+
+ public void WriteArg (ParameterInfo pi)
+ {
+ WriteArg (pi.ParameterType, Mapper.GetArgumentName (pi), pi.IsOut, false);
+ }
+
+ public void WriteArgReverse (ParameterInfo pi)
+ {
+ WriteArg (pi.ParameterType, Mapper.GetArgumentName (pi), pi.IsOut, true);
+ }
+
+ //TODO: clean up and get rid of reverse (or argIsOut) parm
+ public void WriteArg (Type argType, string argName, bool argIsOut, bool reverse)
+ {
+ argType = argIsOut ? argType.GetElementType () : argType;
+ if (argType == typeof (void))
+ return;
+
+ writer.WriteStartElement ("arg");
+
+ if (!String.IsNullOrEmpty (argName))
+ writer.WriteAttributeString ("name", argName);
+
+ //we can't rely on the default direction (qt-dbus requires a direction at time of writing), so we use a boolean to reverse the parameter direction and make it explicit
+
+ if (argIsOut)
+ writer.WriteAttributeString ("direction", !reverse ? "out" : "in");
+ else
+ writer.WriteAttributeString ("direction", !reverse ? "in" : "out");
+
+ Signature sig = Signature.GetSig (argType);
+
+ //TODO: avoid writing null (DType.Invalid) to the XML stream
+ writer.WriteAttributeString ("type", sig.Value);
+
+ //annotations aren't valid in an arg element, so this is disabled
+ //if (argType.IsEnum)
+ // WriteAnnotation ("org.ndesk.DBus.Enum", Mapper.GetInterfaceName (argType));
+
+ writer.WriteEndElement ();
+ }
+
+ public void WriteMethod (MethodInfo mi)
+ {
+ writer.WriteStartElement ("method");
+ writer.WriteAttributeString ("name", mi.Name);
+
+ foreach (ParameterInfo pi in mi.GetParameters ())
+ WriteArg (pi);
+
+ //Mono <= 1.1.13 doesn't support MethodInfo.ReturnParameter, so avoid it
+ //WriteArgReverse (mi.ReturnParameter);
+ WriteArg (mi.ReturnType, Mapper.GetArgumentName (mi.ReturnTypeCustomAttributes, "ret"), false, true);
+
+ WriteAnnotations (mi);
+
+ writer.WriteEndElement ();
+ }
+
+ public void WriteProperty (PropertyInfo pri)
+ {
+ //expose properties as dbus properties
+ writer.WriteStartElement ("property");
+ writer.WriteAttributeString ("name", pri.Name);
+ writer.WriteAttributeString ("type", Signature.GetSig (pri.PropertyType).Value);
+ string access = (pri.CanRead ? "read" : String.Empty) + (pri.CanWrite ? "write" : String.Empty);
+ writer.WriteAttributeString ("access", access);
+ WriteAnnotations (pri);
+ writer.WriteEndElement ();
+
+ //expose properties as methods also
+ //it may not be worth doing this in the long run
+ /*
+ if (pri.CanRead) {
+ writer.WriteStartElement ("method");
+ writer.WriteAttributeString ("name", "Get" + pri.Name);
+ WriteArgReverse (pri.GetGetMethod ().ReturnParameter);
+ writer.WriteEndElement ();
+ }
+
+ if (pri.CanWrite) {
+ writer.WriteStartElement ("method");
+ writer.WriteAttributeString ("name", "Set" + pri.Name);
+ foreach (ParameterInfo pi in pri.GetSetMethod ().GetParameters ())
+ WriteArg (pi);
+ writer.WriteEndElement ();
+ }
+ */
+ }
+
+ public void WriteSignal (EventInfo ei)
+ {
+ writer.WriteStartElement ("signal");
+ writer.WriteAttributeString ("name", ei.Name);
+
+ foreach (ParameterInfo pi in ei.EventHandlerType.GetMethod ("Invoke").GetParameters ())
+ WriteArgReverse (pi);
+
+ if (ExtendedAnnotations) {
+ string handlerName = Mapper.GetInterfaceName (ei.EventHandlerType);
+ WriteAnnotation ("org.ndesk.DBus.SignalHandler", handlerName);
+ }
+
+ WriteAnnotations (ei);
+
+ //no need to consider the delegate return value as dbus doesn't support it
+ writer.WriteEndElement ();
+ }
+
+ const BindingFlags relevantBindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
+
+ public void WriteInterface (Type type)
+ {
+ if (type == null)
+ return;
+
+ //TODO: this is unreliable, fix it
+ if (!Mapper.IsPublic (type))
+ return;
+
+ writer.WriteStartElement ("interface");
+
+ writer.WriteAttributeString ("name", Mapper.GetInterfaceName (type));
+
+ /*
+ foreach (MemberInfo mbi in type.GetMembers (relevantBindingFlags)) {
+ switch (mbi.MemberType) {
+ case MemberTypes.Method:
+ if (!((MethodInfo)mbi).IsSpecialName)
+ WriteMethod ((MethodInfo)mbi);
+ break;
+ case MemberTypes.Event:
+ WriteSignal ((EventInfo)mbi);
+ break;
+ case MemberTypes.Property:
+ WriteProperty ((PropertyInfo)mbi);
+ break;
+ default:
+ Console.Error.WriteLine ("Warning: Unhandled MemberType '{0}' encountered while introspecting {1}", mbi.MemberType, type.FullName);
+ break;
+ }
+ }
+ */
+
+ foreach (MethodInfo mi in type.GetMethods (relevantBindingFlags))
+ if (!mi.IsSpecialName)
+ WriteMethod (mi);
+
+ foreach (EventInfo ei in type.GetEvents (relevantBindingFlags))
+ WriteSignal (ei);
+
+ foreach (PropertyInfo pri in type.GetProperties (relevantBindingFlags))
+ WriteProperty (pri);
+
+ //TODO: indexers
+
+ //TODO: attributes as annotations?
+
+ writer.WriteEndElement ();
+
+ //this recursion seems somewhat inelegant
+ WriteInterface (type.BaseType);
+ }
+
+ public void WriteAnnotations (ICustomAttributeProvider attrProvider)
+ {
+ if (Mapper.IsDeprecated (attrProvider))
+ WriteAnnotation ("org.freedesktop.DBus.Deprecated", "true");
+ }
+
+ public void WriteAnnotation (string name, string value)
+ {
+ writer.WriteStartElement ("annotation");
+
+ writer.WriteAttributeString ("name", name);
+ writer.WriteAttributeString ("value", value);
+
+ writer.WriteEndElement ();
+ }
+
+ //this is not in the spec, and is not finalized
+ public void WriteEnum (Type type)
+ {
+ writer.WriteStartElement ("enum");
+ writer.WriteAttributeString ("name", Mapper.GetInterfaceName (type));
+ writer.WriteAttributeString ("type", Signature.GetSig (type.GetElementType ()).Value);
+ writer.WriteAttributeString ("flags", (type.IsDefined (typeof (FlagsAttribute), false)) ? "true" : "false");
+
+ string[] names = Enum.GetNames (type);
+
+ int i = 0;
+ foreach (Enum val in Enum.GetValues (type)) {
+ writer.WriteStartElement ("element");
+ writer.WriteAttributeString ("name", names[i++]);
+ writer.WriteAttributeString ("value", val.ToString ("d"));
+ writer.WriteEndElement ();
+ }
+
+ writer.WriteEndElement ();
+ }
+ }
+}
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..8078edc
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,68 @@
+ASSEMBLY = dbus-sharp
+TARGET = $(ASSEMBLY).dll
+
+CSFLAGS = \
+ -debug -target:library -unsafe -d:STRONG_NAME -keyfile:$(top_srcdir)/dbus-sharp.snk
+
+LIBFLAGS = \
+ -r:Mono.Posix
+
+CSFILES = \
+ $(srcdir)/Address.cs \
+ $(srcdir)/Authentication.cs \
+ $(srcdir)/Bus.cs \
+ $(srcdir)/BusObject.cs \
+ $(srcdir)/Connection.cs \
+ $(srcdir)/DBus.cs \
+ $(srcdir)/DProxy.cs \
+ $(srcdir)/ExportObject.cs \
+ $(srcdir)/Introspection.cs \
+ $(srcdir)/Protocol.cs \
+ $(srcdir)/Mapper.cs \
+ $(srcdir)/MatchRule.cs \
+ $(srcdir)/Message.cs \
+ $(srcdir)/MessageFilter.cs \
+ $(srcdir)/MessageReader.cs \
+ $(srcdir)/MessageWriter.cs \
+ $(srcdir)/PendingCall.cs \
+ $(srcdir)/Signature.cs \
+ $(srcdir)/SocketTransport.cs \
+ $(srcdir)/Transport.cs \
+ $(srcdir)/TypeImplementer.cs \
+ $(srcdir)/TypeRental.cs \
+ $(srcdir)/Unix.cs \
+ $(srcdir)/UnixNativeTransport.cs \
+ $(srcdir)/UnixTransport.cs \
+ $(srcdir)/Wrapper.cs
+
+all: $(TARGET)
+
+$(TARGET): $(CSFILES) AssemblyInfo.cs
+ $(GMCS) -out:$@ $(CSFLAGS) $(LIBFLAGS) $^
+
+install-data-local: $(TARGET)
+ @if test -n '$(TARGET)'; then \
+ echo "$(GACUTIL) /i $(TARGET) /f /gacdir $(DESTDIR)$(libdir)"; \
+ $(GACUTIL) /i $(TARGET) /package $(PACKAGE)-$(API_VERSION) /f /gacdir $(libdir) /root $(DESTDIR)$(libdir) || exit 1; \
+ fi
+
+uninstall-local:
+ @if test -n '$(TARGET)'; then \
+ echo "$(GACUTIL) /u $(ASSEMBLY) /gacdir $(DESTDIR)$(libdir)"; \
+ $(GACUTIL) /u $(ASSEMBLY) /package $(PACKAGE)-$(API_VERSION) /gacdir $(libdir) /root $(DESTDIR)$(libdir) || exit 1; \
+ fi
+
+EXTRA_DIST = \
+ $(CSFILES) \
+ $(srcdir)/dbus-sharp.dll.config \
+ $(srcdir)/AssemblyInfo.cs.in
+
+CLEANFILES = \
+ $(TARGET) \
+ $(TARGET).mdb
+
+DISTCLEANFILES = \
+ AssemblyInfo.cs
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..dacdb8d
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,382 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = src
+DIST_COMMON = $(srcdir)/AssemblyInfo.cs.in $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES = AssemblyInfo.cs
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+API_VERSION = @API_VERSION@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+GACUTIL = @GACUTIL@
+GMCS = @GMCS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MONO_CFLAGS = @MONO_CFLAGS@
+MONO_LIBS = @MONO_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+am__leading_dot = @am__leading_dot@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ASSEMBLY = dbus-sharp
+TARGET = $(ASSEMBLY).dll
+CSFLAGS = \
+ -debug -target:library -unsafe -d:STRONG_NAME -keyfile:$(top_srcdir)/dbus-sharp.snk
+
+LIBFLAGS = \
+ -r:Mono.Posix
+
+CSFILES = \
+ $(srcdir)/Address.cs \
+ $(srcdir)/Authentication.cs \
+ $(srcdir)/Bus.cs \
+ $(srcdir)/BusObject.cs \
+ $(srcdir)/Connection.cs \
+ $(srcdir)/DBus.cs \
+ $(srcdir)/DProxy.cs \
+ $(srcdir)/ExportObject.cs \
+ $(srcdir)/Introspection.cs \
+ $(srcdir)/Protocol.cs \
+ $(srcdir)/Mapper.cs \
+ $(srcdir)/MatchRule.cs \
+ $(srcdir)/Message.cs \
+ $(srcdir)/MessageFilter.cs \
+ $(srcdir)/MessageReader.cs \
+ $(srcdir)/MessageWriter.cs \
+ $(srcdir)/PendingCall.cs \
+ $(srcdir)/Signature.cs \
+ $(srcdir)/SocketTransport.cs \
+ $(srcdir)/Transport.cs \
+ $(srcdir)/TypeImplementer.cs \
+ $(srcdir)/TypeRental.cs \
+ $(srcdir)/Unix.cs \
+ $(srcdir)/UnixNativeTransport.cs \
+ $(srcdir)/UnixTransport.cs \
+ $(srcdir)/Wrapper.cs
+
+EXTRA_DIST = \
+ $(CSFILES) \
+ $(srcdir)/dbus-sharp.dll.config \
+ $(srcdir)/AssemblyInfo.cs.in
+
+CLEANFILES = \
+ $(TARGET) \
+ $(TARGET).mdb
+
+DISTCLEANFILES = \
+ AssemblyInfo.cs
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+AssemblyInfo.cs: $(top_builddir)/config.status $(srcdir)/AssemblyInfo.cs.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-local
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-local install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am uninstall uninstall-am uninstall-local
+
+
+all: $(TARGET)
+
+$(TARGET): $(CSFILES) AssemblyInfo.cs
+ $(GMCS) -out:$@ $(CSFLAGS) $(LIBFLAGS) $^
+
+install-data-local: $(TARGET)
+ @if test -n '$(TARGET)'; then \
+ echo "$(GACUTIL) /i $(TARGET) /f /gacdir $(DESTDIR)$(libdir)"; \
+ $(GACUTIL) /i $(TARGET) /package $(PACKAGE)-$(API_VERSION) /f /gacdir $(libdir) /root $(DESTDIR)$(libdir) || exit 1; \
+ fi
+
+uninstall-local:
+ @if test -n '$(TARGET)'; then \
+ echo "$(GACUTIL) /u $(ASSEMBLY) /gacdir $(DESTDIR)$(libdir)"; \
+ $(GACUTIL) /u $(ASSEMBLY) /package $(PACKAGE)-$(API_VERSION) /gacdir $(libdir) /root $(DESTDIR)$(libdir) || exit 1; \
+ fi
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/Mapper.cs b/src/Mapper.cs
new file mode 100644
index 0000000..4f223bc
--- /dev/null
+++ b/src/Mapper.cs
@@ -0,0 +1,389 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace DBus
+{
+ static class Mapper
+ {
+ //TODO: move these Get*Name helpers somewhere more appropriate
+ public static string GetArgumentName (ParameterInfo pi)
+ {
+ string argName = pi.Name;
+
+ if (pi.IsRetval && String.IsNullOrEmpty (argName))
+ argName = "ret";
+
+ return GetArgumentName ((ICustomAttributeProvider)pi, argName);
+ }
+
+ public static string GetArgumentName (ICustomAttributeProvider attrProvider, string defaultName)
+ {
+ string argName = defaultName;
+
+ //TODO: no need for foreach
+ foreach (ArgumentAttribute aa in attrProvider.GetCustomAttributes (typeof (ArgumentAttribute), true))
+ argName = aa.Name;
+
+ return argName;
+ }
+
+ //TODO: these two methods are quite messy and need review
+ public static IEnumerable<MemberInfo> GetPublicMembers (Type type)
+ {
+ //note that Type.GetInterfaces() returns all interfaces with flattened hierarchy
+ foreach (Type ifType in type.GetInterfaces ())
+ foreach (MemberInfo mi in GetDeclaredPublicMembers (ifType))
+ yield return mi;
+
+ if (IsPublic (type))
+ foreach (MemberInfo mi in GetDeclaredPublicMembers (type))
+ yield return mi;
+ }
+
+ static IEnumerable<MemberInfo> GetDeclaredPublicMembers (Type type)
+ {
+ if (IsPublic (type))
+ foreach (MemberInfo mi in type.GetMembers (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
+ yield return mi;
+ }
+
+ //this method walks the interface tree in an undefined manner and returns the first match, or if no matches are found, null
+ //the logic needs review and cleanup
+ //TODO: unify member name mapping as is already done with interfaces and args
+ public static MethodInfo GetMethod (Type type, MethodCall method_call)
+ {
+ foreach (MemberInfo member in Mapper.GetPublicMembers (type)) {
+ //this could be made more efficient by using the given interface name earlier and avoiding walking through all public interfaces
+ if (method_call.Interface != null)
+ if (GetInterfaceName (member) != method_call.Interface)
+ continue;
+
+ MethodInfo meth = null;
+ Type[] inTypes = null;
+
+ if (member is PropertyInfo) {
+ PropertyInfo prop = member as PropertyInfo;
+
+ MethodInfo getter = prop.GetGetMethod (false);
+ MethodInfo setter = prop.GetSetMethod (false);
+
+ if (getter != null && "Get" + prop.Name == method_call.Member) {
+ meth = getter;
+ inTypes = Type.EmptyTypes;
+ } else if (setter != null && "Set" + prop.Name == method_call.Member) {
+ meth = setter;
+ inTypes = new Type[] {prop.PropertyType};
+ }
+ } else {
+ meth = member as MethodInfo;
+
+ if (meth == null)
+ continue;
+
+ if (meth.Name != method_call.Member)
+ continue;
+
+ inTypes = Mapper.GetTypes (ArgDirection.In, meth.GetParameters ());
+ }
+
+ if (meth == null || inTypes == null)
+ continue;
+
+ Signature inSig = Signature.GetSig (inTypes);
+
+ if (inSig != method_call.Signature)
+ continue;
+
+ return meth;
+ }
+
+ return null;
+ }
+
+ public static bool IsPublic (MemberInfo mi)
+ {
+ return IsPublic (mi.DeclaringType);
+ }
+
+ public static bool IsPublic (Type type)
+ {
+ //we need to have a proper look at what's really public at some point
+ //this will do for now
+
+ if (type.IsDefined (typeof (InterfaceAttribute), false))
+ return true;
+
+ if (type.IsSubclassOf (typeof (MarshalByRefObject)))
+ return true;
+
+ return false;
+ }
+
+ public static string GetInterfaceName (MemberInfo mi)
+ {
+ return GetInterfaceName (mi.DeclaringType);
+ }
+
+ public static string GetInterfaceName (Type type)
+ {
+ string interfaceName = type.FullName;
+
+ //TODO: better fallbacks and namespace mangling when no InterfaceAttribute is available
+
+ //TODO: no need for foreach
+ foreach (InterfaceAttribute ia in type.GetCustomAttributes (typeof (InterfaceAttribute), true))
+ interfaceName = ia.Name;
+
+ return interfaceName;
+ }
+
+ public static Type[] GetTypes (ArgDirection dir, ParameterInfo[] parms)
+ {
+ List<Type> types = new List<Type> ();
+
+ //TODO: consider InOut/Ref
+
+ for (int i = 0 ; i != parms.Length ; i++) {
+ switch (dir) {
+ case ArgDirection.In:
+ //docs say IsIn isn't reliable, and this is indeed true
+ //if (parms[i].IsIn)
+ if (!parms[i].IsOut)
+ types.Add (parms[i].ParameterType);
+ break;
+ case ArgDirection.Out:
+ if (parms[i].IsOut) {
+ //TODO: note that IsOut is optional to the compiler, we may want to use IsByRef instead
+ //eg: if (parms[i].ParameterType.IsByRef)
+ types.Add (parms[i].ParameterType.GetElementType ());
+ }
+ break;
+ }
+ }
+
+ return types.ToArray ();
+ }
+
+ public static bool IsDeprecated (ICustomAttributeProvider attrProvider)
+ {
+ return attrProvider.IsDefined (typeof (ObsoleteAttribute), true);
+ }
+
+ static bool AreEqual (Type[] a, Type[] b)
+ {
+ if (a.Length != b.Length)
+ return false;
+
+ for (int i = 0 ; i != a.Length ; i++)
+ if (a[i] != b[i])
+ return false;
+
+ return true;
+ }
+
+ //workaround for Mono bug #81035 (memory leak)
+ static List<Type> genTypes = new List<Type> ();
+ internal static Type GetGenericType (Type defType, Type[] parms)
+ {
+ lock (genTypes) {
+ foreach (Type genType in genTypes) {
+ if (genType.GetGenericTypeDefinition () != defType)
+ continue;
+
+ Type[] genParms = genType.GetGenericArguments ();
+
+ if (!AreEqual (genParms, parms))
+ continue;
+
+ return genType;
+ }
+
+ Type type = defType.MakeGenericType (parms);
+ genTypes.Add (type);
+ return type;
+ }
+ }
+ }
+
+ //TODO: this class is messy, move the methods somewhere more appropriate
+ static class MessageHelper
+ {
+ public static Message CreateUnknownMethodError (MethodCall method_call)
+ {
+ if (!method_call.message.ReplyExpected)
+ return null;
+
+ string errMsg = String.Format ("Method \"{0}\" with signature \"{1}\" on interface \"{2}\" doesn't exist", method_call.Member, method_call.Signature.Value, method_call.Interface);
+
+ Error error = new Error ("org.freedesktop.DBus.Error.UnknownMethod", method_call.message.Header.Serial);
+ error.message.Signature = new Signature (DType.String);
+
+ MessageWriter writer = new MessageWriter (Connection.NativeEndianness);
+ writer.Write (errMsg);
+ error.message.Body = writer.ToArray ();
+
+ //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
+ if (method_call.Sender != null)
+ error.message.Header[FieldCode.Destination] = method_call.Sender;
+
+ return error.message;
+ }
+
+ public static void WriteDynamicValues (MessageWriter mw, ParameterInfo[] parms, object[] vals)
+ {
+ foreach (ParameterInfo parm in parms) {
+ if (!parm.IsOut)
+ continue;
+
+ Type actualType = parm.ParameterType.GetElementType ();
+ mw.Write (actualType, vals[parm.Position]);
+ }
+ }
+
+ public static object[] GetDynamicValues (Message msg, ParameterInfo[] parms)
+ {
+ //TODO: this validation check should provide better information, eg. message dump or a stack trace, or at least the interface/member
+ /*
+ if (Protocol.Verbose) {
+ Signature expected = Signature.GetSig (types);
+ Signature actual = msg.Signature;
+ if (actual != expected)
+ Console.Error.WriteLine ("Warning: The signature of the message does not match that of the handler: " + "Expected '" + expected + "', got '" + actual + "'");
+ }
+ */
+
+ object[] vals = new object[parms.Length];
+
+ if (msg.Body != null) {
+ MessageReader reader = new MessageReader (msg);
+ foreach (ParameterInfo parm in parms) {
+ if (parm.IsOut)
+ continue;
+
+ vals[parm.Position] = reader.ReadValue (parm.ParameterType);
+ }
+ }
+
+ return vals;
+ }
+
+ public static object[] GetDynamicValues (Message msg, Type[] types)
+ {
+ //TODO: this validation check should provide better information, eg. message dump or a stack trace, or at least the interface/member
+ if (Protocol.Verbose) {
+ Signature expected = Signature.GetSig (types);
+ Signature actual = msg.Signature;
+ if (actual != expected)
+ Console.Error.WriteLine ("Warning: The signature of the message does not match that of the handler: " + "Expected '" + expected + "', got '" + actual + "'");
+ }
+
+ object[] vals = new object[types.Length];
+
+ if (msg.Body != null) {
+ MessageReader reader = new MessageReader (msg);
+
+ for (int i = 0 ; i != types.Length ; i++)
+ vals[i] = reader.ReadValue (types[i]);
+ }
+
+ return vals;
+ }
+
+ public static object[] GetDynamicValues (Message msg)
+ {
+ Type[] types = msg.Signature.ToTypes ();
+ return GetDynamicValues (msg, types);
+ }
+
+ public static Message ConstructReply (MethodCall method_call, params object[] vals)
+ {
+ MethodReturn method_return = new MethodReturn (method_call.message.Header.Serial);
+ Message replyMsg = method_return.message;
+
+ Signature inSig = Signature.GetSig (vals);
+
+ if (vals != null && vals.Length != 0) {
+ MessageWriter writer = new MessageWriter (Connection.NativeEndianness);
+
+ foreach (object arg in vals)
+ writer.Write (arg.GetType (), arg);
+
+ replyMsg.Body = writer.ToArray ();
+ }
+
+ //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
+ if (method_call.Sender != null)
+ replyMsg.Header[FieldCode.Destination] = method_call.Sender;
+
+ replyMsg.Signature = inSig;
+
+ //replyMsg.WriteHeader ();
+
+ return replyMsg;
+ }
+
+ public static Message ConstructDynamicReply (MethodCall method_call, MethodInfo mi, object retVal, object[] vals)
+ {
+ Type retType = mi.ReturnType;
+
+ MethodReturn method_return = new MethodReturn (method_call.message.Header.Serial);
+ Message replyMsg = method_return.message;
+
+ Signature outSig = Signature.GetSig (retType);
+ outSig += Signature.GetSig (Mapper.GetTypes (ArgDirection.Out, mi.GetParameters ()));
+
+ if (outSig != Signature.Empty) {
+ MessageWriter writer = new MessageWriter (Connection.NativeEndianness);
+
+ //first write the return value, if any
+ if (retType != null && retType != typeof (void))
+ writer.Write (retType, retVal);
+
+ //then write the out args
+ WriteDynamicValues (writer, mi.GetParameters (), vals);
+
+ replyMsg.Body = writer.ToArray ();
+ }
+
+ //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
+ if (method_call.Sender != null)
+ replyMsg.Header[FieldCode.Destination] = method_call.Sender;
+
+ replyMsg.Signature = outSig;
+
+ return replyMsg;
+ }
+ }
+
+ [AttributeUsage (AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
+ public class InterfaceAttribute : Attribute
+ {
+ public string Name;
+
+ public InterfaceAttribute (string name)
+ {
+ this.Name = name;
+ }
+ }
+
+ [AttributeUsage (AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple=false, Inherited=true)]
+ public class ArgumentAttribute : Attribute
+ {
+ public string Name;
+
+ public ArgumentAttribute (string name)
+ {
+ this.Name = name;
+ }
+
+ public static string GetSignatureString (Type type)
+ {
+ return Signature.GetSig (type).Value;
+ }
+ }
+}
diff --git a/src/MatchRule.cs b/src/MatchRule.cs
new file mode 100644
index 0000000..317c171
--- /dev/null
+++ b/src/MatchRule.cs
@@ -0,0 +1,319 @@
+// Copyright 2007 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Collections.Generic;
+
+namespace DBus
+{
+ class MatchRule
+ {
+ public MessageType? MessageType;
+ public readonly SortedList<FieldCode,MatchTest> Fields = new SortedList<FieldCode,MatchTest> ();
+ //public readonly SortedList<int,MatchTest> Args = new SortedList<int,MatchTest> ();
+ public readonly HashSet<ArgMatchTest> Args = new HashSet<ArgMatchTest> ();
+
+ public MatchRule ()
+ {
+ }
+
+ static void Append (StringBuilder sb, string key, object value)
+ {
+ Append (sb, key, value.ToString ());
+ }
+
+ static void Append (StringBuilder sb, string key, string value)
+ {
+ if (sb.Length != 0)
+ sb.Append (',');
+
+ sb.Append (key);
+ sb.Append ("='");
+ sb.Append (value.Replace (@"\", @"\\").Replace (@"'", @"\'"));
+ sb.Append ('\'');
+ }
+
+ static void AppendArg (StringBuilder sb, int index, string value)
+ {
+ Append (sb, "arg" + index, value);
+ }
+
+ static void AppendPathArg (StringBuilder sb, int index, ObjectPath value)
+ {
+ Append (sb, "arg" + index + "path", value.ToString ());
+ }
+
+ public override bool Equals (object o)
+ {
+ MatchRule r = o as MatchRule;
+ if (o == null)
+ return false;
+
+ return ToString () == r.ToString ();
+ }
+
+ public override int GetHashCode ()
+ {
+ //FIXME: not at all optimal
+ return ToString ().GetHashCode ();
+ }
+
+ public override string ToString ()
+ {
+ StringBuilder sb = new StringBuilder ();
+
+ if (MessageType != null)
+ Append (sb, "type", MessageFilter.MessageTypeToString ((MessageType)MessageType));
+
+ // Note that fdo D-Bus daemon sorts in a different order.
+ // It shouldn't matter though as long as we're consistent.
+ foreach (KeyValuePair<FieldCode,MatchTest> pair in Fields) {
+ Append (sb, pair.Key.ToString ().ToLower (), pair.Value.Value);
+ }
+
+ // Sorting the list here is not ideal
+ List<ArgMatchTest> tests = new List<ArgMatchTest> (Args);
+ tests.Sort ( delegate (ArgMatchTest aa, ArgMatchTest bb) { return aa.ArgNum - bb.ArgNum; } );
+
+ if (Args != null)
+ foreach (ArgMatchTest test in tests)
+ if (test.Signature == Signature.StringSig)
+ AppendArg (sb, test.ArgNum, (string)test.Value);
+ else if (test.Signature == Signature.ObjectPathSig)
+ AppendPathArg (sb, test.ArgNum, (ObjectPath)test.Value);
+
+ return sb.ToString ();
+ }
+
+ public static void Test (HashSet<ArgMatchTest> a, Message msg)
+ {
+ List<Signature> sigs = new List<Signature> ();
+ sigs.AddRange (msg.Signature.GetParts ());
+
+ if (sigs.Count == 0) {
+ a.Clear ();
+ return;
+ }
+
+ a.RemoveWhere ( delegate (ArgMatchTest t) { return t.ArgNum >= sigs.Count || t.Signature != sigs[t.ArgNum]; } );
+
+ // Sorting the list here is not ideal
+ List<ArgMatchTest> tests = new List<ArgMatchTest> (a);
+ tests.Sort ( delegate (ArgMatchTest aa, ArgMatchTest bb) { return aa.ArgNum - bb.ArgNum; } );
+
+ if (tests.Count == 0) {
+ a.Clear ();
+ return;
+ }
+
+ MessageReader reader = new MessageReader (msg);
+
+ int argNum = 0;
+ foreach (ArgMatchTest test in tests) {
+ if (argNum > test.ArgNum) {
+ // This test cannot pass because a previous test already did.
+ // So we already know it will fail without even trying.
+ // This logic will need to be changed to support wildcards.
+ a.Remove (test);
+ continue;
+ }
+
+ while (argNum != test.ArgNum) {
+ Signature sig = sigs[argNum];
+ if (!reader.StepOver (sig))
+ throw new Exception ();
+ argNum++;
+ }
+
+ // TODO: Avoid re-reading values
+ int savedPos = reader.pos;
+ if (!reader.ReadValue (test.Signature[0]).Equals (test.Value)) {
+ a.Remove (test);
+ reader.pos = savedPos;
+ continue;
+ }
+
+ argNum++;
+ }
+ }
+
+ public bool MatchesHeader (Message msg)
+ {
+ if (MessageType != null)
+ if (msg.Header.MessageType != MessageType)
+ return false;
+
+ foreach (KeyValuePair<FieldCode,MatchTest> pair in Fields) {
+ object value;
+ if (!msg.Header.Fields.TryGetValue ((byte)pair.Key, out value))
+ return false;
+ if (!pair.Value.Value.Equals (value))
+ return false;
+ }
+
+ return true;
+ }
+
+ static Regex argNRegex = new Regex (@"^arg(\d+)(path)?$");
+ static Regex matchRuleRegex = new Regex (@"(\w+)\s*=\s*'((\\\\|\\'|[^'\\])*)'", RegexOptions.Compiled);
+ public static MatchRule Parse (string text)
+ {
+ if (text.Length > Protocol.MaxMatchRuleLength)
+ throw new Exception ("Match rule length exceeds maximum " + Protocol.MaxMatchRuleLength + " characters");
+
+ MatchRule r = new MatchRule ();
+
+ // TODO: Stricter validation. Tighten up the regex.
+ // It currently succeeds and silently drops malformed test parts.
+
+ for (Match m = matchRuleRegex.Match (text) ; m.Success ; m = m.NextMatch ()) {
+ string key = m.Groups[1].Value;
+ string value = m.Groups[2].Value;
+ // This unescaping may not be perfect..
+ value = value.Replace (@"\\", @"\");
+ value = value.Replace (@"\'", @"'");
+
+ if (key.StartsWith ("arg")) {
+ Match mArg = argNRegex.Match (key);
+ if (!mArg.Success)
+ return null;
+ int argNum = (int)UInt32.Parse (mArg.Groups[1].Value);
+
+ if (argNum < 0 || argNum >= Protocol.MaxMatchRuleArgs)
+ throw new Exception ("arg match must be between 0 and " + (Protocol.MaxMatchRuleArgs - 1) + " inclusive");
+
+ //if (r.Args.ContainsKey (argNum))
+ // return null;
+
+ string argType = mArg.Groups[2].Value;
+
+ if (argType == "path")
+ r.Args.Add (new ArgMatchTest (argNum, new ObjectPath (value)));
+ else
+ r.Args.Add (new ArgMatchTest (argNum, value));
+
+ continue;
+ }
+
+ //TODO: more consistent error handling
+ switch (key) {
+ case "type":
+ if (r.MessageType != null)
+ return null;
+ r.MessageType = MessageFilter.StringToMessageType (value);
+ break;
+ case "interface":
+ r.Fields[FieldCode.Interface] = new MatchTest (value);
+ break;
+ case "member":
+ r.Fields[FieldCode.Member] = new MatchTest (value);
+ break;
+ case "path":
+ r.Fields[FieldCode.Path] = new MatchTest (new ObjectPath (value));
+ break;
+ case "sender":
+ r.Fields[FieldCode.Sender] = new MatchTest (value);
+ break;
+ case "destination":
+ r.Fields[FieldCode.Destination] = new MatchTest (value);
+ break;
+ default:
+ if (Protocol.Verbose)
+ Console.Error.WriteLine ("Warning: Unrecognized match rule key: " + key);
+ break;
+ }
+ }
+
+ return r;
+ }
+ }
+
+ class HeaderTest : MatchTest
+ {
+ public FieldCode Field;
+ public HeaderTest (FieldCode field, object value)
+ {
+ Field = field;
+ Signature = Signature.GetSig (value.GetType ());
+ Value = value;
+ }
+ }
+
+ struct ArgMatchTest
+ {
+ public int ArgNum;
+ public Signature Signature;
+ public object Value;
+
+ public ArgMatchTest (int argNum, string value)
+ {
+ ArgNum = argNum;
+ Signature = Signature.StringSig;
+ Value = value;
+ }
+
+ public ArgMatchTest (int argNum, ObjectPath value)
+ {
+ ArgNum = argNum;
+ Signature = Signature.ObjectPathSig;
+ Value = value;
+ }
+
+ public override int GetHashCode ()
+ {
+ return Signature.GetHashCode () ^ Value.GetHashCode () ^ ArgNum;
+ }
+ }
+
+ /*
+ class ArgMatchTest : MatchTest
+ {
+ public int ArgNum;
+
+ public ArgMatchTest (int argNum, string value) : base (value)
+ {
+ ArgNum = argNum;
+ }
+
+ public ArgMatchTest (int argNum, ObjectPath value) : base (value)
+ {
+ ArgNum = argNum;
+ }
+
+ public override int GetHashCode ()
+ {
+ return base.GetHashCode () ^ ArgNum;
+ }
+ }
+ */
+
+ class MatchTest
+ {
+ public Signature Signature;
+ public object Value;
+
+ public override int GetHashCode ()
+ {
+ return Signature.GetHashCode () ^ Value.GetHashCode ();
+ }
+
+ protected MatchTest ()
+ {
+ }
+
+ public MatchTest (string value)
+ {
+ Signature = Signature.StringSig;
+ Value = value;
+ }
+
+ public MatchTest (ObjectPath value)
+ {
+ Signature = Signature.ObjectPathSig;
+ Value = value;
+ }
+ }
+}
diff --git a/src/Message.cs b/src/Message.cs
new file mode 100644
index 0000000..9487e12
--- /dev/null
+++ b/src/Message.cs
@@ -0,0 +1,499 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace DBus
+{
+ class Message
+ {
+ public Message ()
+ {
+ Header.Endianness = Connection.NativeEndianness;
+ Header.MessageType = MessageType.MethodCall;
+ Header.Flags = HeaderFlag.NoReplyExpected; //TODO: is this the right place to do this?
+ Header.MajorVersion = Protocol.Version;
+ Header.Fields = new Dictionary<byte, object> ();
+ }
+
+ public Header Header = new Header ();
+
+ public Connection Connection;
+
+ public Signature Signature
+ {
+ get {
+ object o = Header[FieldCode.Signature];
+ if (o == null)
+ return Signature.Empty;
+ else
+ return (Signature)o;
+ } set {
+ if (value == Signature.Empty)
+ Header[FieldCode.Signature] = null;
+ else
+ Header[FieldCode.Signature] = value;
+ }
+ }
+
+ public bool ReplyExpected
+ {
+ get {
+ return (Header.Flags & HeaderFlag.NoReplyExpected) == HeaderFlag.None;
+ } set {
+ if (value)
+ Header.Flags &= ~HeaderFlag.NoReplyExpected; //flag off
+ else
+ Header.Flags |= HeaderFlag.NoReplyExpected; //flag on
+ }
+ }
+
+ //public HeaderField[] HeaderFields;
+ //public Dictionary<FieldCode,object>;
+
+ public byte[] Body;
+
+ //TODO: make use of Locked
+ /*
+ protected bool locked = false;
+ public bool Locked
+ {
+ get {
+ return locked;
+ }
+ }
+ */
+
+ public void HandleHeader (Header headerIn)
+ {
+ Header = headerIn;
+ }
+
+ static System.Reflection.MethodInfo hHandler = typeof (Message).GetMethod ("HandleHeader");
+ public void SetHeaderData (byte[] data)
+ {
+ EndianFlag endianness = (EndianFlag)data[0];
+ MessageReader reader = new MessageReader (endianness, data);
+
+ MethodCaller2 mCaller = ExportObject.GetMCaller (hHandler);
+ mCaller (this, reader, null, new MessageWriter ());
+ }
+
+ //public HeaderField[] Fields;
+
+ /*
+ public void SetHeaderData (byte[] data)
+ {
+ EndianFlag endianness = (EndianFlag)data[0];
+ MessageReader reader = new MessageReader (endianness, data);
+
+ Header = (Header)reader.ReadStruct (typeof (Header));
+ }
+ */
+
+ //TypeWriter<Header> headerWriter = TypeImplementer.GetTypeWriter<Header> ();
+ public byte[] GetHeaderData ()
+ {
+ if (Body != null)
+ Header.Length = (uint)Body.Length;
+
+ MessageWriter writer = new MessageWriter (Header.Endianness);
+
+ //writer.stream.Capacity = 512;
+ //headerWriter (writer, Header);
+
+ writer.Write ((byte)Header.Endianness);
+ writer.Write ((byte)Header.MessageType);
+ writer.Write ((byte)Header.Flags);
+ writer.Write (Header.MajorVersion);
+ writer.Write (Header.Length);
+ writer.Write (Header.Serial);
+ writer.WriteHeaderFields (Header.Fields);
+
+ writer.CloseWrite ();
+
+ return writer.ToArray ();
+ }
+
+ public void GetHeaderDataToStream (Stream stream)
+ {
+ if (Body != null)
+ Header.Length = (uint)Body.Length;
+
+ MessageWriter writer = new MessageWriter (Header.Endianness);
+
+ //headerWriter (writer, Header);
+
+ writer.Write ((byte)Header.Endianness);
+ writer.Write ((byte)Header.MessageType);
+ writer.Write ((byte)Header.Flags);
+ writer.Write (Header.MajorVersion);
+ writer.Write (Header.Length);
+ writer.Write (Header.Serial);
+ writer.WriteHeaderFields (Header.Fields);
+
+ writer.CloseWrite ();
+
+ writer.ToStream (stream);
+ }
+ }
+
+ // Allows conversion of complex variants via System.Convert
+ class DValue : IConvertible
+ {
+ // TODO: Note that we currently drop the originating Connection/Message details
+ // They may be useful later in conversion!
+
+ internal EndianFlag endianness;
+ internal Signature signature;
+ internal byte[] data;
+
+ public bool CanConvertTo (Type conversionType)
+ {
+ Signature typeSig = Signature.GetSig (conversionType);
+ return signature == typeSig;
+ }
+
+ public TypeCode GetTypeCode ()
+ {
+ return TypeCode.Object;
+ }
+
+ public object ToType (Type conversionType)
+ {
+ return ToType (conversionType, null);
+ }
+
+ public object ToType (Type conversionType, IFormatProvider provider)
+ {
+ Signature typeSig = Signature.GetSig (conversionType);
+ if (typeSig != signature)
+ throw new InvalidCastException ();
+
+ MessageReader reader = new MessageReader (endianness, data);
+ return reader.ReadValue (conversionType);
+ }
+
+ public override string ToString ()
+ {
+ // Seems a reasonable way of providing the signature to the API layer
+ return signature.ToString ();
+ }
+
+ // IConvertible implementation:
+
+ /*
+ public TypeCode GetTypeCode ()
+ {
+ throw new NotSupportedException ();
+ }
+ */
+
+ public bool ToBoolean (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public byte ToByte (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public char ToChar (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public DateTime ToDateTime (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public decimal ToDecimal (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public double ToDouble (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public short ToInt16 (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public int ToInt32 (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public long ToInt64 (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public sbyte ToSByte (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public float ToSingle (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public string ToString (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ /*
+ public object ToType (Type conversionType, IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+ */
+
+ public ushort ToUInt16 (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public uint ToUInt32 (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public ulong ToUInt64 (IFormatProvider provider)
+ {
+ throw new NotSupportedException ();
+ }
+ }
+
+ partial class MessageReader
+ {
+ // Note: This method doesn't support aggregate signatures
+ public bool StepOver (Signature sig)
+ {
+ if (sig == Signature.VariantSig) {
+ Signature valueSig = ReadSignature ();
+ return StepOver (valueSig);
+ }
+
+ if (sig == Signature.StringSig) {
+ uint valueLength = ReadUInt32 ();
+ pos += (int)valueLength;
+ pos++;
+ return true;
+ }
+
+ if (sig == Signature.ObjectPathSig) {
+ uint valueLength = ReadUInt32 ();
+ pos += (int)valueLength;
+ pos++;
+ return true;
+ }
+
+ if (sig == Signature.SignatureSig) {
+ byte valueLength = ReadByte ();
+ pos += valueLength;
+ pos++;
+ return true;
+ }
+
+ // No need to handle dicts specially. IsArray does the job
+ if (sig.IsArray) {
+ Signature elemSig = sig.GetElementSignature ();
+ uint ln = ReadUInt32 ();
+ pos = Protocol.Padded (pos, elemSig.Alignment);
+ pos += (int)ln;
+ return true;
+ }
+
+ int endPos = pos;
+ if (sig.GetFixedSize (ref endPos)) {
+ pos = endPos;
+ return true;
+ }
+
+ if (sig.IsDictEntry) {
+ pos = Protocol.Padded (pos, sig.Alignment);
+ Signature sigKey, sigValue;
+ sig.GetDictEntrySignatures (out sigKey, out sigValue);
+ if (!StepOver (sigKey))
+ return false;
+ if (!StepOver (sigValue))
+ return false;
+ return true;
+ }
+
+ if (sig.IsStruct) {
+ pos = Protocol.Padded (pos, sig.Alignment);
+ foreach (Signature fieldSig in sig.GetFieldSignatures ())
+ if (!StepOver (fieldSig))
+ return false;
+ return true;
+ }
+
+ throw new Exception ("Can't step over '" + sig + "'");
+ //return false;
+ }
+
+ public IEnumerable<Signature> StepInto (Signature sig)
+ {
+ if (sig == Signature.VariantSig) {
+ Signature valueSig = ReadSignature ();
+ yield return valueSig;
+ yield break;
+ }
+
+ // No need to handle dicts specially. IsArray does the job
+ if (sig.IsArray) {
+ Signature elemSig = sig.GetElementSignature ();
+ uint ln = ReadUInt32 ();
+ ReadPad (elemSig.Alignment);
+ int endPos = pos + (int)ln;
+ while (pos < endPos)
+ yield return elemSig;
+ yield break;
+ }
+
+ if (sig.IsDictEntry) {
+ pos = Protocol.Padded (pos, sig.Alignment);
+ Signature sigKey, sigValue;
+ sig.GetDictEntrySignatures (out sigKey, out sigValue);
+ yield return sigKey;
+ yield return sigValue;
+ yield break;
+ }
+
+ if (sig.IsStruct) {
+ pos = Protocol.Padded (pos, sig.Alignment);
+ foreach (Signature fieldSig in sig.GetFieldSignatures ())
+ yield return fieldSig;
+ yield break;
+ }
+
+ throw new Exception ("Can't step into '" + sig + "'");
+ //yield break;
+ }
+ }
+
+ class MessageDumper
+ {
+ public static byte[] ReadBlock (TextReader r)
+ {
+ //if (Body == null)
+ // return;
+
+ MemoryStream ms = new MemoryStream ();
+
+ while (true) {
+ string ln = r.ReadLine ();
+ if (ln == null)
+ break;
+ if (!ReadFromHex (ms, ln))
+ break;
+ }
+
+ if (ms.Length == 0)
+ return null;
+
+ return ms.ToArray ();
+ }
+
+ public static void WriteComment (string comment, TextWriter w)
+ {
+ w.WriteLine ("# " + comment);
+ }
+
+ public static void WriteBlock (byte[] Body, TextWriter w)
+ {
+ //if (Body == null)
+ // return;
+ if (Body != null)
+ for (int i = 0 ; i != Body.Length ; i++) {
+ if (i == 0) {}
+ else if (i % 32 == 0)
+ w.WriteLine ();
+ else if (i % 4 == 0)
+ w.Write (' ');
+
+ w.Write (Body[i].ToString ("x2", System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ w.Write ('.');
+ w.WriteLine ();
+ w.Flush ();
+ }
+
+ public static void WriteMessage (Message msg, TextWriter w)
+ {
+ w.WriteLine ("# Message");
+ w.WriteLine ("# Header");
+ MessageDumper.WriteBlock (msg.GetHeaderData (), w);
+ w.WriteLine ("# Body");
+ MessageDumper.WriteBlock (msg.Body, w);
+ w.WriteLine ();
+ w.Flush ();
+ }
+
+ public static Message ReadMessage (TextReader r)
+ {
+ byte[] header = MessageDumper.ReadBlock (r);
+
+ if (header == null)
+ return null;
+
+ byte[] body = MessageDumper.ReadBlock (r);
+
+ Message msg = new Message ();
+ msg.SetHeaderData (header);
+ msg.Body = body;
+
+ return msg;
+ }
+
+ static byte FromHexChar (char c)
+ {
+ if ((c >= 'a') && (c <= 'f'))
+ return (byte) (c - 'a' + 10);
+ if ((c >= 'A') && (c <= 'F'))
+ return (byte) (c - 'A' + 10);
+ if ((c >= '0') && (c <= '9'))
+ return (byte) (c - '0');
+ throw new ArgumentException ("Invalid hex char");
+ }
+
+ static bool ReadFromHex (Stream ms, string hex)
+ {
+ if (hex.StartsWith ("#"))
+ return true;
+
+ int i = 0;
+ while (i < hex.Length) {
+ if (char.IsWhiteSpace (hex [i])) {
+ i++;
+ continue;
+ }
+
+ if (hex [i] == '.') {
+ ms.Flush ();
+ return false;
+ }
+
+ byte res = (byte) (FromHexChar (hex [i++]) << 4);
+ res += FromHexChar (hex [i++]);
+ ms.WriteByte (res);
+ }
+
+ ms.Flush ();
+ return true;
+ }
+ }
+}
diff --git a/src/MessageFilter.cs b/src/MessageFilter.cs
new file mode 100644
index 0000000..9d2a042
--- /dev/null
+++ b/src/MessageFilter.cs
@@ -0,0 +1,58 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+
+namespace DBus
+{
+ class MessageFilter
+ {
+ //this should probably be made to use HeaderField or similar
+ //this class is not generalized yet
+
+ public static string MessageTypeToString (MessageType mtype)
+ {
+ switch (mtype)
+ {
+ case MessageType.MethodCall:
+ return "method_call";
+ case MessageType.MethodReturn:
+ return "method_return";
+ case MessageType.Error:
+ return "error";
+ case MessageType.Signal:
+ return "signal";
+ case MessageType.Invalid:
+ return "invalid";
+ default:
+ throw new Exception ("Bad MessageType: " + mtype);
+ }
+ }
+
+ public static MessageType StringToMessageType (string text)
+ {
+ switch (text)
+ {
+ case "method_call":
+ return MessageType.MethodCall;
+ case "method_return":
+ return MessageType.MethodReturn;
+ case "error":
+ return MessageType.Error;
+ case "signal":
+ return MessageType.Signal;
+ case "invalid":
+ return MessageType.Invalid;
+ default:
+ throw new Exception ("Bad MessageType: " + text);
+ }
+ }
+
+ //TODO: remove this -- left here for the benefit of the monitor tool for now
+ public static string CreateMatchRule (MessageType mtype)
+ {
+ return "type='" + MessageTypeToString (mtype) + "'";
+ }
+ }
+}
diff --git a/src/MessageReader.cs b/src/MessageReader.cs
new file mode 100644
index 0000000..758b1ac
--- /dev/null
+++ b/src/MessageReader.cs
@@ -0,0 +1,494 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Text;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+
+namespace DBus
+{
+ partial class MessageReader
+ {
+ protected EndianFlag endianness;
+ //protected byte[] data;
+ public byte[] data;
+ //TODO: this should be uint or long to handle long messages
+ //internal int pos = 0;
+ public int pos = 0;
+ protected Message message;
+
+ public MessageReader (EndianFlag endianness, byte[] data)
+ {
+ //if (data == null)
+ // throw new ArgumentNullException ("data");
+ if (data == null)
+ data = new byte[0];
+
+ this.endianness = endianness;
+ this.IsNativeEndian = endianness == Connection.NativeEndianness;
+ this.data = data;
+ }
+
+ public MessageReader (Message message) : this (message.Header.Endianness, message.Body)
+ {
+ if (message == null)
+ throw new ArgumentNullException ("message");
+
+ this.message = message;
+ }
+
+ public readonly bool IsNativeEndian;
+
+ public object ReadValue (Type type)
+ {
+ if (type == typeof (void))
+ return null;
+
+ if (type.IsArray) {
+ return ReadArray (type.GetElementType ());
+ } else if (type == typeof (ObjectPath)) {
+ return ReadObjectPath ();
+ } else if (type == typeof (Signature)) {
+ return ReadSignature ();
+ } else if (type == typeof (object)) {
+ return ReadVariant ();
+ } else if (type == typeof (string)) {
+ return ReadString ();
+ } else if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (IDictionary<,>)) {
+ Type[] genArgs = type.GetGenericArguments ();
+ //Type dictType = typeof (Dictionary<,>).MakeGenericType (genArgs);
+ //workaround for Mono bug #81035 (memory leak)
+ Type dictType = Mapper.GetGenericType (typeof (Dictionary<,>), genArgs);
+ System.Collections.IDictionary idict = (System.Collections.IDictionary)Activator.CreateInstance(dictType, new object[0]);
+ GetValueToDict (genArgs[0], genArgs[1], idict);
+ return idict;
+ } else if (Mapper.IsPublic (type)) {
+ return GetObject (type);
+ } else if (!type.IsPrimitive && !type.IsEnum) {
+ return ReadStruct (type);
+ } else {
+ object val;
+ DType dtype = Signature.TypeToDType (type);
+ val = ReadValue (dtype);
+
+ if (type.IsEnum)
+ val = Enum.ToObject (type, val);
+
+ return val;
+ }
+ }
+
+ //helper method, should not be used generally
+ public object ReadValue (DType dtype)
+ {
+ switch (dtype)
+ {
+ case DType.Byte:
+ return ReadByte ();
+
+ case DType.Boolean:
+ return ReadBoolean ();
+
+ case DType.Int16:
+ return ReadInt16 ();
+
+ case DType.UInt16:
+ return ReadUInt16 ();
+
+ case DType.Int32:
+ return ReadInt32 ();
+
+ case DType.UInt32:
+ return ReadUInt32 ();
+
+ case DType.Int64:
+ return ReadInt64 ();
+
+ case DType.UInt64:
+ return ReadUInt64 ();
+
+#if !DISABLE_SINGLE
+ case DType.Single:
+ return ReadSingle ();
+#endif
+
+ case DType.Double:
+ return ReadDouble ();
+
+ case DType.String:
+ return ReadString ();
+
+ case DType.ObjectPath:
+ return ReadObjectPath ();
+
+ case DType.Signature:
+ return ReadSignature ();
+
+ case DType.Variant:
+ return ReadVariant ();
+
+ default:
+ throw new Exception ("Unhandled D-Bus type: " + dtype);
+ }
+ }
+
+ public object GetObject (Type type)
+ {
+ ObjectPath path = ReadObjectPath ();
+
+ return message.Connection.GetObject (type, (string)message.Header[FieldCode.Sender], path);
+ }
+
+ public byte ReadByte ()
+ {
+ return data[pos++];
+ }
+
+ public bool ReadBoolean ()
+ {
+ uint intval = ReadUInt32 ();
+
+ switch (intval) {
+ case 0:
+ return false;
+ case 1:
+ return true;
+ default:
+ throw new Exception ("Read value " + intval + " at position " + pos + " while expecting boolean (0/1)");
+ }
+ }
+
+ unsafe protected void MarshalUShort (void* dstPtr)
+ {
+ ReadPad (2);
+
+ if (data.Length < pos + 2)
+ throw new Exception ("Cannot read beyond end of data");
+
+ if (endianness == Connection.NativeEndianness) {
+ fixed (byte* p = &data[pos])
+ *((ushort*)dstPtr) = *((ushort*)p);
+ } else {
+ byte* dst = (byte*)dstPtr;
+ dst[0] = data[pos + 1];
+ dst[1] = data[pos + 0];
+ }
+
+ pos += 2;
+ }
+
+ unsafe public short ReadInt16 ()
+ {
+ short val;
+
+ MarshalUShort (&val);
+
+ return val;
+ }
+
+ unsafe public ushort ReadUInt16 ()
+ {
+ ushort val;
+
+ MarshalUShort (&val);
+
+ return val;
+ }
+
+ unsafe protected void MarshalUInt (void* dstPtr)
+ {
+ ReadPad (4);
+
+ if (data.Length < pos + 4)
+ throw new Exception ("Cannot read beyond end of data");
+
+ if (endianness == Connection.NativeEndianness) {
+ fixed (byte* p = &data[pos])
+ *((uint*)dstPtr) = *((uint*)p);
+ } else {
+ byte* dst = (byte*)dstPtr;
+ dst[0] = data[pos + 3];
+ dst[1] = data[pos + 2];
+ dst[2] = data[pos + 1];
+ dst[3] = data[pos + 0];
+ }
+
+ pos += 4;
+ }
+
+ unsafe public int ReadInt32 ()
+ {
+ int val;
+
+ MarshalUInt (&val);
+
+ return val;
+ }
+
+ unsafe public uint ReadUInt32 ()
+ {
+ uint val;
+
+ MarshalUInt (&val);
+
+ return val;
+ }
+
+ unsafe protected void MarshalULong (void* dstPtr)
+ {
+ ReadPad (8);
+
+ if (data.Length < pos + 8)
+ throw new Exception ("Cannot read beyond end of data");
+
+ if (endianness == Connection.NativeEndianness) {
+ fixed (byte* p = &data[pos])
+ *((ulong*)dstPtr) = *((ulong*)p);
+ } else {
+ byte* dst = (byte*)dstPtr;
+ for (int i = 0; i < 8; ++i)
+ dst[i] = data[pos + (7 - i)];
+ }
+
+ pos += 8;
+ }
+
+ unsafe public long ReadInt64 ()
+ {
+ long val;
+
+ MarshalULong (&val);
+
+ return val;
+ }
+
+ unsafe public ulong ReadUInt64 ()
+ {
+ ulong val;
+
+ MarshalULong (&val);
+
+ return val;
+ }
+
+#if !DISABLE_SINGLE
+ unsafe public float ReadSingle ()
+ {
+ float val;
+
+ MarshalUInt (&val);
+
+ return val;
+ }
+#endif
+
+ unsafe public double ReadDouble ()
+ {
+ double val;
+
+ MarshalULong (&val);
+
+ return val;
+ }
+
+ public string ReadString ()
+ {
+ uint ln = ReadUInt32 ();
+
+ string val = Encoding.UTF8.GetString (data, pos, (int)ln);
+ pos += (int)ln;
+ ReadNull ();
+
+ return val;
+ }
+
+ public ObjectPath ReadObjectPath ()
+ {
+ //exactly the same as string
+ return new ObjectPath (ReadString ());
+ }
+
+ public Signature ReadSignature ()
+ {
+ byte ln = ReadByte ();
+
+ // Avoid an array allocation for small signatures
+ if (ln == 1) {
+ DType dtype = (DType)ReadByte ();
+ ReadNull ();
+ return new Signature (dtype);
+ }
+
+ if (ln > Protocol.MaxSignatureLength)
+ throw new Exception ("Signature length " + ln + " exceeds maximum allowed " + Protocol.MaxSignatureLength + " bytes");
+
+ byte[] sigData = new byte[ln];
+ Array.Copy (data, pos, sigData, 0, (int)ln);
+ pos += (int)ln;
+ ReadNull ();
+
+ return Signature.Take (sigData);
+ }
+
+ public object ReadVariant ()
+ {
+ return ReadValue (ReadSignature ());
+ }
+
+ // Used primarily for reading variant values
+ object ReadValue (Signature sig)
+ {
+ if (sig.IsPrimitive)
+ return ReadValue (sig[0]);
+
+ Type t = null;
+ try {
+ t = sig.ToType ();
+ } catch (NotSupportedException e) {
+ // We don't catch other exceptions as they indicate a malformed signature
+ if (Protocol.Verbose)
+ Console.Error.WriteLine (e.Message);
+ }
+
+ /*
+ if (t == null) {
+ StepOver (sig);
+ return null;
+ }
+ */
+
+ if (t == null) {
+ ReadPad (sig.Alignment);
+ int startPos = pos;
+ StepOver (sig);
+ int ln = pos - startPos;
+
+ DValue dv = new DValue();
+ dv.endianness = endianness;
+ dv.signature = sig;
+ dv.data = new byte[ln];
+ Array.Copy (data, startPos, dv.data, 0, ln);
+ return dv;
+ }
+
+ return ReadValue (t);
+ }
+
+ //not pretty or efficient but works
+ public void GetValueToDict (Type keyType, Type valType, System.Collections.IDictionary val)
+ {
+ uint ln = ReadUInt32 ();
+
+ if (ln > Protocol.MaxArrayLength)
+ throw new Exception ("Dict length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
+
+ //advance to the alignment of the element
+ //ReadPad (Protocol.GetAlignment (Signature.TypeToDType (type)));
+ ReadPad (8);
+
+ int endPos = pos + (int)ln;
+
+ //while (stream.Position != endPos)
+ while (pos < endPos)
+ {
+ ReadPad (8);
+
+ val.Add (ReadValue (keyType), ReadValue (valType));
+ }
+
+ if (pos != endPos)
+ throw new Exception ("Read pos " + pos + " != ep " + endPos);
+ }
+
+ //this could be made generic to avoid boxing
+ public Array ReadArray (Type elemType)
+ {
+ uint ln = ReadUInt32 ();
+
+ if (ln > Protocol.MaxArrayLength)
+ throw new Exception ("Array length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
+
+ //TODO: more fast paths for primitive arrays
+ if (elemType == typeof (byte)) {
+ byte[] valb = new byte[ln];
+ Array.Copy (data, pos, valb, 0, (int)ln);
+ pos += (int)ln;
+ return valb;
+ }
+
+ //advance to the alignment of the element
+ ReadPad (Protocol.GetAlignment (Signature.TypeToDType (elemType)));
+
+ int endPos = pos + (int)ln;
+
+ //List<T> vals = new List<T> ();
+ System.Collections.ArrayList vals = new System.Collections.ArrayList ();
+
+ //while (stream.Position != endPos)
+ while (pos < endPos)
+ vals.Add (ReadValue (elemType));
+
+ if (pos != endPos)
+ throw new Exception ("Read pos " + pos + " != ep " + endPos);
+
+ return vals.ToArray (elemType);
+ }
+
+ //struct
+ //probably the wrong place for this
+ //there might be more elegant solutions
+ public object ReadStruct (Type type)
+ {
+ ReadPad (8);
+
+ object val = Activator.CreateInstance (type);
+
+ /*
+ if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (KeyValuePair<,>)) {
+ object elem;
+
+ System.Reflection.PropertyInfo key_prop = type.GetProperty ("Key");
+ GetValue (key_prop.PropertyType, out elem);
+ key_prop.SetValue (val, elem, null);
+
+ System.Reflection.PropertyInfo val_prop = type.GetProperty ("Value");
+ GetValue (val_prop.PropertyType, out elem);
+ val_prop.SetValue (val, elem, null);
+
+ return;
+ }
+ */
+
+ FieldInfo[] fis = type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+
+ foreach (System.Reflection.FieldInfo fi in fis)
+ fi.SetValue (val, ReadValue (fi.FieldType));
+
+ return val;
+ }
+
+ public void ReadNull ()
+ {
+ if (data[pos] != 0)
+ throw new Exception ("Read non-zero byte at position " + pos + " while expecting null terminator");
+ pos++;
+ }
+
+ /*
+ public void ReadPad (int alignment)
+ {
+ pos = Protocol.Padded (pos, alignment);
+ }
+ */
+
+ public void ReadPad (int alignment)
+ {
+ for (int endPos = Protocol.Padded (pos, alignment) ; pos != endPos ; pos++)
+ if (data[pos] != 0)
+ throw new Exception ("Read non-zero byte at position " + pos + " while expecting padding");
+ }
+ }
+}
diff --git a/src/MessageWriter.cs b/src/MessageWriter.cs
new file mode 100644
index 0000000..bbe25d9
--- /dev/null
+++ b/src/MessageWriter.cs
@@ -0,0 +1,570 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Text;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace DBus
+{
+ sealed class MessageWriter
+ {
+ EndianFlag endianness;
+ internal MemoryStream stream;
+
+ public Connection connection;
+
+ //a default constructor is a bad idea for now as we want to make sure the header and content-type match
+ public MessageWriter () : this (Connection.NativeEndianness) {}
+
+ public MessageWriter (EndianFlag endianness)
+ {
+ this.endianness = endianness;
+ stream = new MemoryStream ();
+ }
+
+ public byte[] ToArray ()
+ {
+ //TODO: mark the writer locked or something here
+ return stream.ToArray ();
+ }
+
+ public void ToStream (Stream dest)
+ {
+ stream.WriteTo (dest);
+ }
+
+ public void CloseWrite ()
+ {
+ WritePad (8);
+ }
+
+ public void Write (byte val)
+ {
+ stream.WriteByte (val);
+ }
+
+ public void Write (bool val)
+ {
+ Write ((uint) (val ? 1 : 0));
+ }
+
+ // Buffer for integer marshaling
+ byte[] dst = new byte[8];
+ unsafe void MarshalUShort (void* dataPtr)
+ {
+ WritePad (2);
+
+ if (endianness == Connection.NativeEndianness) {
+ fixed (byte* p = &dst[0])
+ *((ushort*)p) = *((ushort*)dataPtr);
+ } else {
+ byte* data = (byte*)dataPtr;
+ dst[0] = data[1];
+ dst[1] = data[0];
+ }
+
+ stream.Write (dst, 0, 2);
+ }
+
+ unsafe public void Write (short val)
+ {
+ MarshalUShort (&val);
+ }
+
+ unsafe public void Write (ushort val)
+ {
+ MarshalUShort (&val);
+ }
+
+ unsafe void MarshalUInt (void* dataPtr)
+ {
+ WritePad (4);
+
+ if (endianness == Connection.NativeEndianness) {
+ fixed (byte* p = &dst[0])
+ *((uint*)p) = *((uint*)dataPtr);
+ } else {
+ byte* data = (byte*)dataPtr;
+ dst[0] = data[3];
+ dst[1] = data[2];
+ dst[2] = data[1];
+ dst[3] = data[0];
+ }
+
+ stream.Write (dst, 0, 4);
+ }
+
+ unsafe public void Write (int val)
+ {
+ MarshalUInt (&val);
+ }
+
+ unsafe public void Write (uint val)
+ {
+ MarshalUInt (&val);
+ }
+
+ unsafe void MarshalULong (void* dataPtr)
+ {
+ WritePad (8);
+
+ if (endianness == Connection.NativeEndianness) {
+ fixed (byte* p = &dst[0])
+ *((ulong*)p) = *((ulong*)dataPtr);
+ } else {
+ byte* data = (byte*)dataPtr;
+ for (int i = 0; i < 8; ++i)
+ dst[i] = data[7 - i];
+ }
+
+ stream.Write (dst, 0, 8);
+ }
+
+ unsafe public void Write (long val)
+ {
+ MarshalULong (&val);
+ }
+
+ unsafe public void Write (ulong val)
+ {
+ MarshalULong (&val);
+ }
+
+#if !DISABLE_SINGLE
+ unsafe public void Write (float val)
+ {
+ MarshalUInt (&val);
+ }
+#endif
+
+ unsafe public void Write (double val)
+ {
+ MarshalULong (&val);
+ }
+
+ public void Write (string val)
+ {
+ byte[] utf8_data = Encoding.UTF8.GetBytes (val);
+ Write ((uint)utf8_data.Length);
+ stream.Write (utf8_data, 0, utf8_data.Length);
+ WriteNull ();
+ }
+
+ public void Write (ObjectPath val)
+ {
+ Write (val.Value);
+ }
+
+ public void Write (Signature val)
+ {
+ byte[] ascii_data = val.GetBuffer ();
+
+ if (ascii_data.Length > Protocol.MaxSignatureLength)
+ throw new Exception ("Signature length " + ascii_data.Length + " exceeds maximum allowed " + Protocol.MaxSignatureLength + " bytes");
+
+ Write ((byte)ascii_data.Length);
+ stream.Write (ascii_data, 0, ascii_data.Length);
+ WriteNull ();
+ }
+
+ [Obsolete]
+ public void WriteComplex (object val, Type type)
+ {
+ if (type == typeof (void))
+ return;
+
+ if (type.IsArray) {
+ MethodInfo miDict = typeof (MessageWriter).GetMethod ("WriteArray");
+ MethodInfo mi = miDict.MakeGenericMethod (type.GetElementType ());
+ mi.Invoke (this, new object[] {val});
+ } else if (type.IsGenericType && (type.GetGenericTypeDefinition () == typeof (IDictionary<,>) || type.GetGenericTypeDefinition () == typeof (Dictionary<,>))) {
+ Type[] genArgs = type.GetGenericArguments ();
+ MethodInfo miDict = typeof (MessageWriter).GetMethod ("WriteFromDict");
+ MethodInfo mi = miDict.MakeGenericMethod (genArgs);
+ mi.Invoke (this, new object[] {val});
+ } else if (Mapper.IsPublic (type)) {
+ WriteObject (type, val);
+ } else if (!type.IsPrimitive && !type.IsEnum) {
+ WriteValueType (val, type);
+ /*
+ } else if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>)) {
+ //is it possible to support nullable types?
+ Type[] genArgs = type.GetGenericArguments ();
+ WriteVariant (genArgs[0], val);
+ */
+ } else {
+ throw new Exception ("Can't write");
+ }
+ }
+
+ [Obsolete]
+ public void Write (Type type, object val)
+ {
+ if (type == typeof (void))
+ return;
+
+ if (type.IsArray) {
+ MethodInfo miDict = typeof (MessageWriter).GetMethod ("WriteArray");
+ MethodInfo mi = miDict.MakeGenericMethod (type.GetElementType ());
+ mi.Invoke (this, new object[] {val});
+ } else if (type == typeof (ObjectPath)) {
+ Write ((ObjectPath)val);
+ } else if (type == typeof (Signature)) {
+ Write ((Signature)val);
+ } else if (type == typeof (object)) {
+ Write (val);
+ } else if (type == typeof (string)) {
+ Write ((string)val);
+ } else if (type.IsGenericType && (type.GetGenericTypeDefinition () == typeof (IDictionary<,>) || type.GetGenericTypeDefinition () == typeof (Dictionary<,>))) {
+ Type[] genArgs = type.GetGenericArguments ();
+ MethodInfo miDict = typeof (MessageWriter).GetMethod ("WriteFromDict");
+ MethodInfo mi = miDict.MakeGenericMethod (genArgs);
+ mi.Invoke (this, new object[] {val});
+ } else if (Mapper.IsPublic (type)) {
+ WriteObject (type, val);
+ } else if (!type.IsPrimitive && !type.IsEnum) {
+ WriteValueType (val, type);
+ } else {
+ Write (Signature.TypeToDType (type), val);
+ }
+ }
+
+ //helper method, should not be used as it boxes needlessly
+ public void Write (DType dtype, object val)
+ {
+ switch (dtype)
+ {
+ case DType.Byte:
+ {
+ Write ((byte)val);
+ }
+ break;
+ case DType.Boolean:
+ {
+ Write ((bool)val);
+ }
+ break;
+ case DType.Int16:
+ {
+ Write ((short)val);
+ }
+ break;
+ case DType.UInt16:
+ {
+ Write ((ushort)val);
+ }
+ break;
+ case DType.Int32:
+ {
+ Write ((int)val);
+ }
+ break;
+ case DType.UInt32:
+ {
+ Write ((uint)val);
+ }
+ break;
+ case DType.Int64:
+ {
+ Write ((long)val);
+ }
+ break;
+ case DType.UInt64:
+ {
+ Write ((ulong)val);
+ }
+ break;
+#if !DISABLE_SINGLE
+ case DType.Single:
+ {
+ Write ((float)val);
+ }
+ break;
+#endif
+ case DType.Double:
+ {
+ Write ((double)val);
+ }
+ break;
+ case DType.String:
+ {
+ Write ((string)val);
+ }
+ break;
+ case DType.ObjectPath:
+ {
+ Write ((ObjectPath)val);
+ }
+ break;
+ case DType.Signature:
+ {
+ Write ((Signature)val);
+ }
+ break;
+ case DType.Variant:
+ {
+ Write ((object)val);
+ }
+ break;
+ default:
+ throw new Exception ("Unhandled D-Bus type: " + dtype);
+ }
+ }
+
+ public void WriteObject (Type type, object val)
+ {
+ ObjectPath path;
+
+ BusObject bobj = val as BusObject;
+
+ if (bobj == null && val is MarshalByRefObject) {
+ bobj = ((MarshalByRefObject)val).GetLifetimeService () as BusObject;
+ }
+
+ if (bobj == null)
+ throw new Exception ("No object reference to write");
+
+ path = bobj.Path;
+
+ Write (path);
+ }
+
+ //variant
+ public void Write (object val)
+ {
+ if (val == null)
+ throw new NotSupportedException ("Cannot send null variant");
+
+ if (val is DValue) {
+ DValue dv = (DValue)val;
+
+ if (dv.endianness != endianness)
+ throw new NotImplementedException ("Writing opposite endian DValues not yet implemented.");
+
+ Write (dv.signature);
+ WritePad (dv.signature.Alignment);
+ stream.Write (dv.data, 0, dv.data.Length);
+ return;
+ }
+
+ Type type = val.GetType ();
+
+ WriteVariant (type, val);
+ }
+
+ public void WriteVariant (Type type, object val)
+ {
+ Signature sig = Signature.GetSig (type);
+
+ Write (sig);
+ Write (type, val);
+ }
+
+ //this requires a seekable stream for now
+ public unsafe void WriteArray<T> (T[] val)
+ {
+ Type elemType = typeof (T);
+
+ if (elemType == typeof (byte)) {
+ if (val.Length > Protocol.MaxArrayLength)
+ throw new Exception ("Array length " + val.Length + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
+
+ Write ((uint)val.Length);
+ stream.Write ((byte[])(object)val, 0, val.Length);
+ return;
+ }
+
+ if (elemType.IsEnum)
+ elemType = Enum.GetUnderlyingType (elemType);
+
+ Signature sigElem = Signature.GetSig (elemType);
+ int fixedSize = 0;
+ if (endianness == Connection.NativeEndianness && elemType.IsValueType && !sigElem.IsStruct && sigElem.GetFixedSize (ref fixedSize)) {
+ int byteLength = fixedSize * val.Length;
+ if (byteLength > Protocol.MaxArrayLength)
+ throw new Exception ("Array length " + byteLength + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
+ Write ((uint)byteLength);
+ WritePad (sigElem.Alignment);
+
+ GCHandle valHandle = GCHandle.Alloc (val, GCHandleType.Pinned);
+ IntPtr p = valHandle.AddrOfPinnedObject ();
+ byte[] data = new byte[byteLength];
+ byte* bp = (byte*)p;
+ for (int i = 0 ; i != byteLength ; i++)
+ data[i] = bp[i];
+ stream.Write (data, 0, data.Length);
+ valHandle.Free ();
+ return;
+ }
+
+ long origPos = stream.Position;
+ Write ((uint)0);
+
+ //advance to the alignment of the element
+ WritePad (sigElem.Alignment);
+
+ long startPos = stream.Position;
+
+ TypeWriter<T> tWriter = TypeImplementer.GetTypeWriter<T> ();
+
+ foreach (T elem in val)
+ tWriter (this, elem);
+
+ long endPos = stream.Position;
+ uint ln = (uint)(endPos - startPos);
+ stream.Position = origPos;
+
+ if (ln > Protocol.MaxArrayLength)
+ throw new Exception ("Array length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
+
+ Write (ln);
+ stream.Position = endPos;
+ }
+
+ public void WriteValueType (object val, Type type)
+ {
+ MethodInfo mi = TypeImplementer.GetWriteMethod (type);
+ mi.Invoke (null, new object[] {this, val});
+ }
+
+ public void WriteStructure<T> (T value)
+ {
+ TypeWriter<T> tWriter = TypeImplementer.GetTypeWriter<T> ();
+ tWriter (this, value);
+ }
+
+ public void WriteFromDict<TKey,TValue> (IDictionary<TKey,TValue> val)
+ {
+ long origPos = stream.Position;
+ Write ((uint)0);
+
+ WritePad (8);
+
+ long startPos = stream.Position;
+
+ TypeWriter<TKey> keyWriter = TypeImplementer.GetTypeWriter<TKey> ();
+ TypeWriter<TValue> valueWriter = TypeImplementer.GetTypeWriter<TValue> ();
+
+ foreach (KeyValuePair<TKey,TValue> entry in val)
+ {
+ WritePad (8);
+ keyWriter (this, entry.Key);
+ valueWriter (this, entry.Value);
+ }
+
+ long endPos = stream.Position;
+ uint ln = (uint)(endPos - startPos);
+ stream.Position = origPos;
+
+ if (ln > Protocol.MaxArrayLength)
+ throw new Exception ("Dict length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
+
+ Write (ln);
+ stream.Position = endPos;
+ }
+
+ /*
+ public void Write (IDictionary<FieldCode, object> val)
+ {
+ WriteHeaderDict(val);
+ }
+
+ public void Write (Dictionary<FieldCode, object> val)
+ {
+ WriteHeaderDict (val);
+ }
+ */
+
+ /*
+ public void Write (Dictionary<byte, object> val)
+ {
+ long origPos = stream.Position;
+ Write ((uint)0);
+
+ WritePad (8);
+
+ long startPos = stream.Position;
+
+ foreach (KeyValuePair<byte, object> entry in val) {
+ WritePad (8);
+ Write (entry.Key);
+ Write (entry.Value);
+ }
+
+ long endPos = stream.Position;
+ uint ln = (uint)(endPos - startPos);
+ stream.Position = origPos;
+
+ if (ln > Protocol.MaxArrayLength)
+ throw new Exception ("Dict length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
+
+ Write (ln);
+ stream.Position = endPos;
+ }
+ */
+
+ internal void WriteHeaderFields (Dictionary<byte, object> val)
+ {
+ long origPos = stream.Position;
+ Write ((uint)0);
+
+ WritePad (8);
+
+ long startPos = stream.Position;
+
+ foreach (KeyValuePair<byte, object> entry in val) {
+ WritePad (8);
+ Write (entry.Key);
+ switch ((FieldCode)entry.Key) {
+ case FieldCode.Destination:
+ case FieldCode.ErrorName:
+ case FieldCode.Interface:
+ case FieldCode.Member:
+ case FieldCode.Sender:
+ Write (Signature.StringSig);
+ Write ((string)entry.Value);
+ break;
+ case FieldCode.Path:
+ Write (Signature.ObjectPathSig);
+ Write ((ObjectPath)entry.Value);
+ break;
+ case FieldCode.ReplySerial:
+ Write (Signature.UInt32Sig);
+ Write ((uint)entry.Value);
+ break;
+ default:
+ Write (entry.Value);
+ break;
+ }
+ }
+
+ long endPos = stream.Position;
+ uint ln = (uint)(endPos - startPos);
+ stream.Position = origPos;
+
+ if (ln > Protocol.MaxArrayLength)
+ throw new Exception ("Dict length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
+
+ Write (ln);
+ stream.Position = endPos;
+ }
+
+ public void WriteNull ()
+ {
+ stream.WriteByte (0);
+ }
+
+ // Source buffer for zero-padding
+ static readonly byte[] nullBytes = new byte[8];
+ public void WritePad (int alignment)
+ {
+ int needed = Protocol.PadNeeded ((int)stream.Position, alignment);
+ stream.Write (nullBytes, 0, needed);
+ }
+ }
+}
diff --git a/src/PendingCall.cs b/src/PendingCall.cs
new file mode 100644
index 0000000..09e5e16
--- /dev/null
+++ b/src/PendingCall.cs
@@ -0,0 +1,111 @@
+// Copyright 2007 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Threading;
+
+namespace DBus
+{
+ class PendingCall : IAsyncResult
+ {
+ Connection conn;
+ Message reply = null;
+ //AutoResetEvent waitHandle = new AutoResetEvent (false);
+ ManualResetEvent waitHandle;
+
+ public PendingCall (Connection conn)
+ {
+ this.conn = conn;
+ }
+
+ public Message Reply
+ {
+ get {
+ if (reply != null)
+ return reply;
+
+ if (Thread.CurrentThread == conn.mainThread) {
+ /*
+ while (reply == null)
+ conn.Iterate ();
+ */
+
+ while (reply == null)
+ conn.HandleMessage (conn.Transport.ReadMessage ());
+
+ completedSync = true;
+
+ conn.DispatchSignals ();
+ } else {
+ if (waitHandle == null)
+ waitHandle = new ManualResetEvent (false);
+
+ // TODO: Possible race condition?
+ while (reply == null)
+ waitHandle.WaitOne ();
+
+ completedSync = false;
+ }
+
+ return reply;
+ } set {
+ if (reply != null)
+ throw new Exception ("Cannot handle reply more than once");
+
+ reply = value;
+
+ if (waitHandle != null)
+ waitHandle.Set ();
+
+ if (Completed != null)
+ Completed (reply);
+ }
+ }
+
+ public event Action<Message> Completed;
+ bool completedSync;
+
+ public void Cancel ()
+ {
+ throw new NotImplementedException ();
+ }
+
+
+
+ #region IAsyncResult Members
+
+ object IAsyncResult.AsyncState
+ {
+ get {
+ return conn;
+ }
+ }
+
+ WaitHandle IAsyncResult.AsyncWaitHandle
+ {
+ get {
+ if (waitHandle == null)
+ waitHandle = new ManualResetEvent (false);
+
+ return waitHandle;
+ }
+ }
+
+ bool IAsyncResult.CompletedSynchronously
+ {
+ get {
+ return reply != null && completedSync;
+ }
+ }
+
+ bool IAsyncResult.IsCompleted
+ {
+ get {
+ return reply != null;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Protocol.cs b/src/Protocol.cs
new file mode 100644
index 0000000..d7a5df4
--- /dev/null
+++ b/src/Protocol.cs
@@ -0,0 +1,525 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+
+namespace DBus
+{
+ //yyyyuua{yv}
+ //struct Header
+ class Header
+ {
+ public EndianFlag Endianness;
+ public MessageType MessageType;
+ public HeaderFlag Flags;
+ public byte MajorVersion;
+ public uint Length;
+ public uint Serial;
+ //public HeaderField[] Fields;
+
+ // Dictionary keyed by Enum has performance issues on .NET
+ // So we key by byte and use an indexer instead.
+ public Dictionary<byte, object> Fields;
+ public object this[FieldCode key]
+ {
+ get
+ {
+ object value = null;
+ Fields.TryGetValue ((byte)key, out value);
+ return value;
+ } set {
+ if (value == null)
+ Fields.Remove((byte)key);
+ else
+ Fields[(byte)key] = value;
+ }
+ }
+
+ /*
+ public static DType TypeForField (FieldCode f)
+ {
+ switch (f) {
+ case FieldCode.Invalid:
+ return DType.Invalid;
+ case FieldCode.Path:
+ return DType.ObjectPath;
+ case FieldCode.Interface:
+ return DType.String;
+ case FieldCode.Member:
+ return DType.String;
+ case FieldCode.ErrorName:
+ return DType.String;
+ case FieldCode.ReplySerial:
+ return DType.UInt32;
+ case FieldCode.Destination:
+ return DType.String;
+ case FieldCode.Sender:
+ return DType.String;
+ case FieldCode.Signature:
+ return DType.Signature;
+#if PROTO_REPLY_SIGNATURE
+ case FieldCode.ReplySignature: //note: not supported in dbus
+ return DType.Signature;
+#endif
+ default:
+ return DType.Invalid;
+ }
+ }
+ */
+ }
+
+ /*
+ public struct HeaderField
+ {
+ //public HeaderField (FieldCode code, object value)
+ //{
+ // this.Code = code;
+ // this.Value = value;
+ //}
+
+ public static HeaderField Create (FieldCode code, object value)
+ {
+ HeaderField hf;
+
+ hf.Code = code;
+ hf.Value = value;
+
+ return hf;
+ }
+
+ public FieldCode Code;
+ public object Value;
+ }
+ */
+
+ /*
+ struct HeaderFieldSet
+ {
+ public ObjectPath Path;
+ public string Interface;
+ public string Member;
+ public string ErrorName;
+ public uint ReplySerial;
+ public string Destination;
+ public string Sender;
+ //public Signature Signature;
+ public Signature Sig;
+
+#if PROTO_REPLY_SIGNATURE
+ public Signature ReplySignature;
+#endif
+
+ public void Read (MessageReader reader)
+ {
+ FieldCode code = (FieldCode)reader.ReadByte ();
+ }
+
+ public void Write (MessageWriter writer)
+ {
+ // TODO: Write overall length
+
+ if (Path != null) {
+ writer.WritePad (8);
+ writer.Write ((byte)FieldCode.Path);
+ writer.Write (Signature.ObjectPathSig);
+ writer.Write (Path);
+ }
+
+ if (Interface != null) {
+ writer.WritePad (8);
+ writer.Write ((byte)FieldCode.Interface);
+ writer.Write (Signature.StringSig);
+ writer.Write (Interface);
+ }
+
+ if (Member != null) {
+ writer.WritePad (8);
+ writer.Write ((byte)FieldCode.Member);
+ writer.Write (Signature.StringSig);
+ writer.Write (Member);
+ }
+
+ if (ErrorName != null) {
+ writer.WritePad (8);
+ writer.Write ((byte)FieldCode.ErrorName);
+ writer.Write (Signature.StringSig);
+ writer.Write (ErrorName);
+ }
+
+ if (ReplySerial != 0) {
+ writer.WritePad (8);
+ writer.Write ((byte)FieldCode.ReplySerial);
+ writer.Write (Signature.UInt32Sig);
+ writer.Write (ReplySerial);
+ }
+
+ if (Destination != null) {
+ writer.WritePad (8);
+ writer.Write ((byte)FieldCode.Destination);
+ writer.Write (Signature.StringSig);
+ writer.Write (Destination);
+ }
+
+ if (Sender != null) {
+ writer.WritePad (8);
+ writer.Write ((byte)FieldCode.Sender);
+ writer.Write (Signature.StringSig);
+ writer.Write (Sender);
+ }
+
+ if (Sig != Signature.Empty) {
+ writer.WritePad (8);
+ writer.Write ((byte)FieldCode.Signature);
+ writer.Write (Signature.SignatureSig);
+ writer.Write (Sig);
+ }
+ }
+ }
+ */
+
+ enum MessageType : byte
+ {
+ //This is an invalid type.
+ Invalid,
+ //Method call.
+ MethodCall,
+ //Method reply with returned data.
+ MethodReturn,
+ //Error reply. If the first argument exists and is a string, it is an error message.
+ Error,
+ //Signal emission.
+ Signal,
+ }
+
+ enum FieldCode : byte
+ {
+ Invalid,
+ Path,
+ Interface,
+ Member,
+ ErrorName,
+ ReplySerial,
+ Destination,
+ Sender,
+ Signature,
+#if PROTO_REPLY_SIGNATURE
+ ReplySignature, //note: not supported in dbus
+#endif
+ }
+
+ enum EndianFlag : byte
+ {
+ Little = (byte)'l',
+ Big = (byte)'B',
+ }
+
+ [Flags]
+ enum HeaderFlag : byte
+ {
+ None = 0,
+ NoReplyExpected = 0x1,
+ NoAutoStart = 0x2,
+ }
+
+ public sealed class ObjectPath : IComparable, IComparable<ObjectPath>, IEquatable<ObjectPath>
+ {
+ public static readonly ObjectPath Root = new ObjectPath ("/");
+
+ internal readonly string Value;
+
+ public ObjectPath (string value)
+ {
+ if (value == null)
+ throw new ArgumentNullException ("value");
+
+ Validate (value);
+
+ this.Value = value;
+ }
+
+ static void Validate (string value)
+ {
+ if (!value.StartsWith ("/"))
+ throw new ArgumentException ("value");
+ if (value.EndsWith ("/") && value.Length > 1)
+ throw new ArgumentException ("ObjectPath cannot end in '/'");
+
+ bool multipleSlash = false;
+
+ foreach (char c in value) {
+ bool valid = (c >= 'a' && c <='z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == '_'
+ || (!multipleSlash && c == '/');
+
+ if (!valid) {
+ var message = string.Format ("'{0}' is not a valid character in an ObjectPath", c);
+ throw new ArgumentException (message, "value");
+ }
+
+ multipleSlash = c == '/';
+ }
+
+ }
+
+ public int CompareTo (ObjectPath other)
+ {
+ if (other == null)
+ return 1;
+
+ return Value.CompareTo (other.Value);
+ }
+
+ public int CompareTo (object otherObject)
+ {
+ ObjectPath other = otherObject as ObjectPath;
+
+ if (other == null)
+ return 1;
+
+ return Value.CompareTo (other.Value);
+ }
+
+ public bool Equals (ObjectPath other)
+ {
+ if (other == null)
+ return false;
+
+ return Value == other.Value;
+ }
+
+ public override bool Equals (object o)
+ {
+ ObjectPath b = o as ObjectPath;
+
+ if (b == null)
+ return false;
+
+ return Value.Equals (b.Value);
+ }
+
+ public static bool operator == (ObjectPath a, ObjectPath b)
+ {
+ object aa = a, bb = b;
+ if (aa == null && bb == null)
+ return true;
+
+ if (aa == null || bb == null)
+ return false;
+
+ return a.Value == b.Value;
+ }
+
+ public static bool operator != (ObjectPath a, ObjectPath b)
+ {
+ return !(a == b);
+ }
+
+ public override int GetHashCode ()
+ {
+ return Value.GetHashCode ();
+ }
+
+ public override string ToString ()
+ {
+ return Value;
+ }
+
+ //this may or may not prove useful
+ internal string[] Decomposed
+ {
+ get {
+ return Value.Split (new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
+ /*
+ } set {
+ Value = String.Join ("/", value);
+ */
+ }
+ }
+
+ internal ObjectPath Parent
+ {
+ get {
+ if (Value == Root.Value)
+ return null;
+
+ string par = Value.Substring (0, Value.LastIndexOf ('/'));
+ if (par == String.Empty)
+ par = "/";
+
+ return new ObjectPath (par);
+ }
+ }
+
+ /*
+ public int CompareTo (object value)
+ {
+ return 1;
+ }
+
+ public int CompareTo (ObjectPath value)
+ {
+ return 1;
+ }
+
+ public bool Equals (ObjectPath value)
+ {
+ return false;
+ }
+ */
+ }
+
+ static class Protocol
+ {
+ //protocol versions that we support
+ public const byte MinVersion = 0;
+ public const byte Version = 1;
+ public const byte MaxVersion = Version + 1;
+
+ public const uint MaxMessageLength = 134217728; //2 to the 27th power
+ public const uint MaxArrayLength = 67108864; //2 to the 26th power
+ public const uint MaxSignatureLength = 255;
+ public const uint MaxArrayDepth = 32;
+ public const uint MaxStructDepth = 32;
+
+ //this is not strictly related to Protocol since names are passed around as strings
+ internal const uint MaxNameLength = 255;
+ internal const uint MaxMatchRuleLength = 1024;
+ internal const uint MaxMatchRuleArgs = 64;
+
+ public static int PadNeeded (int pos, int alignment)
+ {
+ int pad = pos % alignment;
+ pad = pad == 0 ? 0 : alignment - pad;
+
+ return pad;
+ }
+
+ public static int Padded (int pos, int alignment)
+ {
+ int pad = pos % alignment;
+ if (pad != 0)
+ pos += alignment - pad;
+
+ return pos;
+ }
+
+ public static int GetAlignment (DType dtype)
+ {
+ switch (dtype) {
+ case DType.Byte:
+ return 1;
+ case DType.Boolean:
+ return 4;
+ case DType.Int16:
+ case DType.UInt16:
+ return 2;
+ case DType.Int32:
+ case DType.UInt32:
+ return 4;
+ case DType.Int64:
+ case DType.UInt64:
+ return 8;
+#if !DISABLE_SINGLE
+ case DType.Single: //Not yet supported!
+ return 4;
+#endif
+ case DType.Double:
+ return 8;
+ case DType.String:
+ return 4;
+ case DType.ObjectPath:
+ return 4;
+ case DType.Signature:
+ return 1;
+ case DType.Array:
+ return 4;
+ case DType.Struct:
+ case DType.StructBegin:
+ return 8;
+ case DType.Variant:
+ return 1;
+ case DType.DictEntry:
+ case DType.DictEntryBegin:
+ return 8;
+ case DType.Invalid:
+ default:
+ throw new Exception ("Cannot determine alignment of " + dtype);
+ }
+ }
+
+ //this class may not be the best place for Verbose
+ public readonly static bool Verbose;
+
+ static Protocol ()
+ {
+ Verbose = !String.IsNullOrEmpty (Environment.GetEnvironmentVariable ("DBUS_VERBOSE"));
+ }
+ }
+
+ // Currently only for internal use on exported objects
+ class BusException : Exception
+ {
+ public BusException (string errorName, string errorMessage)
+ {
+ this.ErrorName = errorName;
+ this.ErrorMessage = errorMessage;
+ }
+
+ public BusException (string errorName, string format, params object[] args)
+ {
+ this.ErrorName = errorName;
+ this.ErrorMessage = String.Format (format, args);
+ }
+
+ public override string Message
+ {
+ get
+ {
+ return ErrorName + ": " + ErrorMessage;
+ }
+ }
+
+ public readonly string ErrorName;
+
+ public readonly string ErrorMessage;
+ }
+
+#if UNDOCUMENTED_IN_SPEC
+/*
+"org.freedesktop.DBus.Error.Failed"
+"org.freedesktop.DBus.Error.NoMemory"
+"org.freedesktop.DBus.Error.ServiceUnknown"
+"org.freedesktop.DBus.Error.NameHasNoOwner"
+"org.freedesktop.DBus.Error.NoReply"
+"org.freedesktop.DBus.Error.IOError"
+"org.freedesktop.DBus.Error.BadAddress"
+"org.freedesktop.DBus.Error.NotSupported"
+"org.freedesktop.DBus.Error.LimitsExceeded"
+"org.freedesktop.DBus.Error.AccessDenied"
+"org.freedesktop.DBus.Error.AuthFailed"
+"org.freedesktop.DBus.Error.NoServer"
+"org.freedesktop.DBus.Error.Timeout"
+"org.freedesktop.DBus.Error.NoNetwork"
+"org.freedesktop.DBus.Error.AddressInUse"
+"org.freedesktop.DBus.Error.Disconnected"
+"org.freedesktop.DBus.Error.InvalidArgs"
+"org.freedesktop.DBus.Error.FileNotFound"
+"org.freedesktop.DBus.Error.UnknownMethod"
+"org.freedesktop.DBus.Error.TimedOut"
+"org.freedesktop.DBus.Error.MatchRuleNotFound"
+"org.freedesktop.DBus.Error.MatchRuleInvalid"
+"org.freedesktop.DBus.Error.Spawn.ExecFailed"
+"org.freedesktop.DBus.Error.Spawn.ForkFailed"
+"org.freedesktop.DBus.Error.Spawn.ChildExited"
+"org.freedesktop.DBus.Error.Spawn.ChildSignaled"
+"org.freedesktop.DBus.Error.Spawn.Failed"
+"org.freedesktop.DBus.Error.UnixProcessIdUnknown"
+"org.freedesktop.DBus.Error.InvalidSignature"
+"org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"
+*/
+#endif
+}
diff --git a/src/Signature.cs b/src/Signature.cs
new file mode 100644
index 0000000..6439fe8
--- /dev/null
+++ b/src/Signature.cs
@@ -0,0 +1,897 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Text;
+
+using System.Collections.Generic;
+//TODO: Reflection should be done at a higher level than this class
+using System.Reflection;
+
+namespace DBus
+{
+ //maybe this should be nullable?
+ struct Signature
+ {
+ //TODO: this class needs some work
+ //Data should probably include the null terminator
+
+ public static readonly Signature Empty = new Signature (String.Empty);
+ public static readonly Signature ByteSig = Allocate (DType.Byte);
+ public static readonly Signature UInt16Sig = Allocate (DType.UInt16);
+ public static readonly Signature UInt32Sig = Allocate (DType.UInt32);
+ public static readonly Signature StringSig = Allocate (DType.String);
+ public static readonly Signature ObjectPathSig = Allocate (DType.ObjectPath);
+ public static readonly Signature SignatureSig = Allocate (DType.Signature);
+ public static readonly Signature VariantSig = Allocate (DType.Variant);
+
+ public static bool operator == (Signature a, Signature b)
+ {
+ if (a.data == b.data)
+ return true;
+
+ if (a.data == null)
+ return false;
+
+ if (b.data == null)
+ return false;
+
+ if (a.data.Length != b.data.Length)
+ return false;
+
+ for (int i = 0 ; i != a.data.Length ; i++)
+ if (a.data[i] != b.data[i])
+ return false;
+
+ return true;
+ }
+
+ public static bool operator != (Signature a, Signature b)
+ {
+ return !(a == b);
+ }
+
+ public override bool Equals (object o)
+ {
+ if (o == null)
+ return false;
+
+ if (!(o is Signature))
+ return false;
+
+ return this == (Signature)o;
+ }
+
+ public override int GetHashCode ()
+ {
+ // TODO: Avoid string conversion
+ return Value.GetHashCode ();
+ }
+
+ public static Signature operator + (Signature s1, Signature s2)
+ {
+ return Concat (s1, s2);
+ }
+
+ public static Signature Concat (Signature s1, Signature s2)
+ {
+ if (s1.data == null && s2.data == null)
+ return Signature.Empty;
+
+ if (s1.data == null)
+ return s2;
+
+ if (s2.data == null)
+ return s1;
+
+ if (s1.Length + s2.Length == 0)
+ return Signature.Empty;
+
+ byte[] data = new byte[s1.data.Length + s2.data.Length];
+ s1.data.CopyTo (data, 0);
+ s2.data.CopyTo (data, s1.data.Length);
+ return Signature.Take (data);
+ }
+
+ public Signature (string value)
+ {
+ if (value.Length == 0) {
+ this.data = Empty.data;
+ return;
+ }
+
+ if (value.Length == 1) {
+ this.data = DataForDType ((DType)value[0]);
+ return;
+ }
+
+ this.data = Encoding.ASCII.GetBytes (value);
+ }
+
+ internal static Signature Take (byte[] value)
+ {
+ Signature sig;
+
+ if (value.Length == 0) {
+ sig.data = Empty.data;
+ return sig;
+ }
+
+ if (value.Length == 1) {
+ sig.data = DataForDType ((DType)value[0]);
+ return sig;
+ }
+
+ sig.data = value;
+ return sig;
+ }
+
+ static byte[] DataForDType (DType value)
+ {
+ // Reduce heap allocations.
+ // For now, we only cache the most common protocol signatures.
+ switch (value) {
+ case DType.Byte:
+ return ByteSig.data;
+ case DType.UInt16:
+ return UInt16Sig.data;
+ case DType.UInt32:
+ return UInt32Sig.data;
+ case DType.String:
+ return StringSig.data;
+ case DType.ObjectPath:
+ return ObjectPathSig.data;
+ case DType.Signature:
+ return SignatureSig.data;
+ case DType.Variant:
+ return VariantSig.data;
+ default:
+ return new byte[] {(byte)value};
+ }
+ }
+
+ private static Signature Allocate (DType value)
+ {
+ Signature sig;
+ sig.data = new byte[] {(byte)value};
+ return sig;
+ }
+
+ internal Signature (DType value)
+ {
+ this.data = DataForDType (value);
+ }
+
+ internal Signature (DType[] value)
+ {
+ if (value.Length == 0) {
+ this.data = Empty.data;
+ return;
+ }
+
+ if (value.Length == 1) {
+ this.data = DataForDType (value[0]);
+ return;
+ }
+
+ this.data = new byte[value.Length];
+
+ for (int i = 0 ; i != value.Length ; i++)
+ this.data[i] = (byte)value[i];
+ }
+
+ byte[] data;
+
+ //TODO: this should be private, but MessageWriter and Monitor still use it
+ //[Obsolete]
+ public byte[] GetBuffer ()
+ {
+ return data;
+ }
+
+ internal DType this[int index]
+ {
+ get {
+ return (DType)data[index];
+ }
+ }
+
+ public int Length
+ {
+ get {
+ return data.Length;
+ }
+ }
+
+ //[Obsolete]
+ public string Value
+ {
+ get {
+ //FIXME: hack to handle bad case when Data is null
+ if (data == null)
+ return String.Empty;
+
+ return Encoding.ASCII.GetString (data);
+ }
+ }
+
+ public override string ToString ()
+ {
+ return Value;
+
+ /*
+ StringBuilder sb = new StringBuilder ();
+
+ foreach (DType t in data) {
+ //we shouldn't rely on object mapping here, but it's an easy way to get string representations for now
+ Type type = DTypeToType (t);
+ if (type != null) {
+ sb.Append (type.Name);
+ } else {
+ char c = (char)t;
+ if (!Char.IsControl (c))
+ sb.Append (c);
+ else
+ sb.Append (@"\" + (int)c);
+ }
+ sb.Append (" ");
+ }
+
+ return sb.ToString ();
+ */
+ }
+
+ public Signature MakeArraySignature ()
+ {
+ return new Signature (DType.Array) + this;
+ }
+
+ public static Signature MakeStruct (params Signature[] elems)
+ {
+ Signature sig = Signature.Empty;
+
+ sig += new Signature (DType.StructBegin);
+
+ foreach (Signature elem in elems)
+ sig += elem;
+
+ sig += new Signature (DType.StructEnd);
+
+ return sig;
+ }
+
+ public static Signature MakeDictEntry (Signature keyType, Signature valueType)
+ {
+ Signature sig = Signature.Empty;
+
+ sig += new Signature (DType.DictEntryBegin);
+
+ sig += keyType;
+ sig += valueType;
+
+ sig += new Signature (DType.DictEntryEnd);
+
+ return sig;
+ }
+
+ public static Signature MakeDict (Signature keyType, Signature valueType)
+ {
+ return MakeDictEntry (keyType, valueType).MakeArraySignature ();
+ }
+
+ public int Alignment
+ {
+ get {
+ if (data.Length == 0)
+ return 0;
+
+ return Protocol.GetAlignment (this[0]);
+ }
+ }
+
+ static int GetSize (DType dtype)
+ {
+ switch (dtype) {
+ case DType.Byte:
+ return 1;
+ case DType.Boolean:
+ return 4;
+ case DType.Int16:
+ case DType.UInt16:
+ return 2;
+ case DType.Int32:
+ case DType.UInt32:
+ return 4;
+ case DType.Int64:
+ case DType.UInt64:
+ return 8;
+#if !DISABLE_SINGLE
+ case DType.Single: //Not yet supported!
+ return 4;
+#endif
+ case DType.Double:
+ return 8;
+ case DType.String:
+ case DType.ObjectPath:
+ case DType.Signature:
+ case DType.Array:
+ case DType.StructBegin:
+ case DType.Variant:
+ case DType.DictEntryBegin:
+ return -1;
+ case DType.Invalid:
+ default:
+ throw new Exception ("Cannot determine size of " + dtype);
+ }
+ }
+
+ public bool GetFixedSize (ref int size)
+ {
+ if (size < 0)
+ return false;
+
+ if (data.Length == 0)
+ return true;
+
+ // Sensible?
+ size = Protocol.Padded (size, Alignment);
+
+ if (data.Length == 1) {
+ int valueSize = GetSize (this[0]);
+
+ if (valueSize == -1)
+ return false;
+
+ size += valueSize;
+ return true;
+ }
+
+ if (IsStructlike) {
+ foreach (Signature sig in GetParts ())
+ if (!sig.GetFixedSize (ref size))
+ return false;
+ return true;
+ }
+
+ if (IsArray || IsDict)
+ return false;
+
+ if (IsStruct) {
+ foreach (Signature sig in GetFieldSignatures ())
+ if (!sig.GetFixedSize (ref size))
+ return false;
+ return true;
+ }
+
+ // Any other cases?
+ throw new Exception ();
+ }
+
+ public bool IsFixedSize
+ {
+ get {
+ if (data.Length == 0)
+ return true;
+
+ if (data.Length == 1) {
+ int size = GetSize (this[0]);
+ return size != -1;
+ }
+
+ if (IsStructlike) {
+ foreach (Signature sig in GetParts ())
+ if (!sig.IsFixedSize)
+ return false;
+ return true;
+ }
+
+ if (IsArray || IsDict)
+ return false;
+
+ if (IsStruct) {
+ foreach (Signature sig in GetFieldSignatures ())
+ if (!sig.IsFixedSize)
+ return false;
+ return true;
+ }
+
+ // Any other cases?
+ throw new Exception ();
+ }
+ }
+
+ //TODO: complete this
+ public bool IsPrimitive
+ {
+ get {
+ if (data.Length != 1)
+ return false;
+
+ if (this[0] == DType.Variant)
+ return false;
+
+ if (this[0] == DType.Invalid)
+ return false;
+
+ return true;
+ }
+ }
+
+ public bool IsStruct
+ {
+ get {
+ if (Length < 2)
+ return false;
+
+ if (this[0] != DType.StructBegin)
+ return false;
+
+ // FIXME: Incorrect! What if this is in fact a Structlike starting and finishing with structs?
+ if (this[Length - 1] != DType.StructEnd)
+ return false;
+
+ return true;
+ }
+ }
+
+ public bool IsDictEntry
+ {
+ get {
+ if (Length < 2)
+ return false;
+
+ if (this[0] != DType.DictEntryBegin)
+ return false;
+
+ // FIXME: Incorrect! What if this is in fact a Structlike starting and finishing with structs?
+ if (this[Length - 1] != DType.DictEntryEnd)
+ return false;
+
+ return true;
+ }
+ }
+
+ public bool IsStructlike
+ {
+ get {
+ if (Length < 2)
+ return false;
+
+ if (IsArray)
+ return false;
+
+ if (IsDict)
+ return false;
+
+ if (IsStruct)
+ return false;
+
+ return true;
+ }
+ }
+
+ public bool IsDict
+ {
+ get {
+ if (Length < 3)
+ return false;
+
+ if (!IsArray)
+ return false;
+
+ // 0 is 'a'
+ if (this[1] != DType.DictEntryBegin)
+ return false;
+
+ return true;
+ }
+ }
+
+ public bool IsArray
+ {
+ get {
+ if (Length < 2)
+ return false;
+
+ if (this[0] != DType.Array)
+ return false;
+
+ return true;
+ }
+ }
+
+ public Signature GetElementSignature ()
+ {
+ if (!IsArray)
+ throw new Exception ("Cannot get the element signature of a non-array (signature was '" + this + "')");
+
+ //TODO: improve this
+ //if (IsDict)
+ // throw new NotSupportedException ("Parsing dict signature is not supported (signature was '" + this + "')");
+
+ // Skip over 'a'
+ int pos = 1;
+ return GetNextSignature (ref pos);
+ }
+
+ public Type[] ToTypes ()
+ {
+ // TODO: Find a way to avoid these null checks everywhere.
+ if (data == null)
+ return Type.EmptyTypes;
+
+ List<Type> types = new List<Type> ();
+ for (int i = 0 ; i != data.Length ; types.Add (ToType (ref i)));
+ return types.ToArray ();
+ }
+
+ public Type ToType ()
+ {
+ int pos = 0;
+ Type ret = ToType (ref pos);
+ if (pos != data.Length)
+ throw new Exception ("Signature '" + Value + "' is not a single complete type");
+ return ret;
+ }
+
+ internal static DType TypeCodeToDType (TypeCode typeCode)
+ {
+ switch (typeCode)
+ {
+ case TypeCode.Empty:
+ return DType.Invalid;
+ case TypeCode.Object:
+ return DType.Invalid;
+ case TypeCode.DBNull:
+ return DType.Invalid;
+ case TypeCode.Boolean:
+ return DType.Boolean;
+ case TypeCode.Char:
+ return DType.UInt16;
+ case TypeCode.SByte:
+ return DType.Byte;
+ case TypeCode.Byte:
+ return DType.Byte;
+ case TypeCode.Int16:
+ return DType.Int16;
+ case TypeCode.UInt16:
+ return DType.UInt16;
+ case TypeCode.Int32:
+ return DType.Int32;
+ case TypeCode.UInt32:
+ return DType.UInt32;
+ case TypeCode.Int64:
+ return DType.Int64;
+ case TypeCode.UInt64:
+ return DType.UInt64;
+ case TypeCode.Single:
+ return DType.Single;
+ case TypeCode.Double:
+ return DType.Double;
+ case TypeCode.Decimal:
+ return DType.Invalid;
+ case TypeCode.DateTime:
+ return DType.Invalid;
+ case TypeCode.String:
+ return DType.String;
+ default:
+ return DType.Invalid;
+ }
+ }
+
+ //FIXME: this method is bad, get rid of it
+ internal static DType TypeToDType (Type type)
+ {
+ if (type == typeof (void))
+ return DType.Invalid;
+
+ if (type == typeof (string))
+ return DType.String;
+
+ if (type == typeof (ObjectPath))
+ return DType.ObjectPath;
+
+ if (type == typeof (Signature))
+ return DType.Signature;
+
+ if (type == typeof (object))
+ return DType.Variant;
+
+ if (type.IsPrimitive)
+ return TypeCodeToDType (Type.GetTypeCode (type));
+
+ if (type.IsEnum)
+ return TypeToDType (Enum.GetUnderlyingType (type));
+
+ //needs work
+ if (type.IsArray)
+ return DType.Array;
+
+ //if (type.UnderlyingSystemType != null)
+ // return TypeToDType (type.UnderlyingSystemType);
+ if (Mapper.IsPublic (type))
+ return DType.ObjectPath;
+
+ if (!type.IsPrimitive && !type.IsEnum)
+ return DType.Struct;
+
+ //TODO: maybe throw an exception here
+ return DType.Invalid;
+ }
+
+ /*
+ public static DType TypeToDType (Type type)
+ {
+ if (type == null)
+ return DType.Invalid;
+ else if (type == typeof (byte))
+ return DType.Byte;
+ else if (type == typeof (bool))
+ return DType.Boolean;
+ else if (type == typeof (short))
+ return DType.Int16;
+ else if (type == typeof (ushort))
+ return DType.UInt16;
+ else if (type == typeof (int))
+ return DType.Int32;
+ else if (type == typeof (uint))
+ return DType.UInt32;
+ else if (type == typeof (long))
+ return DType.Int64;
+ else if (type == typeof (ulong))
+ return DType.UInt64;
+ else if (type == typeof (float)) //not supported by libdbus at time of writing
+ return DType.Single;
+ else if (type == typeof (double))
+ return DType.Double;
+ else if (type == typeof (string))
+ return DType.String;
+ else if (type == typeof (ObjectPath))
+ return DType.ObjectPath;
+ else if (type == typeof (Signature))
+ return DType.Signature;
+ else
+ return DType.Invalid;
+ }
+ */
+
+ public IEnumerable<Signature> GetFieldSignatures ()
+ {
+ if (this == Signature.Empty || this[0] != DType.StructBegin)
+ throw new Exception ("Not a struct");
+
+ for (int pos = 1 ; pos < data.Length - 1 ;)
+ yield return GetNextSignature (ref pos);
+ }
+
+ public void GetDictEntrySignatures (out Signature sigKey, out Signature sigValue)
+ {
+ if (this == Signature.Empty || this[0] != DType.DictEntryBegin)
+ throw new Exception ("Not a DictEntry");
+
+ int pos = 1;
+ sigKey = GetNextSignature (ref pos);
+ sigValue = GetNextSignature (ref pos);
+ }
+
+ public IEnumerable<Signature> GetParts ()
+ {
+ if (data == null)
+ yield break;
+ for (int pos = 0 ; pos < data.Length ;) {
+ yield return GetNextSignature (ref pos);
+ }
+ }
+
+ public Signature GetNextSignature (ref int pos)
+ {
+ if (data == null)
+ return Signature.Empty;
+
+ DType dtype = (DType)data[pos++];
+
+ switch (dtype) {
+ //case DType.Invalid:
+ // return typeof (void);
+ case DType.Array:
+ //peek to see if this is in fact a dictionary
+ if ((DType)data[pos] == DType.DictEntryBegin) {
+ //skip over the {
+ pos++;
+ Signature keyType = GetNextSignature (ref pos);
+ Signature valueType = GetNextSignature (ref pos);
+ //skip over the }
+ pos++;
+ return Signature.MakeDict (keyType, valueType);
+ } else {
+ Signature elementType = GetNextSignature (ref pos);
+ return elementType.MakeArraySignature ();
+ }
+ //case DType.DictEntryBegin: // FIXME: DictEntries should be handled separately.
+ case DType.StructBegin:
+ //List<Signature> fieldTypes = new List<Signature> ();
+ Signature fieldsSig = Signature.Empty;
+ while ((DType)data[pos] != DType.StructEnd)
+ fieldsSig += GetNextSignature (ref pos);
+ //skip over the )
+ pos++;
+ return Signature.MakeStruct (fieldsSig);
+ //return fieldsSig;
+ case DType.DictEntryBegin:
+ Signature sigKey = GetNextSignature (ref pos);
+ Signature sigValue = GetNextSignature (ref pos);
+ //skip over the }
+ pos++;
+ return Signature.MakeDictEntry (sigKey, sigValue);
+ default:
+ return new Signature (dtype);
+ }
+ }
+
+ public Type ToType (ref int pos)
+ {
+ // TODO: Find a way to avoid these null checks everywhere.
+ if (data == null)
+ return typeof (void);
+
+ DType dtype = (DType)data[pos++];
+
+ switch (dtype) {
+ case DType.Invalid:
+ return typeof (void);
+ case DType.Byte:
+ return typeof (byte);
+ case DType.Boolean:
+ return typeof (bool);
+ case DType.Int16:
+ return typeof (short);
+ case DType.UInt16:
+ return typeof (ushort);
+ case DType.Int32:
+ return typeof (int);
+ case DType.UInt32:
+ return typeof (uint);
+ case DType.Int64:
+ return typeof (long);
+ case DType.UInt64:
+ return typeof (ulong);
+ case DType.Single: ////not supported by libdbus at time of writing
+ return typeof (float);
+ case DType.Double:
+ return typeof (double);
+ case DType.String:
+ return typeof (string);
+ case DType.ObjectPath:
+ return typeof (ObjectPath);
+ case DType.Signature:
+ return typeof (Signature);
+ case DType.Array:
+ //peek to see if this is in fact a dictionary
+ if ((DType)data[pos] == DType.DictEntryBegin) {
+ //skip over the {
+ pos++;
+ Type keyType = ToType (ref pos);
+ Type valueType = ToType (ref pos);
+ //skip over the }
+ pos++;
+ //return typeof (IDictionary<,>).MakeGenericType (new Type[] {keyType, valueType});
+ //workaround for Mono bug #81035 (memory leak)
+ return Mapper.GetGenericType (typeof (IDictionary<,>), new Type[] {keyType, valueType});
+ } else {
+ return ToType (ref pos).MakeArrayType ();
+ }
+ case DType.Struct:
+ return typeof (ValueType);
+ case DType.DictEntry:
+ return typeof (System.Collections.Generic.KeyValuePair<,>);
+ case DType.Variant:
+ return typeof (object);
+ default:
+ throw new NotSupportedException ("Parsing or converting this signature is not yet supported (signature was '" + this + "'), at DType." + dtype);
+ }
+ }
+
+ public static Signature GetSig (object[] objs)
+ {
+ return GetSig (Type.GetTypeArray (objs));
+ }
+
+ public static Signature GetSig (Type[] types)
+ {
+ if (types == null)
+ throw new ArgumentNullException ("types");
+
+ Signature sig = Signature.Empty;
+
+ foreach (Type type in types)
+ sig += GetSig (type);
+
+ return sig;
+ }
+
+ public static Signature GetSig (Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException ("type");
+
+ //this is inelegant, but works for now
+ if (type == typeof (Signature))
+ return new Signature (DType.Signature);
+
+ if (type == typeof (ObjectPath))
+ return new Signature (DType.ObjectPath);
+
+ if (type == typeof (void))
+ return Signature.Empty;
+
+ if (type == typeof (string))
+ return new Signature (DType.String);
+
+ if (type == typeof (object))
+ return new Signature (DType.Variant);
+
+ if (type.IsArray)
+ return GetSig (type.GetElementType ()).MakeArraySignature ();
+
+ if (type.IsGenericType && (type.GetGenericTypeDefinition () == typeof (IDictionary<,>) || type.GetGenericTypeDefinition () == typeof (Dictionary<,>))) {
+
+ Type[] genArgs = type.GetGenericArguments ();
+ return Signature.MakeDict (GetSig (genArgs[0]), GetSig (genArgs[1]));
+ }
+
+ if (Mapper.IsPublic (type)) {
+ return new Signature (DType.ObjectPath);
+ }
+
+ if (!type.IsPrimitive && !type.IsEnum) {
+ Signature sig = Signature.Empty;
+
+ foreach (FieldInfo fi in type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
+ sig += GetSig (fi.FieldType);
+
+ return Signature.MakeStruct (sig);
+ }
+
+ DType dtype = Signature.TypeToDType (type);
+ return new Signature (dtype);
+ }
+ }
+
+ enum ArgDirection
+ {
+ In,
+ Out,
+ }
+
+ enum DType : byte
+ {
+ Invalid = (byte)'\0',
+
+ Byte = (byte)'y',
+ Boolean = (byte)'b',
+ Int16 = (byte)'n',
+ UInt16 = (byte)'q',
+ Int32 = (byte)'i',
+ UInt32 = (byte)'u',
+ Int64 = (byte)'x',
+ UInt64 = (byte)'t',
+ Single = (byte)'f', //This is not yet supported!
+ Double = (byte)'d',
+ String = (byte)'s',
+ ObjectPath = (byte)'o',
+ Signature = (byte)'g',
+
+ Array = (byte)'a',
+ [Obsolete ("Not in protocol")]
+ Struct = (byte)'r',
+ [Obsolete ("Not in protocol")]
+ DictEntry = (byte)'e',
+ Variant = (byte)'v',
+
+ StructBegin = (byte)'(',
+ StructEnd = (byte)')',
+ DictEntryBegin = (byte)'{',
+ DictEntryEnd = (byte)'}',
+ }
+}
diff --git a/src/SocketTransport.cs b/src/SocketTransport.cs
new file mode 100644
index 0000000..e6eb6b3
--- /dev/null
+++ b/src/SocketTransport.cs
@@ -0,0 +1,70 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+
+namespace DBus.Transports
+{
+ class SocketTransport : Transport
+ {
+ internal Socket socket;
+
+ public override void Open (AddressEntry entry)
+ {
+ string host, portStr, family;
+ int port;
+
+ if (!entry.Properties.TryGetValue ("host", out host))
+ host = "localhost";
+
+ if (!entry.Properties.TryGetValue ("port", out portStr))
+ throw new Exception ("No port specified");
+
+ if (!Int32.TryParse (portStr, out port))
+ throw new Exception ("Invalid port: \"" + port + "\"");
+
+ if (!entry.Properties.TryGetValue ("family", out family))
+ family = null;
+
+ Open (host, port, family);
+ }
+
+ public void Open (string host, int port, string family)
+ {
+ //TODO: use Socket directly
+ TcpClient client = new TcpClient (host, port);
+ /*
+ client.NoDelay = true;
+ client.ReceiveBufferSize = (int)Protocol.MaxMessageLength;
+ client.SendBufferSize = (int)Protocol.MaxMessageLength;
+ */
+ this.socket = client.Client;
+ SocketHandle = (long)client.Client.Handle;
+ Stream = client.GetStream ();
+ }
+
+ public void Open (Socket socket)
+ {
+ this.socket = socket;
+
+ socket.Blocking = true;
+ SocketHandle = (long)socket.Handle;
+ //Stream = new UnixStream ((int)socket.Handle);
+ Stream = new NetworkStream (socket);
+ }
+
+ public override void WriteCred ()
+ {
+ Stream.WriteByte (0);
+ }
+
+ public override string AuthString ()
+ {
+ return String.Empty;
+ }
+ }
+}
diff --git a/src/Transport.cs b/src/Transport.cs
new file mode 100644
index 0000000..991683d
--- /dev/null
+++ b/src/Transport.cs
@@ -0,0 +1,383 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+
+namespace DBus.Transports
+{
+ abstract class Transport
+ {
+ public static Transport Create (AddressEntry entry)
+ {
+ switch (entry.Method) {
+ case "tcp":
+ {
+ Transport transport = new SocketTransport ();
+ transport.Open (entry);
+ return transport;
+ }
+#if !PORTABLE
+ case "unix":
+ {
+ Transport transport = new UnixNativeTransport ();
+ transport.Open (entry);
+ return transport;
+ }
+#endif
+#if ENABLE_PIPES
+ case "win": {
+ Transport transport = new PipeTransport ();
+ transport.Open (entry);
+ return transport;
+ }
+#endif
+ default:
+ throw new NotSupportedException ("Transport method \"" + entry.Method + "\" not supported");
+ }
+ }
+
+ protected Connection connection;
+
+ public Connection Connection
+ {
+ get {
+ return connection;
+ } set {
+ connection = value;
+ }
+ }
+
+ //TODO: design this properly
+
+ //this is just a temporary solution
+ public Stream Stream;
+ public long SocketHandle;
+ public abstract void Open (AddressEntry entry);
+ public abstract string AuthString ();
+ public abstract void WriteCred ();
+
+ public virtual bool TryGetPeerPid (out uint pid)
+ {
+ pid = 0;
+ return false;
+ }
+
+ Stream ns {
+ get {
+ return this.Stream;
+ }
+ }
+
+ public virtual void Disconnect ()
+ {
+ ns.Dispose ();
+ }
+
+ internal Queue<Message> Inbound = new Queue<Message> ();
+
+ public event EventHandler WakeUp;
+ protected void FireWakeUp ()
+ {
+ if (WakeUp != null)
+ WakeUp (this, EventArgs.Empty);
+ }
+
+ internal Message TryReadMessage ()
+ {
+ GetData ();
+ if (Inbound.Count > 0)
+ return Inbound.Dequeue ();
+ return null;
+ }
+
+ public void Iterate ()
+ {
+ GetData ();
+ }
+
+ internal Message ReadMessage ()
+ {
+ // Hack to complete pending async reads in progress.
+ while (msgRdr != null)
+ GetData ();
+
+ try {
+ return ReadMessageReal ();
+ } catch (IOException e) {
+ if (Protocol.Verbose)
+ Console.Error.WriteLine (e.Message);
+ connection.isConnected = false;
+ return null;
+ }
+ }
+
+ int Read (byte[] buffer, int offset, int count)
+ {
+ int read = 0;
+ //System.Net.Sockets.NetworkStream nns = ns as System.Net.Sockets.NetworkStream;
+ //SocketTransport st = this as SocketTransport;
+ while (read < count) {
+ // FIXME: Remove this hack to support non-blocking sockets on Windows
+ //if (st != null && st.socket.Blocking == false && nns != null && !nns.DataAvailable) {
+ /*
+ if (nns != null && !nns.DataAvailable) {
+ System.Threading.Thread.Sleep (10);
+ continue;
+ }
+ */
+ int nread = ns.Read (buffer, offset + read, count - read);
+ if (nread == 0)
+ break;
+ read += nread;
+ }
+
+ //if (read < count)
+ // throw new Exception ();
+
+ if (read > count)
+ throw new Exception ();
+
+ return read;
+ }
+
+ byte[] mmbuf = null;
+
+ int mmpos = 0;
+ int mmneeded = 16;
+ IEnumerator<MsgState> msgRdr;
+
+ public void GetData ()
+ {
+ if (msgRdr == null) {
+ msgRdr = ReadMessageReal2 ();
+ }
+
+ SocketTransport st = this as SocketTransport;
+
+ int avail = st.socket.Available;
+ if (mmneeded == 0)
+ throw new Exception ();
+
+ if (avail == 0)
+ return;
+
+ avail = Math.Min (avail, mmneeded);
+ int nread = st.socket.Receive (mmbuf, mmpos, avail, System.Net.Sockets.SocketFlags.None);
+ mmpos += nread;
+ mmneeded -= nread;
+ if (!msgRdr.MoveNext ())
+ throw new Exception ();
+
+ MsgState state = msgRdr.Current;
+ if (state != MsgState.Done)
+ return;
+
+ mmpos = 0;
+ mmneeded = 16;
+
+ msgRdr = null;
+ }
+
+ enum MsgState
+ {
+ Wait16,
+ WaitHeader,
+ WaitBody,
+ Done,
+ }
+
+ IEnumerator<MsgState> ReadMessageReal2 ()
+ {
+ byte[] body = null;
+ mmneeded = 16;
+ while (mmpos < 16)
+ yield return MsgState.Wait16;
+
+ EndianFlag endianness = (EndianFlag)mmbuf[0];
+ MessageReader reader = new MessageReader (endianness, mmbuf);
+
+ //discard the endian byte as we've already read it
+ reader.ReadByte ();
+
+ //discard message type and flags, which we don't care about here
+ reader.ReadByte ();
+ reader.ReadByte ();
+
+ byte version = reader.ReadByte ();
+
+ if (version < Protocol.MinVersion || version > Protocol.MaxVersion)
+ throw new NotSupportedException ("Protocol version '" + version.ToString () + "' is not supported");
+
+ if (Protocol.Verbose)
+ if (version != Protocol.Version)
+ Console.Error.WriteLine ("Warning: Protocol version '" + version.ToString () + "' is not explicitly supported but may be compatible");
+
+ uint bodyLength = reader.ReadUInt32 ();
+ //discard serial
+ reader.ReadUInt32 ();
+ uint headerLength = reader.ReadUInt32 ();
+
+ //this check may become relevant if a future version of the protocol allows larger messages
+ /*
+ if (bodyLength > Int32.MaxValue || headerLength > Int32.MaxValue)
+ throw new NotImplementedException ("Long messages are not yet supported");
+ */
+
+ int bodyLen = (int)bodyLength;
+ int toRead = (int)headerLength;
+
+ //we fixup to include the padding following the header
+ toRead = Protocol.Padded (toRead, 8);
+
+ long msgLength = toRead + bodyLen;
+ if (msgLength > Protocol.MaxMessageLength)
+ throw new Exception ("Message length " + msgLength + " exceeds maximum allowed " + Protocol.MaxMessageLength + " bytes");
+
+ byte[] header = new byte[16 + toRead];
+ Array.Copy (mmbuf, header, 16);
+
+ mmneeded = toRead;
+ while (mmpos < 16 + toRead)
+ yield return MsgState.WaitHeader;
+
+ Array.Copy (mmbuf, 16, header, 16, toRead);
+
+ //if (read != toRead)
+ // throw new Exception ("Message header length mismatch: " + read + " of expected " + toRead);
+
+ mmneeded = bodyLen;
+ while (mmpos < 16 + toRead + bodyLen)
+ yield return MsgState.WaitBody;
+
+ //read the body
+ if (bodyLen != 0) {
+ body = new byte[bodyLen];
+
+ Array.Copy (mmbuf, 16 + toRead, body, 0, bodyLen);
+
+ //if (read != bodyLen)
+ // throw new Exception ("Message body length mismatch: " + read + " of expected " + bodyLen);
+ }
+
+ Message msg = new Message ();
+ msg.Connection = this.Connection;
+ msg.Body = body;
+ msg.SetHeaderData (header);
+
+ Inbound.Enqueue (msg);
+
+ mmneeded = 16;
+
+ yield return MsgState.Done;
+ }
+
+ Message ReadMessageReal ()
+ {
+ byte[] header;
+ byte[] body = null;
+
+ int read;
+
+ //16 bytes is the size of the fixed part of the header
+ byte[] hbuf = new byte[16];
+
+ read = Read (hbuf, 0, 16);
+
+ if (read == 0)
+ return null;
+
+ if (read != 16)
+ throw new Exception ("Header read length mismatch: " + read + " of expected " + "16");
+
+ EndianFlag endianness = (EndianFlag)hbuf[0];
+ MessageReader reader = new MessageReader (endianness, hbuf);
+
+ //discard the endian byte as we've already read it
+ reader.ReadByte ();
+
+ //discard message type and flags, which we don't care about here
+ reader.ReadByte ();
+ reader.ReadByte ();
+
+ byte version = reader.ReadByte ();
+
+ if (version < Protocol.MinVersion || version > Protocol.MaxVersion)
+ throw new NotSupportedException ("Protocol version '" + version.ToString () + "' is not supported");
+
+ if (Protocol.Verbose)
+ if (version != Protocol.Version)
+ Console.Error.WriteLine ("Warning: Protocol version '" + version.ToString () + "' is not explicitly supported but may be compatible");
+
+ uint bodyLength = reader.ReadUInt32 ();
+ //discard serial
+ reader.ReadUInt32 ();
+ uint headerLength = reader.ReadUInt32 ();
+
+ //this check may become relevant if a future version of the protocol allows larger messages
+ /*
+ if (bodyLength > Int32.MaxValue || headerLength > Int32.MaxValue)
+ throw new NotImplementedException ("Long messages are not yet supported");
+ */
+
+ int bodyLen = (int)bodyLength;
+ int toRead = (int)headerLength;
+
+ //we fixup to include the padding following the header
+ toRead = Protocol.Padded (toRead, 8);
+
+ long msgLength = toRead + bodyLen;
+ if (msgLength > Protocol.MaxMessageLength)
+ throw new Exception ("Message length " + msgLength + " exceeds maximum allowed " + Protocol.MaxMessageLength + " bytes");
+
+ header = new byte[16 + toRead];
+ Array.Copy (hbuf, header, 16);
+
+ read = Read (header, 16, toRead);
+
+ if (read != toRead)
+ throw new Exception ("Message header length mismatch: " + read + " of expected " + toRead);
+
+ //read the body
+ if (bodyLen != 0) {
+ body = new byte[bodyLen];
+
+ read = Read (body, 0, bodyLen);
+
+ if (read != bodyLen)
+ throw new Exception ("Message body length mismatch: " + read + " of expected " + bodyLen);
+ }
+
+ Message msg = new Message ();
+ msg.Connection = this.Connection;
+ msg.Body = body;
+ msg.SetHeaderData (header);
+
+ return msg;
+ }
+
+ readonly object writeLock = new object ();
+ internal virtual void WriteMessage (Message msg)
+ {
+ /*
+ byte[] HeaderData = msg.GetHeaderData ();
+
+ long msgLength = HeaderData.Length + (msg.Body != null ? msg.Body.Length : 0);
+ if (msgLength > Protocol.MaxMessageLength)
+ throw new Exception ("Message length " + msgLength + " exceeds maximum allowed " + Protocol.MaxMessageLength + " bytes");
+ */
+
+ lock (writeLock) {
+ //ns.Write (HeaderData, 0, HeaderData.Length);
+ msg.GetHeaderDataToStream (ns);
+ if (msg.Body != null && msg.Body.Length != 0)
+ ns.Write (msg.Body, 0, msg.Body.Length);
+ ns.Flush ();
+ }
+
+ }
+ }
+}
diff --git a/src/TypeImplementer.cs b/src/TypeImplementer.cs
new file mode 100644
index 0000000..2d0b106
--- /dev/null
+++ b/src/TypeImplementer.cs
@@ -0,0 +1,909 @@
+// Copyright 2007 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Collections.Generic;
+
+namespace DBus
+{
+ class TypeImplementer
+ {
+ public static readonly TypeImplementer Root = new TypeImplementer ("DBus.Proxies", false);
+ AssemblyBuilder asmB;
+ ModuleBuilder modB;
+ static readonly object getImplLock = new Object ();
+
+ public TypeImplementer (string name, bool canSave)
+ {
+ asmB = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName (name), canSave ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run);
+ modB = asmB.DefineDynamicModule (name);
+ }
+
+ Dictionary<Type,Type> map = new Dictionary<Type,Type> ();
+
+ public Type GetImplementation (Type declType)
+ {
+ Type retT;
+
+ lock (getImplLock)
+ if (map.TryGetValue (declType, out retT))
+ return retT;
+
+ string proxyName = declType.FullName + "Proxy";
+
+ Type parentType;
+
+ if (declType.IsInterface)
+ parentType = typeof (BusObject);
+ else
+ parentType = declType;
+
+ TypeBuilder typeB = modB.DefineType (proxyName, TypeAttributes.Class | TypeAttributes.Public, parentType);
+
+ if (declType.IsInterface)
+ Implement (typeB, declType);
+
+ foreach (Type iface in declType.GetInterfaces ())
+ Implement (typeB, iface);
+
+ retT = typeB.CreateType ();
+
+ lock (getImplLock)
+ map[declType] = retT;
+
+ return retT;
+ }
+
+ static void Implement (TypeBuilder typeB, Type iface)
+ {
+ typeB.AddInterfaceImplementation (iface);
+
+ Dictionary<string,MethodBuilder> builders = new Dictionary<string,MethodBuilder> ();
+
+ foreach (MethodInfo declMethod in iface.GetMethods ()) {
+ ParameterInfo[] parms = declMethod.GetParameters ();
+
+ Type[] parmTypes = new Type[parms.Length];
+ for (int i = 0 ; i < parms.Length ; i++)
+ parmTypes[i] = parms[i].ParameterType;
+
+ MethodAttributes attrs = declMethod.Attributes ^ MethodAttributes.Abstract;
+ attrs ^= MethodAttributes.NewSlot;
+ attrs |= MethodAttributes.Final;
+ MethodBuilder method_builder = typeB.DefineMethod (declMethod.Name, attrs, declMethod.ReturnType, parmTypes);
+ typeB.DefineMethodOverride (method_builder, declMethod);
+
+ //define in/out/ref/name for each of the parameters
+ for (int i = 0; i < parms.Length ; i++)
+ method_builder.DefineParameter (i + 1, parms[i].Attributes, parms[i].Name);
+
+ ILGenerator ilg = method_builder.GetILGenerator ();
+ GenHookupMethod (ilg, declMethod, sendMethodCallMethod, Mapper.GetInterfaceName (iface), declMethod.Name);
+
+ if (declMethod.IsSpecialName)
+ builders[declMethod.Name] = method_builder;
+ }
+
+ foreach (EventInfo declEvent in iface.GetEvents ())
+ {
+ EventBuilder event_builder = typeB.DefineEvent (declEvent.Name, declEvent.Attributes, declEvent.EventHandlerType);
+ event_builder.SetAddOnMethod (builders["add_" + declEvent.Name]);
+ event_builder.SetRemoveOnMethod (builders["remove_" + declEvent.Name]);
+ }
+
+ foreach (PropertyInfo declProp in iface.GetProperties ())
+ {
+ List<Type> indexers = new List<Type> ();
+ foreach (ParameterInfo pi in declProp.GetIndexParameters ())
+ indexers.Add (pi.ParameterType);
+
+ PropertyBuilder prop_builder = typeB.DefineProperty (declProp.Name, declProp.Attributes, declProp.PropertyType, indexers.ToArray ());
+ MethodBuilder mb;
+ if (builders.TryGetValue ("get_" + declProp.Name, out mb))
+ prop_builder.SetGetMethod (mb);
+ if (builders.TryGetValue ("set_" + declProp.Name, out mb))
+ prop_builder.SetSetMethod (mb);
+ }
+ }
+
+ static MethodInfo sendMethodCallMethod = typeof (BusObject).GetMethod ("SendMethodCall");
+ static MethodInfo sendSignalMethod = typeof (BusObject).GetMethod ("SendSignal");
+ static MethodInfo toggleSignalMethod = typeof (BusObject).GetMethod ("ToggleSignal");
+
+ static Dictionary<EventInfo,DynamicMethod> hookup_methods = new Dictionary<EventInfo,DynamicMethod> ();
+ public static DynamicMethod GetHookupMethod (EventInfo ei)
+ {
+ DynamicMethod hookupMethod;
+ if (hookup_methods.TryGetValue (ei, out hookupMethod))
+ return hookupMethod;
+
+ if (ei.EventHandlerType.IsAssignableFrom (typeof (System.EventHandler)))
+ Console.Error.WriteLine ("Warning: Cannot yet fully expose EventHandler and its subclasses: " + ei.EventHandlerType);
+
+ MethodInfo declMethod = ei.EventHandlerType.GetMethod ("Invoke");
+
+ hookupMethod = GetHookupMethod (declMethod, sendSignalMethod, Mapper.GetInterfaceName (ei), ei.Name);
+
+ hookup_methods[ei] = hookupMethod;
+
+ return hookupMethod;
+ }
+
+ public static DynamicMethod GetHookupMethod (MethodInfo declMethod, MethodInfo invokeMethod, string @interface, string member)
+ {
+ ParameterInfo[] delegateParms = declMethod.GetParameters ();
+ Type[] hookupParms = new Type[delegateParms.Length+1];
+ hookupParms[0] = typeof (BusObject);
+ for (int i = 0; i < delegateParms.Length ; i++)
+ hookupParms[i+1] = delegateParms[i].ParameterType;
+
+ DynamicMethod hookupMethod = new DynamicMethod ("Handle" + member, declMethod.ReturnType, hookupParms, typeof (MessageWriter));
+
+ ILGenerator ilg = hookupMethod.GetILGenerator ();
+
+ GenHookupMethod (ilg, declMethod, invokeMethod, @interface, member);
+
+ return hookupMethod;
+ }
+
+ static MethodInfo getTypeFromHandleMethod = typeof (Type).GetMethod ("GetTypeFromHandle", new Type[] {typeof (RuntimeTypeHandle)});
+ static ConstructorInfo argumentNullExceptionConstructor = typeof (ArgumentNullException).GetConstructor (new Type[] {typeof (string)});
+ static ConstructorInfo messageWriterConstructor = typeof (MessageWriter).GetConstructor (Type.EmptyTypes);
+ static MethodInfo messageWriterWritePad = typeof (MessageWriter).GetMethod ("WritePad", new Type[] {typeof (int)});
+ static MethodInfo messageReaderReadPad = typeof (MessageReader).GetMethod ("ReadPad", new Type[] {typeof (int)});
+
+ static Dictionary<Type,MethodInfo> writeMethods = new Dictionary<Type,MethodInfo> ();
+
+ public static MethodInfo GetWriteMethod (Type t)
+ {
+ MethodInfo meth;
+
+ if (writeMethods.TryGetValue (t, out meth))
+ return meth;
+
+ DynamicMethod method_builder = new DynamicMethod ("Write" + t.Name, typeof (void), new Type[] {typeof (MessageWriter), t}, typeof (MessageWriter), true);
+
+ ILGenerator ilg = method_builder.GetILGenerator ();
+
+ ilg.Emit (OpCodes.Ldarg_0);
+ ilg.Emit (OpCodes.Ldarg_1);
+
+ GenWriter (ilg, t);
+
+ ilg.Emit (OpCodes.Ret);
+
+ meth = method_builder;
+
+ writeMethods[t] = meth;
+ return meth;
+ }
+
+ static Dictionary<Type,object> typeWriters = new Dictionary<Type,object> ();
+ public static TypeWriter<T> GetTypeWriter<T> ()
+ {
+ Type t = typeof (T);
+
+ object value;
+ if (typeWriters.TryGetValue (t, out value))
+ return (TypeWriter<T>)value;
+
+ MethodInfo mi = GetWriteMethod (t);
+ DynamicMethod dm = mi as DynamicMethod;
+ if (dm == null)
+ return null;
+
+ TypeWriter<T> tWriter = dm.CreateDelegate (typeof (TypeWriter<T>)) as TypeWriter<T>;
+ typeWriters[t] = tWriter;
+ return tWriter;
+ }
+
+ //takes the Writer instance and the value of Type t off the stack, writes it
+ public static void GenWriter (ILGenerator ilg, Type t)
+ {
+ Type tUnder = t;
+
+ if (t.IsEnum) {
+ tUnder = Enum.GetUnderlyingType (t);
+ //imprecise = true;
+ }
+
+ Type type = t;
+
+ //MethodInfo exactWriteMethod = typeof (MessageWriter).GetMethod ("Write", new Type[] {tUnder});
+ MethodInfo exactWriteMethod = typeof (MessageWriter).GetMethod ("Write", BindingFlags.ExactBinding | BindingFlags.Instance | BindingFlags.Public, null, new Type[] {tUnder}, null);
+ //ExactBinding InvokeMethod
+
+ if (exactWriteMethod != null) {
+ ilg.Emit (exactWriteMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, exactWriteMethod);
+ } else if (t.IsArray) {
+ MethodInfo mi = typeof (MessageWriter).GetMethod ("WriteArray");
+ exactWriteMethod = mi.MakeGenericMethod (type.GetElementType ());
+ ilg.Emit (exactWriteMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, exactWriteMethod);
+ } else if (type.IsGenericType && (type.GetGenericTypeDefinition () == typeof (IDictionary<,>) || type.GetGenericTypeDefinition () == typeof (Dictionary<,>))) {
+ Type[] genArgs = type.GetGenericArguments ();
+ MethodInfo mi = typeof (MessageWriter).GetMethod ("WriteFromDict");
+ exactWriteMethod = mi.MakeGenericMethod (genArgs);
+ ilg.Emit (exactWriteMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, exactWriteMethod);
+ } else {
+ GenStructWriter (ilg, t);
+ }
+ }
+
+ public static IEnumerable<FieldInfo> GetMarshalFields (Type type)
+ {
+ // FIXME: Field order!
+ return type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+ }
+
+ //takes a writer and a reference to an object off the stack
+ public static void GenStructWriter (ILGenerator ilg, Type type)
+ {
+ LocalBuilder val = ilg.DeclareLocal (type);
+ ilg.Emit (OpCodes.Stloc, val);
+
+ LocalBuilder writer = ilg.DeclareLocal (typeof (MessageWriter));
+ ilg.Emit (OpCodes.Stloc, writer);
+
+ //align to 8 for structs
+ ilg.Emit (OpCodes.Ldloc, writer);
+ ilg.Emit (OpCodes.Ldc_I4, 8);
+ ilg.Emit (OpCodes.Call, messageWriterWritePad);
+
+ foreach (FieldInfo fi in GetMarshalFields (type)) {
+ Type t = fi.FieldType;
+
+ // null checking of fields
+ if (!t.IsValueType) {
+ Label notNull = ilg.DefineLabel ();
+
+ //if the value is null...
+ //ilg.Emit (OpCodes.Ldarg, i);
+ ilg.Emit (OpCodes.Ldloc, val);
+ ilg.Emit (OpCodes.Ldfld, fi);
+
+ ilg.Emit (OpCodes.Brtrue_S, notNull);
+
+ //...throw Exception
+ string paramName = fi.Name;
+ ilg.Emit (OpCodes.Ldstr, paramName);
+ // TODO: Should not really be argumentNullException
+ ilg.Emit (OpCodes.Newobj, argumentNullExceptionConstructor);
+ ilg.Emit (OpCodes.Throw);
+
+ //was not null, so all is well
+ ilg.MarkLabel (notNull);
+ }
+
+ //the Writer to write to
+ ilg.Emit (OpCodes.Ldloc, writer);
+
+ //the object to read from
+ ilg.Emit (OpCodes.Ldloc, val);
+ ilg.Emit (OpCodes.Ldfld, fi);
+
+ GenWriter (ilg, t);
+ }
+ }
+
+ //takes a reader and a reference to an object off the stack
+ public static void GenStructReader (ILGenerator ilg, Type type)
+ {
+ // FIXME: Newobj fails if type has no default ctor!
+
+ LocalBuilder val = ilg.DeclareLocal (type);
+ ConstructorInfo ctor = type.GetConstructor (Type.EmptyTypes);
+ ilg.Emit (OpCodes.Newobj, ctor);
+ ilg.Emit (OpCodes.Stloc, val);
+
+ LocalBuilder reader = ilg.DeclareLocal (typeof (MessageReader));
+ ilg.Emit (OpCodes.Stloc, reader);
+
+ //align to 8 for structs
+ ilg.Emit (OpCodes.Ldloc, reader);
+ ilg.Emit (OpCodes.Ldc_I4, 8);
+ ilg.Emit (OpCodes.Call, messageReaderReadPad);
+
+ foreach (FieldInfo fi in GetMarshalFields (type)) {
+ Type t = fi.FieldType;
+
+ //the object to read into
+ ilg.Emit (OpCodes.Ldloc, val);
+
+ //the Reader to read from
+ ilg.Emit (OpCodes.Ldloc, reader);
+
+ GenReader (ilg, t);
+
+ ilg.Emit (OpCodes.Stfld, fi);
+ }
+
+ ilg.Emit (OpCodes.Ldloc, val);
+ //if (type.IsValueType)
+ // ilg.Emit (OpCodes.Box, type);
+ }
+
+ static MethodInfo getBusObject = typeof(BusObject).GetMethod("GetBusObject");
+
+ public static void GenHookupMethod (ILGenerator ilg, MethodInfo declMethod, MethodInfo invokeMethod, string @interface, string member)
+ {
+ ParameterInfo[] parms = declMethod.GetParameters ();
+ Type retType = declMethod.ReturnType;
+
+ //the BusObject instance
+ ilg.Emit (OpCodes.Ldarg_0);
+
+ ilg.Emit (OpCodes.Call, getBusObject);
+
+ //MethodInfo
+
+ //interface
+ ilg.Emit (OpCodes.Ldstr, @interface);
+
+ //special case event add/remove methods
+ if (declMethod.IsSpecialName && (declMethod.Name.StartsWith ("add_") || declMethod.Name.StartsWith ("remove_"))) {
+ string[] parts = declMethod.Name.Split (new char[]{'_'}, 2);
+ string ename = parts[1];
+ //Delegate dlg = (Delegate)inArgs[0];
+ bool adding = parts[0] == "add";
+
+ ilg.Emit (OpCodes.Ldstr, ename);
+
+ ilg.Emit (OpCodes.Ldarg_1);
+
+ ilg.Emit (OpCodes.Ldc_I4, adding ? 1 : 0);
+
+ ilg.Emit (OpCodes.Tailcall);
+ ilg.Emit (toggleSignalMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, toggleSignalMethod);
+ ilg.Emit (OpCodes.Ret);
+ return;
+ }
+
+ //property accessor mapping
+ if (declMethod.IsSpecialName) {
+ if (member.StartsWith ("get_"))
+ member = "Get" + member.Substring (4);
+ else if (member.StartsWith ("set_"))
+ member = "Set" + member.Substring (4);
+ }
+
+ //member
+ ilg.Emit (OpCodes.Ldstr, member);
+
+ //signature
+ Signature inSig = Signature.Empty;
+ Signature outSig = Signature.Empty;
+ SigsForMethod (declMethod, out inSig, out outSig);
+
+ ilg.Emit (OpCodes.Ldstr, inSig.Value);
+
+ LocalBuilder writer = ilg.DeclareLocal (typeof (MessageWriter));
+ ilg.Emit (OpCodes.Newobj, messageWriterConstructor);
+ ilg.Emit (OpCodes.Stloc, writer);
+
+ foreach (ParameterInfo parm in parms)
+ {
+ if (parm.IsOut)
+ continue;
+
+ Type t = parm.ParameterType;
+ //offset by one to account for "this"
+ int i = parm.Position + 1;
+
+ //null checking of parameters (but not their recursive contents)
+ if (!t.IsValueType) {
+ Label notNull = ilg.DefineLabel ();
+
+ //if the value is null...
+ ilg.Emit (OpCodes.Ldarg, i);
+ ilg.Emit (OpCodes.Brtrue_S, notNull);
+
+ //...throw Exception
+ string paramName = parm.Name;
+ ilg.Emit (OpCodes.Ldstr, paramName);
+ ilg.Emit (OpCodes.Newobj, argumentNullExceptionConstructor);
+ ilg.Emit (OpCodes.Throw);
+
+ //was not null, so all is well
+ ilg.MarkLabel (notNull);
+ }
+
+ ilg.Emit (OpCodes.Ldloc, writer);
+
+ //the parameter
+ ilg.Emit (OpCodes.Ldarg, i);
+
+ GenWriter (ilg, t);
+ }
+
+ ilg.Emit (OpCodes.Ldloc, writer);
+
+ //the expected return Type
+ ilg.Emit (OpCodes.Ldtoken, retType);
+ ilg.Emit (OpCodes.Call, getTypeFromHandleMethod);
+
+ LocalBuilder exc = ilg.DeclareLocal (typeof (Exception));
+ ilg.Emit (OpCodes.Ldloca_S, exc);
+
+ //make the call
+ ilg.Emit (invokeMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, invokeMethod);
+
+ //define a label we'll use to deal with a non-null Exception
+ Label noErr = ilg.DefineLabel ();
+
+ //if the out Exception is not null...
+ ilg.Emit (OpCodes.Ldloc, exc);
+ ilg.Emit (OpCodes.Brfalse_S, noErr);
+
+ //...throw it.
+ ilg.Emit (OpCodes.Ldloc, exc);
+ ilg.Emit (OpCodes.Throw);
+
+ //Exception was null, so all is well
+ ilg.MarkLabel (noErr);
+
+ if (invokeMethod.ReturnType == typeof (MessageReader)) {
+ LocalBuilder reader = ilg.DeclareLocal (typeof (MessageReader));
+ ilg.Emit (OpCodes.Stloc, reader);
+
+ foreach (ParameterInfo parm in parms)
+ {
+ //t.IsByRef
+ if (!parm.IsOut)
+ continue;
+
+ Type t = parm.ParameterType.GetElementType ();
+ //offset by one to account for "this"
+ int i = parm.Position + 1;
+
+ ilg.Emit (OpCodes.Ldarg, i);
+ ilg.Emit (OpCodes.Ldloc, reader);
+ GenReader (ilg, t);
+ ilg.Emit (OpCodes.Stobj, t);
+ }
+
+ if (retType != typeof (void)) {
+ ilg.Emit (OpCodes.Ldloc, reader);
+ GenReader (ilg, retType);
+ }
+
+ ilg.Emit (OpCodes.Ret);
+ return;
+ }
+
+ if (retType == typeof (void)) {
+ //we aren't expecting a return value, so throw away the (hopefully) null return
+ if (invokeMethod.ReturnType != typeof (void))
+ ilg.Emit (OpCodes.Pop);
+ } else {
+ if (retType.IsValueType)
+ ilg.Emit (OpCodes.Unbox_Any, retType);
+ else
+ ilg.Emit (OpCodes.Castclass, retType);
+ }
+
+ ilg.Emit (OpCodes.Ret);
+ }
+
+
+ public static bool SigsForMethod (MethodInfo mi, out Signature inSig, out Signature outSig)
+ {
+ inSig = Signature.Empty;
+ outSig = Signature.Empty;
+
+ foreach (ParameterInfo parm in mi.GetParameters ()) {
+ if (parm.IsOut)
+ outSig += Signature.GetSig (parm.ParameterType.GetElementType ());
+ else
+ inSig += Signature.GetSig (parm.ParameterType);
+ }
+
+ outSig += Signature.GetSig (mi.ReturnType);
+
+ return true;
+ }
+
+ static Dictionary<Type,MethodInfo> readMethods = new Dictionary<Type,MethodInfo> ();
+ static void InitReaders ()
+ {
+ foreach (MethodInfo mi in typeof (MessageReader).GetMethods (BindingFlags.Instance | BindingFlags.Public)) {
+ if (!mi.Name.StartsWith ("Read"))
+ continue;
+ if (mi.ReturnType == typeof (void))
+ continue;
+ if (mi.GetParameters ().Length != 0)
+ continue;
+
+ readMethods[mi.ReturnType] = mi;
+ }
+ }
+
+ internal static MethodInfo GetReadMethod (Type t)
+ {
+ if (readMethods.Count == 0)
+ InitReaders ();
+
+ MethodInfo mi;
+ if (readMethods.TryGetValue (t, out mi))
+ return mi;
+
+ return null;
+ }
+
+ internal static MethodCaller2 GenCaller2 (MethodInfo target)
+ {
+ DynamicMethod hookupMethod = GenReadMethod (target);
+ MethodCaller2 caller = hookupMethod.CreateDelegate (typeof (MethodCaller2)) as MethodCaller2;
+ return caller;
+ }
+
+ internal static MethodCaller GenCaller (MethodInfo target, object targetInstance)
+ {
+ DynamicMethod hookupMethod = GenReadMethod (target);
+ MethodCaller caller = hookupMethod.CreateDelegate (typeof (MethodCaller), targetInstance) as MethodCaller;
+ return caller;
+ }
+
+ internal static DynamicMethod GenReadMethod (MethodInfo target)
+ {
+ Type[] parms = new Type[] { typeof (object), typeof (MessageReader), typeof (Message), typeof (MessageWriter) };
+ DynamicMethod hookupMethod = new DynamicMethod ("Caller", typeof (void), parms, typeof (MessageReader));
+ Gen (hookupMethod, target);
+ return hookupMethod;
+ }
+
+ static void Gen (DynamicMethod hookupMethod, MethodInfo declMethod)
+ {
+ ILGenerator ilg = hookupMethod.GetILGenerator ();
+
+ ParameterInfo[] parms = declMethod.GetParameters ();
+ Type retType = declMethod.ReturnType;
+
+ // The target instance
+ ilg.Emit (OpCodes.Ldarg_0);
+
+ Dictionary<ParameterInfo,LocalBuilder> locals = new Dictionary<ParameterInfo,LocalBuilder> ();
+
+ foreach (ParameterInfo parm in parms) {
+
+ Type parmType = parm.ParameterType;
+
+ if (parm.IsOut) {
+ LocalBuilder parmLocal = ilg.DeclareLocal (parmType.GetElementType ());
+ locals[parm] = parmLocal;
+ ilg.Emit (OpCodes.Ldloca, parmLocal);
+ continue;
+ }
+
+ ilg.Emit (OpCodes.Ldarg_1);
+ GenReader (ilg, parmType);
+ }
+
+ ilg.Emit (declMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, declMethod);
+
+ foreach (ParameterInfo parm in parms) {
+ if (!parm.IsOut)
+ continue;
+
+ Type parmType = parm.ParameterType.GetElementType ();
+
+ LocalBuilder parmLocal = locals[parm];
+ ilg.Emit (OpCodes.Ldarg_3); // writer
+ ilg.Emit (OpCodes.Ldloc, parmLocal);
+ GenWriter (ilg, parmType);
+ }
+
+ if (retType != typeof (void)) {
+ // Skip reply message construction if MessageWriter is null
+
+ LocalBuilder retLocal = ilg.DeclareLocal (retType);
+ ilg.Emit (OpCodes.Stloc, retLocal);
+
+ ilg.Emit (OpCodes.Ldarg_3); // writer
+ ilg.Emit (OpCodes.Ldloc, retLocal);
+ GenWriter (ilg, retType);
+
+ }
+
+ ilg.Emit (OpCodes.Ret);
+ }
+
+ //takes the Reader instance off the stack, puts value of type t on the stack
+ public static void GenReader (ILGenerator ilg, Type t)
+ {
+ // TODO: Cache generated methods
+ // TODO: Generate methods with the correct module/type permissions
+
+ Type tUnder = t;
+
+ if (t.IsEnum)
+ tUnder = Enum.GetUnderlyingType (t);
+
+ MethodInfo exactMethod = GetReadMethod (tUnder);
+ if (exactMethod != null)
+ ilg.Emit (exactMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, exactMethod);
+ else if (t.IsArray)
+ GenReadCollection (ilg, t);
+ else if (t.IsGenericType && (t.GetGenericTypeDefinition () == typeof (IList<>)))
+ GenReadCollection (ilg, t);
+ else if (t.IsGenericType && (t.GetGenericTypeDefinition () == typeof (IDictionary<,>) || t.GetGenericTypeDefinition () == typeof (Dictionary<,>)))
+ GenReadCollection (ilg, t);
+ else if (t.IsInterface)
+ GenFallbackReader (ilg, tUnder);
+ else if (!tUnder.IsValueType) {
+ GenStructReader (ilg, tUnder);
+ } else
+ GenFallbackReader (ilg, tUnder);
+ }
+
+ public static void GenFallbackReader (ILGenerator ilg, Type t)
+ {
+ // TODO: do we want non-tUnder here for Castclass use?
+ if (Protocol.Verbose)
+ Console.Error.WriteLine ("Bad! Generating fallback reader for " + t);
+
+ MethodInfo exactMethod;
+ exactMethod = typeof (MessageReader).GetMethod ("ReadValue", new Type[] { typeof (System.Type) });
+
+ // The Type parameter
+ ilg.Emit (OpCodes.Ldtoken, t);
+ ilg.Emit (OpCodes.Call, getTypeFromHandleMethod);
+
+ ilg.Emit (exactMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, exactMethod);
+
+ if (t.IsValueType)
+ ilg.Emit (OpCodes.Unbox_Any, t);
+ else
+ ilg.Emit (OpCodes.Castclass, t);
+ }
+
+ public static void GenReadArrayFixed (ILGenerator ilg, Type t, int knownElemSize)
+ {
+ LocalBuilder readerLocal = ilg.DeclareLocal (typeof (MessageReader));
+ ilg.Emit (OpCodes.Stloc, readerLocal);
+
+ Type tElem = t.GetElementType ();
+ Signature sigElem = Signature.GetSig (tElem);
+ int alignElem = sigElem.Alignment;
+ int knownElemSizePadded = Protocol.Padded (knownElemSize, sigElem.Alignment);
+ Type tUnder = tElem.IsEnum ? Enum.GetUnderlyingType (tElem) : tElem;
+ int managedElemSize = System.Runtime.InteropServices.Marshal.SizeOf (tUnder);
+
+ // Read the array's byte length
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ MethodInfo exactMethod = GetReadMethod (typeof (uint));
+ ilg.Emit (exactMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, exactMethod);
+ LocalBuilder sizeLocal = ilg.DeclareLocal (typeof (uint));
+ ilg.Emit (OpCodes.Stloc, sizeLocal);
+
+ // Create a new array of the correct element length
+ ilg.Emit (OpCodes.Ldloc, sizeLocal);
+ if (knownElemSizePadded > 1) {
+ ilg.Emit (OpCodes.Ldc_I4, alignElem);
+ MethodInfo paddedMethod = typeof (Protocol).GetMethod ("Padded");
+ ilg.Emit (OpCodes.Call, paddedMethod);
+ // Divide by the known element size
+ ilg.Emit (OpCodes.Ldc_I4, knownElemSizePadded);
+ ilg.Emit (OpCodes.Div_Un);
+ }
+ ilg.Emit (OpCodes.Newarr, tElem);
+ LocalBuilder aryLocal = ilg.DeclareLocal (t);
+ ilg.Emit (OpCodes.Stloc, aryLocal);
+
+ Label nonBlitLabel = ilg.DefineLabel ();
+ Label endLabel = ilg.DefineLabel ();
+
+ // Skip read or blit for zero-length arrays.
+ ilg.Emit (OpCodes.Ldloc, sizeLocal);
+ ilg.Emit (OpCodes.Brfalse, endLabel);
+
+ // WARNING: This may skew pos when we later increment it!
+ if (alignElem > 4) {
+ // Align to element if alignment requirement is higher than 4 (since we just read a uint)
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ ilg.Emit (OpCodes.Ldc_I4, alignElem);
+ ilg.Emit (OpCodes.Call, messageReaderReadPad);
+ }
+
+ // Blit where possible
+
+ // shouldBlit: Blit if endian is native
+ // mustBlit: Blit regardless of endian (ie. byte or structs containing only bytes)
+
+ bool shouldBlit = tElem.IsValueType && knownElemSizePadded == managedElemSize && !sigElem.IsStruct;
+
+ // bool and char are not reliably blittable, so we don't allow blitting in these cases.
+ // Their exact layout varies between runtimes, platforms and even data types.
+ shouldBlit &= tElem != typeof (bool) && tElem != typeof (char);
+
+ bool mustBlit = shouldBlit && knownElemSizePadded == 1;
+
+ if (shouldBlit) {
+ if (!mustBlit) {
+ // Check to see if we can blit the data structures
+ FieldInfo nativeEndianField = typeof (MessageReader).GetField ("IsNativeEndian");
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ ilg.Emit (OpCodes.Ldfld, nativeEndianField);
+ ilg.Emit (OpCodes.Brfalse_S, nonBlitLabel);
+ }
+
+ // Get the destination address
+ ilg.Emit (OpCodes.Ldloc, aryLocal);
+ ilg.Emit (OpCodes.Ldc_I4_0);
+ ilg.Emit (OpCodes.Ldelema, tElem);
+
+ // Get the source address
+ FieldInfo dataField = typeof (MessageReader).GetField ("data");
+ FieldInfo posField = typeof (MessageReader).GetField ("pos");
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ ilg.Emit (OpCodes.Ldfld, dataField);
+ {
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ ilg.Emit (OpCodes.Ldfld, posField);
+ }
+ ilg.Emit (OpCodes.Ldelema, typeof (byte));
+
+ // The number of bytes to copy
+ ilg.Emit (OpCodes.Ldloc, sizeLocal);
+
+ // Blit the array
+ ilg.Emit (OpCodes.Cpblk);
+
+ // pos += bytesRead
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ ilg.Emit (OpCodes.Ldfld, posField);
+ ilg.Emit (OpCodes.Ldloc, sizeLocal);
+ ilg.Emit (OpCodes.Add);
+ ilg.Emit (OpCodes.Stfld, posField);
+
+ ilg.Emit (OpCodes.Br, endLabel);
+ }
+
+ if (!mustBlit) {
+ ilg.MarkLabel (nonBlitLabel);
+
+ // for (int i = 0 ; i < ary.Length ; i++)
+ LocalBuilder indexLocal = ilg.DeclareLocal (typeof (int));
+ ilg.Emit (OpCodes.Ldc_I4_0);
+ ilg.Emit (OpCodes.Stloc, indexLocal);
+
+ Label loopStartLabel = ilg.DefineLabel ();
+ Label loopEndLabel = ilg.DefineLabel ();
+
+ ilg.Emit (OpCodes.Br, loopEndLabel);
+
+ ilg.MarkLabel (loopStartLabel);
+
+ {
+ // Read and store an element to the array
+ ilg.Emit (OpCodes.Ldloc, aryLocal);
+ ilg.Emit (OpCodes.Ldloc, indexLocal);
+
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ GenReader (ilg, tElem);
+
+ ilg.Emit (OpCodes.Stelem, tElem);
+ }
+
+ // i++
+ ilg.Emit (OpCodes.Ldloc, indexLocal);
+ ilg.Emit (OpCodes.Ldc_I4_1);
+ ilg.Emit (OpCodes.Add);
+ ilg.Emit (OpCodes.Stloc, indexLocal);
+
+ ilg.MarkLabel (loopEndLabel);
+ ilg.Emit (OpCodes.Ldloc, indexLocal);
+ ilg.Emit (OpCodes.Ldloc, aryLocal);
+ ilg.Emit (OpCodes.Ldlen);
+ ilg.Emit (OpCodes.Blt, loopStartLabel);
+ }
+
+ ilg.MarkLabel (endLabel);
+
+ // Return the new array
+ ilg.Emit (OpCodes.Ldloc, aryLocal);
+ }
+
+ public static void GenReadCollection (ILGenerator ilg, Type type)
+ {
+ int fixedSize = 0;
+ if (type.IsArray && Signature.GetSig (type.GetElementType ()).GetFixedSize (ref fixedSize)) {
+ GenReadArrayFixed (ilg, type, fixedSize);
+ return;
+ }
+
+ LocalBuilder readerLocal = ilg.DeclareLocal (typeof (MessageReader));
+ ilg.Emit (OpCodes.Stloc, readerLocal);
+
+ Type[] genArgs = type.IsArray ? new Type[] { type.GetElementType () } : type.GetGenericArguments ();
+
+ Type collType = Mapper.GetGenericType (genArgs.Length == 2 ? typeof (Dictionary<,>) : typeof (List<>), genArgs);
+
+ ConstructorInfo ctor = collType.GetConstructor (Type.EmptyTypes);
+ ilg.Emit (OpCodes.Newobj, ctor);
+
+ LocalBuilder collLocal = ilg.DeclareLocal (collType);
+ ilg.Emit (OpCodes.Stloc, collLocal);
+
+ MethodInfo addMethod = collType.GetMethod ("Add", genArgs);
+
+
+ // Read the array's byte length
+ MethodInfo readUInt32Method = GetReadMethod (typeof (uint));
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ ilg.Emit (readUInt32Method.IsFinal ? OpCodes.Call : OpCodes.Callvirt, readUInt32Method);
+
+ {
+ // Align to 8 for structs
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ // TODO: This padding logic is sketchy
+ ilg.Emit (OpCodes.Ldc_I4, genArgs.Length > 1 ? 8 : Signature.GetSig (genArgs[0]).Alignment);
+ ilg.Emit (OpCodes.Call, messageReaderReadPad);
+ }
+
+ // Similar to the fixed array loop code
+
+ FieldInfo posField = typeof (MessageReader).GetField ("pos");
+ LocalBuilder endPosLocal = ilg.DeclareLocal (typeof (int));
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ ilg.Emit (OpCodes.Ldfld, posField);
+
+ // Add the current position and byte length to determine endPos
+ // TODO: Consider padding?
+ ilg.Emit (OpCodes.Add);
+ ilg.Emit (OpCodes.Stloc, endPosLocal);
+
+ {
+ Label loopStartLabel = ilg.DefineLabel ();
+ Label loopEndLabel = ilg.DefineLabel ();
+
+ ilg.Emit (OpCodes.Br, loopEndLabel);
+
+ ilg.MarkLabel (loopStartLabel);
+
+ {
+ if (genArgs.Length > 1) {
+ // Align to 8 for structs
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ ilg.Emit (OpCodes.Ldc_I4, 8);
+ ilg.Emit (OpCodes.Call, messageReaderReadPad);
+ }
+
+ // Read and store an element to the array
+ ilg.Emit (OpCodes.Ldloc, collLocal);
+
+ foreach (Type genArg in genArgs) {
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ GenReader (ilg, genArg);
+ }
+
+ ilg.Emit (OpCodes.Call, addMethod);
+ }
+
+ ilg.MarkLabel (loopEndLabel);
+
+ ilg.Emit (OpCodes.Ldloc, readerLocal);
+ ilg.Emit (OpCodes.Ldfld, posField);
+
+ ilg.Emit (OpCodes.Ldloc, endPosLocal);
+ ilg.Emit (OpCodes.Blt, loopStartLabel);
+ }
+
+ // Return the new collection
+ ilg.Emit (OpCodes.Ldloc, collLocal);
+
+ if (type.IsArray) {
+ MethodInfo toArrayMethod = collType.GetMethod ("ToArray", Type.EmptyTypes);
+ ilg.Emit (OpCodes.Call, toArrayMethod);
+ }
+ }
+ }
+
+ internal delegate void TypeWriter<T> (MessageWriter writer, T value);
+
+ internal delegate void MethodCaller (MessageReader rdr, Message msg, MessageWriter ret);
+ internal delegate void MethodCaller2 (object instance, MessageReader rdr, Message msg, MessageWriter ret);
+}
diff --git a/src/TypeRental.cs b/src/TypeRental.cs
new file mode 100644
index 0000000..96af149
--- /dev/null
+++ b/src/TypeRental.cs
@@ -0,0 +1,504 @@
+// Copyright 2009 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Collections.Generic;
+
+namespace DBus
+{
+ public class ILReader2
+ {
+ public byte[] m_byteArray;
+ Int32 m_position;
+ MethodBase m_enclosingMethod;
+
+ static OpCode[] s_OneByteOpCodes = new OpCode[0x100];
+ static OpCode[] s_TwoByteOpCodes = new OpCode[0x100];
+ static ILReader2()
+ {
+ foreach (FieldInfo fi in typeof(OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static))
+ {
+ OpCode opCode = (OpCode)fi.GetValue(null);
+ UInt16 value = (UInt16)opCode.Value;
+ if (value < 0x100)
+ s_OneByteOpCodes[value] = opCode;
+ else if ((value & 0xff00) == 0xfe00)
+ s_TwoByteOpCodes[value & 0xff] = opCode;
+ }
+ }
+
+ /*
+ public ILReader(MethodBase enclosingMethod)
+ {
+ this.m_enclosingMethod = enclosingMethod;
+ MethodBody methodBody = m_enclosingMethod.GetMethodBody();
+ this.m_byteArray = (methodBody == null) ? new Byte[0] : methodBody.GetILAsByteArray();
+ this.m_position = 0;
+ }
+ */
+
+ public ILReader2(MethodBase enclosingMethod)
+ {
+ this.m_enclosingMethod = enclosingMethod;
+ MethodBody methodBody = m_enclosingMethod.GetMethodBody();
+ this.m_byteArray = (methodBody == null) ? new Byte[0] : methodBody.GetILAsByteArray();
+ this.m_position = 0;
+ }
+
+ public ILOp[] Iterate()
+ {
+ List<ILOp> data = new List<ILOp>();
+
+ while (m_position < m_byteArray.Length) {
+ Next();
+
+ if (current.operandType == null)
+ current.operandType = String.Empty;
+
+ if (current.operand == null)
+ current.operand = String.Empty;
+
+ data.Add(current);
+ }
+
+ //Console.WriteLine("dataCount: " + data.Count);
+ m_position = 0;
+
+ return data.ToArray();
+ }
+
+ public struct ILOp
+ {
+ /*
+ public ILOp(OpCodeType opType, string operandType)
+ {
+ this.opType = opType;
+ this.operandType = operandType;
+ this.operand = String.Empty;
+ }
+ */
+
+ public OpCode opCode;
+
+ //public OpCodeType opType;
+ public string operandType;
+ public object operand;
+
+ /*
+ public string operandType
+ {
+ get {
+ //return String.Empty;
+ return String.Empty;
+ } set {
+ }
+ }
+ */
+ public Type operandTypeT
+ {
+ get {
+ //return String.Empty;
+ if (operandType == String.Empty)
+ return null;
+ return Type.GetType("System" + Type.Delimiter + operandType);
+ }
+ }
+
+ /*
+ public string operand
+ {
+ get {
+ return String.Empty;
+ } set {
+ }
+ }
+ */
+
+
+ /*
+ public OpCode _opCode
+ {
+ get {
+ //UInt16 value = (UInt16)opCode.Value;
+ UInt16 value = (UInt16)opCodeValue;
+ if (value < 0x100)
+ s_OneByteOpCodes[value] = opCode;
+ else if ((value & 0xff00) == 0xfe00)
+ s_TwoByteOpCodes[value & 0xff] = opCode;
+ }
+ }
+ */
+
+ static Type ilgType = typeof(ILGenerator);
+
+ public bool Emit(ILGenerator ilg)
+ {
+ Type t = operandTypeT;
+
+ if (t == null) {
+ //Console.WriteLine("emitsimple: " + opCode);
+ if (ilg != null)
+ ilg.Emit(opCode);
+ return true;
+ }
+
+ MethodInfo emitmi = ilgType.GetMethod("Emit", new Type[] {typeof(OpCode), t});
+ //Console.WriteLine("emitmi: " + opCode + " " + emitmi);
+
+ object operandObj = null;
+
+ //if (t == typeof(MethodInfo)) {
+ if (typeof(MemberInfo).IsAssignableFrom(t)) {
+ string operandStr = (string)operand;
+ int idx = operandStr.LastIndexOf(Type.Delimiter);
+ if (idx < 0)
+ return false;
+ string ifaceName = operandStr.Remove(idx);
+ string methName = operandStr.Substring(idx + 1);
+
+ //Console.WriteLine("ifacename: " + ifaceName);
+ //Console.WriteLine("methname: " + methName);
+
+ Type declType = Type.GetType(ifaceName);
+ if (declType == null)
+ declType = Assembly.GetExecutingAssembly().GetType(ifaceName, false);
+ if (declType == null)
+ declType = Assembly.GetCallingAssembly().GetType(ifaceName, false);
+
+ if (declType == null)
+ return false;
+
+ //MethodInfo mi = declType.GetMethod(methName);
+ //if (mi == null)
+ // return false;
+ MemberInfo[] mis = declType.GetMember(methName);
+ if (mis.Length == 0)
+ return false;
+
+ MemberInfo mi = mis[0];
+
+ //Console.WriteLine("good!: " + mi);
+
+ operandObj = mi;
+ } else if (t == typeof(string))
+ operandObj = (string)operand;
+ else
+ operandObj = Convert.ChangeType(operand, t);
+
+ //Console.WriteLine("operandObj: " + operandObj);
+ if (ilg != null)
+ emitmi.Invoke(ilg, new object[] { opCode, operandObj });
+
+ /*
+ switch (operandType) {
+ case nu:
+ ilg.Emit(opCode);
+ return true;
+ case "MethodInfo":
+ MethodInfo mi = null;
+ ilg.Emit(opCode, mi);
+ return true;
+ }
+ */
+
+ return true;
+ }
+ }
+
+ public static bool TryGetType(string ifaceName, out Type declType)
+ {
+ declType = Type.GetType(ifaceName);
+ if (declType == null)
+ declType = Assembly.GetExecutingAssembly().GetType(ifaceName, false);
+ if (declType == null)
+ declType = Assembly.GetCallingAssembly().GetType(ifaceName, false);
+ return declType != null;
+ }
+
+
+ ILOp current;
+
+ void Next()
+ {
+ Int32 offset = m_position;
+ OpCode opCode = OpCodes.Nop;
+ int token = 0;
+
+ // read first 1 or 2 bytes as opCode
+ Byte code = ReadByte();
+ if (code != 0xFE)
+ opCode = s_OneByteOpCodes[code];
+ else
+ {
+ code = ReadByte();
+ opCode = s_TwoByteOpCodes[code];
+ }
+
+ //Console.WriteLine("opcode: " + opCode);
+
+ current = new ILOp();
+ //current.opType = opCode.OpCodeType;
+ current.opCode = opCode;
+ //current.opType = opCode.OperandType;
+
+ switch (opCode.OperandType)
+ {
+ case OperandType.InlineNone:
+ //ilg.Emit(opCode);
+ break;
+ case OperandType.ShortInlineBrTarget:
+ SByte shortDelta = ReadSByte();
+ //ilg.Emit(opCode, shortDelta);
+ break;
+ case OperandType.InlineBrTarget:
+ Int32 delta = ReadInt32();
+ //ilg.Emit(opCode, delta);
+ break;
+ case OperandType.ShortInlineI:
+ byte int8 = ReadByte();
+ //ilg.Emit(opCode, int8);
+ break;
+ case OperandType.InlineI:
+ Int32 int32 = ReadInt32();
+ //ilg.Emit(opCode, int32);
+ break;
+ case OperandType.InlineI8:
+ Int64 int64 = ReadInt64();
+ //ilg.Emit(opCode, int64);
+ break;
+ case OperandType.ShortInlineR:
+ Single float32 = ReadSingle();
+ //ilg.Emit(opCode, float32);
+ break;
+ case OperandType.InlineR:
+ Double float64 = ReadDouble();
+ //ilg.Emit(opCode, float64);
+ break;
+ case OperandType.ShortInlineVar:
+ Byte index8 = ReadByte();
+ //ilg.Emit(opCode, index8);
+ break;
+ case OperandType.InlineVar:
+ UInt16 index16 = ReadUInt16();
+ //ilg.Emit(opCode, index16);
+ break;
+ case OperandType.InlineString:
+ token = ReadInt32();
+ current.operandType = "String";
+ current.operand = m_enclosingMethod.Module.ResolveString(token);
+ //ilg.Emit(opCode, m_enclosingMethod.Module.ResolveString(token));
+ break;
+ case OperandType.InlineSig:
+ token = ReadInt32();
+ //ilg.Emit(opCode, m_enclosingMethod.Module.ResolveSignature(token));
+ throw new NotImplementedException();
+ break;
+ case OperandType.InlineField:
+ token = ReadInt32();
+ FieldInfo fi = m_enclosingMethod.Module.ResolveField(token);
+ current.operandType = "Reflection.FieldInfo";
+ current.operand = fi.DeclaringType.FullName + Type.Delimiter + fi.Name;
+ //ilg.Emit(opCode, m_enclosingMethod.Module.ResolveField(token));
+ break;
+ case OperandType.InlineType:
+ token = ReadInt32();
+ current.operandType = "Type";
+ Type t = m_enclosingMethod.Module.ResolveType(token);
+ current.operand = t.FullName;
+ //ilg.Emit(opCode, m_enclosingMethod.Module.ResolveType(token));
+ break;
+ case OperandType.InlineTok:
+ token = ReadInt32();
+ //ilg.Emit(opCode, token);
+ break;
+ case OperandType.InlineMethod:
+ token = ReadInt32();
+ MethodInfo mi = (MethodInfo)m_enclosingMethod.Module.ResolveMethod(token);
+ current.operandType = "Reflection.MethodInfo";
+ current.operand = mi.DeclaringType.FullName + Type.Delimiter + mi.Name;
+ //ilg.Emit(opCode, mi);
+ break;
+ case OperandType.InlineSwitch:
+
+ throw new NotImplementedException();
+
+ Int32 cases = ReadInt32();
+ Int32[] deltas = new Int32[cases];
+ for (Int32 i = 0; i < cases; i++) deltas[i] = ReadInt32();
+ break;
+
+ default:
+ throw new BadImageFormatException("unexpected OperandType " + opCode.OperandType);
+ }
+ }
+
+ Byte ReadByte()
+ {
+ current.operandType = "Byte";
+ Byte ret = (Byte)m_byteArray[m_position++];
+ current.operand = ret;
+ return ret;
+ }
+
+ SByte ReadSByte()
+ {
+ current.operandType = "SByte";
+ SByte ret = (SByte)ReadByte();
+ current.operand = ret;
+ return ret;
+ }
+
+ UInt16 ReadUInt16() {
+ current.operandType = "UInt16";
+ m_position += 2;
+ UInt16 ret = BitConverter.ToUInt16(m_byteArray, m_position - 2);
+ current.operand = ret;
+ return ret;
+ }
+
+ UInt32 ReadUInt32() {
+ current.operandType = "UInt32";
+ m_position += 4;
+ UInt32 ret = BitConverter.ToUInt32(m_byteArray, m_position - 4);
+ current.operand = ret;
+ return ret;
+ }
+
+ UInt64 ReadUInt64() {
+ current.operandType = "UInt64";
+ m_position += 8;
+ UInt64 ret = BitConverter.ToUInt64(m_byteArray, m_position - 8);
+ current.operand = ret;
+ return ret;
+ }
+
+ Int32 ReadInt32() {
+ current.operandType = "Int32";
+ m_position += 4;
+ Int32 ret = BitConverter.ToInt32(m_byteArray, m_position - 4);
+ current.operand = ret;
+ return ret;
+ }
+
+ Int64 ReadInt64() {
+ current.operandType = "Int64";
+ m_position += 8;
+ Int64 ret = BitConverter.ToInt64(m_byteArray, m_position - 8);
+ current.operand = ret;
+ return ret;
+ }
+
+ Single ReadSingle() {
+ current.operandType = "UInt16";
+ m_position += 4;
+ Single ret = BitConverter.ToSingle(m_byteArray, m_position - 4);
+ current.operand = ret;
+ return ret;
+ }
+
+ Double ReadDouble() {
+ current.operandType = "Double";
+ m_position += 8;
+ Double ret = BitConverter.ToDouble(m_byteArray, m_position - 8);
+ current.operand = ret;
+ return ret;
+ }
+ }
+
+#if RENTAL_STUFF_FROM_DAEMON
+
+ /*
+ public string MyMeth (uint val1, string val2)
+ {
+ Console.WriteLine ("MyMeth " + val1 + " " + val2);
+ return "WEE!";
+ }
+ */
+
+ /*
+ public struct MethData
+ {
+ public int A;
+ public int B;
+ public int C;
+ }
+ */
+
+ public class MethDataBase
+ {
+ public int A;
+ }
+
+ public class MethData : MethDataBase
+ {
+ public int B;
+ public int C;
+ //public MethData[] Children;
+ public long[] Children;
+ }
+
+ public void MyMeth0 ()
+ {
+ }
+
+ public string MyMeth (MethData d, int[] ary, IDictionary<int, string> dict)
+ {
+ Console.WriteLine ("MyMeth struct " + d.A + " " + d.B + " " + d.C);
+ foreach (int i in ary)
+ Console.WriteLine (i);
+ Console.WriteLine ("Children: " + d.Children.Length);
+ Console.WriteLine ("Dict entries: " + dict.Count);
+ Console.WriteLine ("321: " + dict[321]);
+ return "WEE!";
+ }
+
+ // From HandleMessage():
+ //if (msg.Signature == new Signature ("u"))
+ if (false) {
+ System.Reflection.MethodInfo target = typeof (ServerBus).GetMethod ("MyMeth");
+ //System.Reflection.MethodInfo target = typeof (ServerBus).GetMethod ("MyMeth0");
+ Signature inSig, outSig;
+ TypeImplementer.SigsForMethod (target, out inSig, out outSig);
+ Console.WriteLine ("inSig: " + inSig);
+
+ if (msg.Signature == inSig) {
+ MethodCaller caller = TypeImplementer.GenCaller (target, this);
+ //caller (new MessageReader (msg), msg);
+
+ MessageWriter retWriter = new MessageWriter ();
+ caller (new MessageReader (msg), msg, retWriter);
+
+ if (msg.ReplyExpected) {
+ MethodReturn method_return = new MethodReturn (msg.Header.Serial);
+ Message replyMsg = method_return.message;
+ replyMsg.Body = retWriter.ToArray ();
+ Console.WriteLine ("replyMsg body: " + replyMsg.Body.Length);
+ /*
+ try {
+ replyMsg.Header[FieldCode.Destination] = msg.Header[FieldCode.Sender];
+ replyMsg.Header[FieldCode.Sender] = Caller.UniqueName;
+ } catch (Exception e) {
+ Console.Error.WriteLine (e);
+ }
+ */
+ replyMsg.Header[FieldCode.Destination] = Caller.UniqueName;
+ replyMsg.Header[FieldCode.Sender] = "org.freedesktop.DBus";
+ replyMsg.Signature = outSig;
+ {
+ Caller.Send (replyMsg);
+
+ /*
+ replyMsg.Header.Serial = Caller.GenerateSerial ();
+ MessageDumper.WriteMessage (replyMsg, Console.Out);
+ Caller.SendReal (replyMsg);
+ */
+ return;
+ }
+ }
+ }
+ }
+#endif
+}
diff --git a/src/Unix.cs b/src/Unix.cs
new file mode 100644
index 0000000..5cd6879
--- /dev/null
+++ b/src/Unix.cs
@@ -0,0 +1,484 @@
+// Copyright 2008 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace DBus.Unix
+{
+ // size_t
+ using SizeT = System.UIntPtr;
+ // ssize_t
+ using SSizeT = System.IntPtr;
+ // socklen_t: assumed to be 4 bytes
+ // uid_t: assumed to be 4 bytes
+
+ sealed class UnixStream : Stream //, IDisposable
+ {
+ public readonly UnixSocket usock;
+
+ public UnixStream (int fd)
+ {
+ this.usock = new UnixSocket (fd);
+ }
+
+ public UnixStream (UnixSocket usock)
+ {
+ this.usock = usock;
+ }
+
+ public override bool CanRead
+ {
+ get {
+ return true;
+ }
+ }
+
+ public override bool CanSeek
+ {
+ get {
+ return false;
+ }
+ }
+
+ public override bool CanWrite
+ {
+ get {
+ return true;
+ }
+ }
+
+ public override long Length
+ {
+ get {
+ throw new NotImplementedException ("Seeking is not implemented");
+ }
+ }
+
+ public override long Position
+ {
+ get {
+ throw new NotImplementedException ("Seeking is not implemented");
+ } set {
+ throw new NotImplementedException ("Seeking is not implemented");
+ }
+ }
+
+ public override long Seek (long offset, SeekOrigin origin)
+ {
+ throw new NotImplementedException ("Seeking is not implemented");
+ }
+
+ public override void SetLength (long value)
+ {
+ throw new NotImplementedException ("Not implemented");
+ }
+
+ public override void Flush ()
+ {
+ }
+
+ public override int Read ([In, Out] byte[] buffer, int offset, int count)
+ {
+ return usock.Read (buffer, offset, count);
+ }
+
+ public override void Write (byte[] buffer, int offset, int count)
+ {
+ usock.Write (buffer, offset, count);
+ }
+
+ unsafe public override int ReadByte ()
+ {
+ byte value;
+ usock.Read (&value, 1);
+ return value;
+ }
+
+ unsafe public override void WriteByte (byte value)
+ {
+ usock.Write (&value, 1);
+ }
+ }
+
+ static class UnixUid
+ {
+ internal const string LIBC = "libc";
+
+ [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=false)]
+ static extern uint getuid ();
+
+ [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=false)]
+ static extern uint geteuid ();
+
+ public static long GetUID ()
+ {
+ long uid = getuid ();
+ return uid;
+ }
+
+ public static long GetEUID ()
+ {
+ long euid = geteuid ();
+ return euid;
+ }
+ }
+
+ static class UnixError
+ {
+ internal const string LIBC = "libc";
+
+ [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=false)]
+ static extern IntPtr strerror (int errnum);
+
+ static string GetErrorString (int errnum)
+ {
+ IntPtr strPtr = strerror (errnum);
+
+ if (strPtr == IntPtr.Zero)
+ return "Unknown Unix error";
+
+ return Marshal.PtrToStringAnsi (strPtr);
+ }
+
+ // FIXME: Don't hard-code this.
+ const int EINTR = 4;
+
+ public static bool ShouldRetry
+ {
+ get {
+ int errno = System.Runtime.InteropServices.Marshal.GetLastWin32Error ();
+ return errno == EINTR;
+ }
+ }
+
+ public static Exception GetLastUnixException ()
+ {
+ int errno = System.Runtime.InteropServices.Marshal.GetLastWin32Error ();
+ return new Exception (String.Format ("Error {0}: {1}", errno, GetErrorString (errno)));
+ }
+ }
+
+ //[StructLayout(LayoutKind.Sequential, Pack=1)]
+ unsafe struct IOVector
+ {
+ public IOVector (IntPtr bbase, int length)
+ {
+ this.Base = (void*)bbase;
+ this.length = (SizeT)length;
+ }
+
+ //public IntPtr Base;
+ public void* Base;
+
+ public SizeT length;
+ public int Length
+ {
+ get {
+ return (int)length;
+ } set {
+ length = (SizeT)value;
+ }
+ }
+ }
+
+ /*
+ unsafe class SockAddr
+ {
+ byte[] data;
+ }
+ */
+
+ unsafe class UnixSocket
+ {
+ internal const string LIBC = "libc";
+
+ // Solaris provides socket functionality in libsocket rather than libc.
+ // We use a dllmap in the .config to deal with this.
+ internal const string LIBSOCKET = "libsocket";
+
+ public const short AF_UNIX = 1;
+ // FIXME: SOCK_STREAM is 2 on Solaris
+ public const short SOCK_STREAM = 1;
+
+ [DllImport (LIBC, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+ internal static extern IntPtr fork ();
+
+ [DllImport (LIBC, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+ internal static extern int dup2 (int fd, int fd2);
+
+ [DllImport (LIBC, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+ internal static extern int open ([MarshalAs(UnmanagedType.LPStr)] string path, int oflag);
+
+ [DllImport (LIBC, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+ internal static extern IntPtr setsid ();
+
+
+ [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ internal static extern int close (int fd);
+
+ [DllImport (LIBSOCKET, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ protected static extern int socket (int domain, int type, int protocol);
+
+ [DllImport (LIBSOCKET, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ protected static extern int connect (int sockfd, byte[] serv_addr, uint addrlen);
+
+ [DllImport (LIBSOCKET, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ protected static extern int bind (int sockfd, byte[] my_addr, uint addrlen);
+
+ [DllImport (LIBSOCKET, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ protected static extern int listen (int sockfd, int backlog);
+
+ //TODO: this prototype is probably wrong, fix it
+ [DllImport (LIBSOCKET, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ protected static extern int accept (int sockfd, void* addr, ref uint addrlen);
+
+ //TODO: confirm and make use of these functions
+ [DllImport (LIBSOCKET, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ protected static extern int getsockopt (int s, int optname, IntPtr optval, ref uint optlen);
+
+ [DllImport (LIBSOCKET, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ protected static extern int setsockopt (int s, int optname, IntPtr optval, uint optlen);
+
+ [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ unsafe static extern SSizeT read (int fd, byte* buf, SizeT count);
+
+ [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ unsafe static extern SSizeT write (int fd, byte* buf, SizeT count);
+
+ [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ unsafe static extern SSizeT readv (int fd, IOVector* iov, int iovcnt);
+
+ [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ unsafe static extern SSizeT writev (int fd, IOVector* iov, int iovcnt);
+
+ // Linux
+ //[DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ //static extern int vmsplice (int fd, IOVector* iov, uint nr_segs, uint flags);
+
+ [DllImport (LIBSOCKET, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ public static extern SSizeT recvmsg (int s, void* msg, int flags);
+
+ [DllImport (LIBSOCKET, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+ public static extern SSizeT sendmsg (int s, void* msg, int flags);
+
+ public int Handle;
+ bool ownsHandle = false;
+
+ public UnixSocket (int handle) : this (handle, false)
+ {
+ }
+
+ public UnixSocket (int handle, bool ownsHandle)
+ {
+ this.Handle = handle;
+ this.ownsHandle = ownsHandle;
+ // TODO: SafeHandle?
+ }
+
+ public UnixSocket ()
+ {
+ //TODO: don't hard-code PF_UNIX and SOCK_STREAM or SocketType.Stream
+ //AddressFamily family, SocketType type, ProtocolType proto
+
+ int r = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ Handle = r;
+ ownsHandle = true;
+ }
+
+ ~UnixSocket ()
+ {
+ if (ownsHandle && Handle > 0)
+ Close ();
+ }
+
+ protected bool connected = false;
+
+ //TODO: consider memory management
+ public void Close ()
+ {
+ int r = 0;
+
+ do {
+ r = close (Handle);
+ } while (r < 0 && UnixError.ShouldRetry);
+
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ Handle = -1;
+ connected = false;
+ }
+
+ //TODO: consider memory management
+ public void Connect (byte[] remote_end)
+ {
+ int r = 0;
+
+ do {
+ r = connect (Handle, remote_end, (uint)remote_end.Length);
+ } while (r < 0 && UnixError.ShouldRetry);
+
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ connected = true;
+ }
+
+ //assigns a name to the socket
+ public void Bind (byte[] local_end)
+ {
+ int r = bind (Handle, local_end, (uint)local_end.Length);
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+ }
+
+ public void Listen (int backlog)
+ {
+ int r = listen (Handle, backlog);
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+ }
+
+ public UnixSocket Accept ()
+ {
+ byte[] addr = new byte[110];
+ uint addrlen = (uint)addr.Length;
+
+ fixed (byte* addrP = addr) {
+ int r = 0;
+
+ do {
+ r = accept (Handle, addrP, ref addrlen);
+ } while (r < 0 && UnixError.ShouldRetry);
+
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ //TODO: use the returned addr
+ //string str = Encoding.Default.GetString (addr, 0, (int)addrlen);
+ return new UnixSocket (r, true);
+ }
+ }
+
+ unsafe public int Read (byte[] buf, int offset, int count)
+ {
+ fixed (byte* bufP = buf)
+ return Read (bufP + offset, count);
+ }
+
+ public int Write (byte[] buf, int offset, int count)
+ {
+ fixed (byte* bufP = buf)
+ return Write (bufP + offset, count);
+ }
+
+ unsafe public int Read (byte* bufP, int count)
+ {
+ int r = 0;
+
+ do {
+ r = (int)read (Handle, bufP, (SizeT)count);
+ } while (r < 0 && UnixError.ShouldRetry);
+
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ return r;
+ }
+
+ public int Write (byte* bufP, int count)
+ {
+ int r = 0;
+
+ do {
+ r = (int)write (Handle, bufP, (SizeT)count);
+ } while (r < 0 && UnixError.ShouldRetry);
+
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ return r;
+ }
+
+ public int RecvMsg (void* bufP, int flags)
+ {
+ int r = 0;
+
+ do {
+ r = (int)recvmsg (Handle, bufP, flags);
+ } while (r < 0 && UnixError.ShouldRetry);
+
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ return r;
+ }
+
+ public int SendMsg (void* bufP, int flags)
+ {
+ int r = 0;
+
+ do {
+ r = (int)sendmsg (Handle, bufP, flags);
+ } while (r < 0 && UnixError.ShouldRetry);
+
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ return r;
+ }
+
+ public int ReadV (IOVector* iov, int count)
+ {
+ //FIXME: Handle EINTR here or elsewhere
+ //FIXME: handle r != count
+ //TODO: check offset correctness
+
+ int r = (int)readv (Handle, iov, count);
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ return r;
+ }
+
+ public int WriteV (IOVector* iov, int count)
+ {
+ //FIXME: Handle EINTR here or elsewhere
+ //FIXME: handle r != count
+ //TODO: check offset correctness
+
+ int r = (int)writev (Handle, iov, count);
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ return r;
+ }
+
+ public int Write (IOVector[] iov, int offset, int count)
+ {
+ //FIXME: Handle EINTR here or elsewhere
+ //FIXME: handle r != count
+ //TODO: check offset correctness
+
+ fixed (IOVector* bufP = &iov[offset]) {
+ int r = (int)writev (Handle, bufP + offset, count);
+ if (r < 0)
+ throw UnixError.GetLastUnixException ();
+
+ return r;
+ }
+ }
+
+ public int Write (IOVector[] iov)
+ {
+ return Write (iov, 0, iov.Length);
+ }
+
+ }
+}
diff --git a/src/UnixNativeTransport.cs b/src/UnixNativeTransport.cs
new file mode 100644
index 0000000..14eca60
--- /dev/null
+++ b/src/UnixNativeTransport.cs
@@ -0,0 +1,180 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+//We send BSD-style credentials on all platforms
+//Doesn't seem to break Linux (but is redundant there)
+//This may turn out to be a bad idea
+#define HAVE_CMSGCRED
+
+using System;
+using System.IO;
+using System.Text;
+using System.Runtime.InteropServices;
+using DBus.Unix;
+
+namespace DBus.Transports
+{
+ class UnixNativeTransport : UnixTransport
+ {
+ internal UnixSocket socket;
+
+ public override string AuthString ()
+ {
+ long uid = UnixUid.GetEUID ();
+ return uid.ToString ();
+ }
+
+ public override void Open (string path, bool @abstract)
+ {
+ if (String.IsNullOrEmpty (path))
+ throw new ArgumentException ("path");
+
+ if (@abstract)
+ socket = OpenAbstractUnix (path);
+ else
+ socket = OpenUnix (path);
+
+ //socket.Blocking = true;
+ SocketHandle = (long)socket.Handle;
+ //Stream = new UnixStream ((int)socket.Handle);
+ Stream = new UnixStream (socket);
+ }
+
+ //send peer credentials null byte
+ //different platforms do this in different ways
+#if HAVE_CMSGCRED
+ unsafe void WriteBsdCred ()
+ {
+ //null credentials byte
+ byte buf = 0;
+
+ IOVector iov = new IOVector ();
+ //iov.Base = (IntPtr)(&buf);
+ iov.Base = &buf;
+ iov.Length = 1;
+
+ msghdr msg = new msghdr ();
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ cmsg cm = new cmsg ();
+ msg.msg_control = (IntPtr)(&cm);
+ msg.msg_controllen = (uint)sizeof (cmsg);
+ cm.hdr.cmsg_len = (uint)sizeof (cmsg);
+ cm.hdr.cmsg_level = 0xffff; //SOL_SOCKET
+ cm.hdr.cmsg_type = 0x03; //SCM_CREDS
+
+ int written = socket.SendMsg (&msg, 0);
+ if (written != 1)
+ throw new Exception ("Failed to write credentials");
+ }
+#endif
+
+ public override void WriteCred ()
+ {
+#if HAVE_CMSGCRED
+ try {
+ WriteBsdCred ();
+ return;
+ } catch {
+ if (Protocol.Verbose)
+ Console.Error.WriteLine ("Warning: WriteBsdCred() failed; falling back to ordinary WriteCred()");
+ }
+#endif
+ //null credentials byte
+ byte buf = 0;
+ Stream.WriteByte (buf);
+ }
+
+ public static byte[] GetSockAddr (string path)
+ {
+ byte[] p = Encoding.Default.GetBytes (path);
+
+ byte[] sa = new byte[2 + p.Length + 1];
+
+ //we use BitConverter to stay endian-safe
+ byte[] afData = BitConverter.GetBytes (UnixSocket.AF_UNIX);
+ sa[0] = afData[0];
+ sa[1] = afData[1];
+
+ for (int i = 0 ; i != p.Length ; i++)
+ sa[2 + i] = p[i];
+ sa[2 + p.Length] = 0; //null suffix for domain socket addresses, see unix(7)
+
+ return sa;
+ }
+
+ public static byte[] GetSockAddrAbstract (string path)
+ {
+ byte[] p = Encoding.Default.GetBytes (path);
+
+ byte[] sa = new byte[2 + 1 + p.Length];
+
+ //we use BitConverter to stay endian-safe
+ byte[] afData = BitConverter.GetBytes (UnixSocket.AF_UNIX);
+ sa[0] = afData[0];
+ sa[1] = afData[1];
+
+ sa[2] = 0; //null prefix for abstract domain socket addresses, see unix(7)
+ for (int i = 0 ; i != p.Length ; i++)
+ sa[3 + i] = p[i];
+
+ return sa;
+ }
+
+ internal UnixSocket OpenUnix (string path)
+ {
+ byte[] sa = GetSockAddr (path);
+ UnixSocket client = new UnixSocket ();
+ client.Connect (sa);
+ return client;
+ }
+
+ internal UnixSocket OpenAbstractUnix (string path)
+ {
+ byte[] sa = GetSockAddrAbstract (path);
+ UnixSocket client = new UnixSocket ();
+ client.Connect (sa);
+ return client;
+ }
+ }
+
+#if HAVE_CMSGCRED
+ unsafe struct msghdr
+ {
+ public IntPtr msg_name; //optional address
+ public uint msg_namelen; //size of address
+ public IOVector *msg_iov; //scatter/gather array
+ public int msg_iovlen; //# elements in msg_iov
+ public IntPtr msg_control; //ancillary data, see below
+ public uint msg_controllen; //ancillary data buffer len
+ public int msg_flags; //flags on received message
+ }
+
+ struct cmsghdr
+ {
+ public uint cmsg_len; //data byte count, including header
+ public int cmsg_level; //originating protocol
+ public int cmsg_type; //protocol-specific type
+ }
+
+ unsafe struct cmsgcred
+ {
+ const int CMGROUP_MAX = 16;
+
+ public int cmcred_pid; //PID of sending process
+ public uint cmcred_uid; //real UID of sending process
+ public uint cmcred_euid; //effective UID of sending process
+ public uint cmcred_gid; //real GID of sending process
+ public short cmcred_ngroups; //number or groups
+ public fixed uint cmcred_groups[CMGROUP_MAX]; //groups
+ }
+
+ struct cmsg
+ {
+ public cmsghdr hdr;
+ public cmsgcred cred;
+ }
+#endif
+}
diff --git a/src/UnixTransport.cs b/src/UnixTransport.cs
new file mode 100644
index 0000000..e433b6d
--- /dev/null
+++ b/src/UnixTransport.cs
@@ -0,0 +1,29 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.IO;
+
+namespace DBus.Transports
+{
+ abstract class UnixTransport : Transport
+ {
+ public override void Open (AddressEntry entry)
+ {
+ string path;
+ bool abstr;
+
+ if (entry.Properties.TryGetValue ("path", out path))
+ abstr = false;
+ else if (entry.Properties.TryGetValue ("abstract", out path))
+ abstr = true;
+ else
+ throw new Exception ("No path specified for UNIX transport");
+
+ Open (path, abstr);
+ }
+
+ public abstract void Open (string path, bool @abstract);
+ }
+}
diff --git a/src/Wrapper.cs b/src/Wrapper.cs
new file mode 100644
index 0000000..ff13102
--- /dev/null
+++ b/src/Wrapper.cs
@@ -0,0 +1,158 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace DBus
+{
+ //TODO: complete and use these wrapper classes
+ //not sure exactly what I'm thinking but there seems to be sense here
+
+ //FIXME: signature sending/receiving is currently ambiguous in this code
+ //FIXME: in fact, these classes are totally broken and end up doing no-op, do not use without understanding the problem
+ class MethodCall
+ {
+ public Message message = new Message ();
+
+ public MethodCall (ObjectPath path, string @interface, string member, string destination, Signature signature)
+ {
+ message.Header.MessageType = MessageType.MethodCall;
+ message.ReplyExpected = true;
+ message.Header[FieldCode.Path] = path;
+ message.Header[FieldCode.Interface] = @interface;
+ message.Header[FieldCode.Member] = member;
+ message.Header[FieldCode.Destination] = destination;
+ //TODO: consider setting Sender here for p2p situations
+ //this will allow us to remove the p2p hacks in MethodCall and Message
+#if PROTO_REPLY_SIGNATURE
+ //TODO
+#endif
+ message.Signature = signature;
+ }
+
+ public MethodCall (Message message)
+ {
+ this.message = message;
+ Path = (ObjectPath)message.Header[FieldCode.Path];
+ Interface = (string)message.Header[FieldCode.Interface];
+ Member = (string)message.Header[FieldCode.Member];
+ Destination = (string)message.Header[FieldCode.Destination];
+ //TODO: filled by the bus so reliable, but not the case for p2p
+ //so we make it optional here, but this needs some more thought
+ //if (message.Header.Fields.ContainsKey (FieldCode.Sender))
+ Sender = (string)message.Header[FieldCode.Sender];
+#if PROTO_REPLY_SIGNATURE
+ //TODO: note that an empty ReplySignature should really be treated differently to the field not existing!
+ if (message.Header.Fields.ContainsKey (FieldCode.ReplySignature))
+ ReplySignature = (Signature)message.Header[FieldCode.ReplySignature];
+ else
+ ReplySignature = Signature.Empty;
+#endif
+ Signature = message.Signature;
+ }
+
+ public ObjectPath Path;
+ public string Interface;
+ public string Member;
+ public string Destination;
+ public string Sender;
+#if PROTO_REPLY_SIGNATURE
+ public Signature ReplySignature;
+#endif
+ public Signature Signature;
+
+ public Error CreateError (string errorName, string errorMessage)
+ {
+ Error error = new Error (errorName, message.Header.Serial);
+ error.message.Signature = Signature.StringSig;
+
+ MessageWriter writer = new MessageWriter (message.Header.Endianness);
+ //writer.connection = conn;
+ writer.Write (errorMessage);
+ error.message.Body = writer.ToArray ();
+
+ //if (method_call.Sender != null)
+ // replyMsg.Header[FieldCode.Destination] = method_call.Sender;
+
+ return error;
+ }
+ }
+
+ class MethodReturn
+ {
+ public Message message = new Message ();
+
+ public MethodReturn (uint reply_serial)
+ {
+ message.Header.MessageType = MessageType.MethodReturn;
+ message.Header.Flags = HeaderFlag.NoReplyExpected | HeaderFlag.NoAutoStart;
+ message.Header[FieldCode.ReplySerial] = reply_serial;
+ //signature optional?
+ //message.Header[FieldCode.Signature] = signature;
+ }
+
+ public MethodReturn (Message message)
+ {
+ this.message = message;
+ ReplySerial = (uint)message.Header[FieldCode.ReplySerial];
+ }
+
+ public uint ReplySerial;
+ }
+
+ class Error
+ {
+ public Message message = new Message ();
+
+ public Error (string error_name, uint reply_serial)
+ {
+ message.Header.MessageType = MessageType.Error;
+ message.Header.Flags = HeaderFlag.NoReplyExpected | HeaderFlag.NoAutoStart;
+ message.Header[FieldCode.ErrorName] = error_name;
+ message.Header[FieldCode.ReplySerial] = reply_serial;
+ }
+
+ public Error (Message message)
+ {
+ this.message = message;
+ ErrorName = (string)message.Header[FieldCode.ErrorName];
+ ReplySerial = (uint)message.Header[FieldCode.ReplySerial];
+ //Signature = (Signature)message.Header[FieldCode.Signature];
+ }
+
+ public string ErrorName;
+ public uint ReplySerial;
+ //public Signature Signature;
+ }
+
+ class Signal
+ {
+ public Message message = new Message ();
+
+ public Signal (ObjectPath path, string @interface, string member)
+ {
+ message.Header.MessageType = MessageType.Signal;
+ message.Header.Flags = HeaderFlag.NoReplyExpected | HeaderFlag.NoAutoStart;
+ message.Header[FieldCode.Path] = path;
+ message.Header[FieldCode.Interface] = @interface;
+ message.Header[FieldCode.Member] = member;
+ }
+
+ public Signal (Message message)
+ {
+ this.message = message;
+ Path = (ObjectPath)message.Header[FieldCode.Path];
+ Interface = (string)message.Header[FieldCode.Interface];
+ Member = (string)message.Header[FieldCode.Member];
+ Sender = (string)message.Header[FieldCode.Sender];
+ }
+
+ public ObjectPath Path;
+ public string Interface;
+ public string Member;
+ public string Sender;
+ }
+}
diff --git a/src/dbus-sharp.dll.config b/src/dbus-sharp.dll.config
new file mode 100644
index 0000000..39995ef
--- /dev/null
+++ b/src/dbus-sharp.dll.config
@@ -0,0 +1,3 @@
+<configuration>
+ <dllmap dll="libsocket" os="!solaris" target="libc.so.6"/>
+</configuration>
diff --git a/tools/Introspect.cs b/tools/Introspect.cs
new file mode 100644
index 0000000..d1c6d68
--- /dev/null
+++ b/tools/Introspect.cs
@@ -0,0 +1,35 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using System.Xml.Serialization;
+using DBus;
+using Schemas;
+
+public class test
+{
+ public static void Main (string[] args)
+ {
+ string fname = args[0];
+ StreamReader sr = new StreamReader (fname);
+ XmlSerializer sz = new XmlSerializer (typeof (Node));
+ Node node = (Node)sz.Deserialize (sr);
+
+ Interface iface = node.Interfaces[1];
+
+ foreach (Method meth in iface.Methods) {
+ Console.Write (meth.Name);
+ Console.Write (" (");
+
+ if (meth.Arguments != null)
+ foreach (Argument arg in meth.Arguments)
+ Console.Write ("[" + arg.Direction + "] " + arg.Type + " " + arg.Name + ", ");
+ Console.Write (");");
+ Console.WriteLine ();
+ }
+ }
+}
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..b7610af
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,3 @@
+EXTRA_DIST = \
+ Introspect.cs \
+ Monitor.cs
diff --git a/tools/Makefile.in b/tools/Makefile.in
new file mode 100644
index 0000000..52b3490
--- /dev/null
+++ b/tools/Makefile.in
@@ -0,0 +1,311 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = tools
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+API_VERSION = @API_VERSION@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+GACUTIL = @GACUTIL@
+GMCS = @GMCS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MONO_CFLAGS = @MONO_CFLAGS@
+MONO_LIBS = @MONO_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+am__leading_dot = @am__leading_dot@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ Introspect.cs \
+ Monitor.cs
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tools/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tools/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tools/Monitor.cs b/tools/Monitor.cs
new file mode 100644
index 0000000..73bfb05
--- /dev/null
+++ b/tools/Monitor.cs
@@ -0,0 +1,239 @@
+// Copyright 2006 Alp Toker <alp at atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Text;
+using System.IO;
+using System.Collections.Generic;
+using DBus;
+using org.freedesktop.DBus;
+
+class BusMonitor
+{
+ static Connection bus = null;
+
+ public static int Main (string[] args)
+ {
+ bus = null;
+ bool readIn = false;
+ bool readOut = false;
+ List<string> rules = new List<string> ();
+
+ for (int i = 0 ; i != args.Length ; i++) {
+ string arg = args[i];
+
+ if (!arg.StartsWith ("--")) {
+ rules.Add (arg);
+ continue;
+ }
+
+ switch (arg)
+ {
+ case "--stdin":
+ readIn = true;
+ break;
+ case "--stdout":
+ readOut = true;
+ break;
+ case "--system":
+ bus = Bus.System;
+ break;
+ case "--session":
+ bus = Bus.Session;
+ break;
+ default:
+ Console.Error.WriteLine ("Usage: monitor.exe [--stdin|--stdout|--system|--session] [watch expressions]");
+ Console.Error.WriteLine (" If no watch expressions are provided, defaults will be used.");
+ return 1;
+ }
+ }
+
+ if (bus == null)
+ bus = Bus.Session;
+
+ if (rules.Count != 0) {
+ //install custom match rules only
+ foreach (string rule in rules)
+ bus.AddMatch (rule);
+ } else {
+ //no custom match rules, install the defaults
+ bus.AddMatch (MessageFilter.CreateMatchRule (MessageType.Signal));
+ bus.AddMatch (MessageFilter.CreateMatchRule (MessageType.MethodReturn));
+ bus.AddMatch (MessageFilter.CreateMatchRule (MessageType.Error));
+ bus.AddMatch (MessageFilter.CreateMatchRule (MessageType.MethodCall));
+ }
+
+ if (readIn) {
+ ReadIn ();
+ return 0;
+ }
+
+ if (readOut) {
+ ReadOut ();
+ return 0;
+ }
+
+ PrettyPrintOut ();
+ return 0;
+ }
+
+ static void ReadIn ()
+ {
+ TextReader r = Console.In;
+
+ while (true) {
+ Message msg = MessageDumper.ReadMessage (r);
+ if (msg == null)
+ break;
+ PrintMessage (msg);
+ Console.WriteLine ();
+
+ /*
+ byte[] header = MessageDumper.ReadBlock (r);
+ if (header == null)
+ break;
+ PrintHeader (header);
+
+ byte[] body = MessageDumper.ReadBlock (r);
+ PrintBody (header);
+ */
+ }
+ }
+
+ static void ReadOut ()
+ {
+ TextWriter w = Console.Out;
+
+ DumpConn (bus, w);
+
+ while (true) {
+ Message msg = bus.Transport.ReadMessage ();
+ if (msg == null)
+ break;
+ DumpMessage (msg, w);
+ }
+ }
+
+ static void PrettyPrintOut ()
+ {
+ while (true) {
+ Message msg = bus.Transport.ReadMessage ();
+ if (msg == null)
+ break;
+ PrintMessage (msg);
+ Console.WriteLine ();
+ }
+ }
+
+ static void DumpConn (Connection conn, TextWriter w)
+ {
+ w.WriteLine ("# This is a managed D-Bus protocol dump");
+ w.WriteLine ();
+ w.WriteLine ("# Machine: " + Connection.MachineId);
+ w.WriteLine ("# Connection: " + conn.Id);
+ w.WriteLine ("# Date: " + DateTime.Now.ToString ("F"));
+ w.WriteLine ();
+ }
+
+ static DateTime startTime = DateTime.Now;
+ static void DumpMessage (Message msg, TextWriter w)
+ {
+ w.WriteLine ("# Message: " + msg.Header.Serial);
+
+ TimeSpan delta = DateTime.Now - startTime;
+ startTime = DateTime.Now;
+ w.WriteLine ("# Time delta: " + delta.Ticks);
+
+ w.WriteLine ("# Header");
+ MessageDumper.WriteBlock (msg.GetHeaderData (), w);
+ w.WriteLine ("# Body");
+ MessageDumper.WriteBlock (msg.Body, w);
+
+ w.WriteLine ();
+ w.Flush ();
+ }
+
+ const string indent = " ";
+
+ static void PrintMessage (Message msg)
+ {
+ Console.WriteLine ("Message (" + msg.Header.Endianness + " endian, v" + msg.Header.MajorVersion + "):");
+ Console.WriteLine (indent + "Type: " + msg.Header.MessageType);
+ Console.WriteLine (indent + "Flags: " + msg.Header.Flags);
+ Console.WriteLine (indent + "Serial: " + msg.Header.Serial);
+
+ //foreach (HeaderField hf in msg.HeaderFields)
+ // Console.WriteLine (indent + hf.Code + ": " + hf.Value);
+ Console.WriteLine (indent + "Header Fields:");
+ foreach (KeyValuePair<byte,object> field in msg.Header.Fields)
+ Console.WriteLine (indent + indent + field.Key + ": " + field.Value);
+
+ Console.WriteLine (indent + "Body (" + msg.Header.Length + " bytes):");
+ if (msg.Body != null) {
+ MessageReader reader = new MessageReader (msg);
+
+ int argNum = 0;
+ foreach (Signature sig in msg.Signature.GetParts ()) {
+ //Console.Write (indent + indent + "arg" + argNum + " " + sig + ": ");
+ PrintValue (reader, sig, 1);
+ /*
+ if (sig.IsPrimitive) {
+ object arg = reader.ReadValue (sig[0]);
+ Console.WriteLine (arg);
+ } else {
+ if (sig.IsArray) {
+ //foreach (Signature elemSig in writer.StepInto (sig))
+ }
+ reader.StepOver (sig);
+ Console.WriteLine ("?");
+ }
+ */
+ argNum++;
+ }
+ }
+ }
+
+ static void PrintValue (MessageReader reader, Signature sig, int depth)
+ {
+ string indent = new String (' ', depth * 2);
+ indent += " ";
+
+ //Console.Write (indent + indent + "arg" + argNum + " " + sig + ": ");
+ Console.Write (indent);
+ if (sig == Signature.VariantSig) {
+ foreach (Signature elemSig in reader.StepInto (sig)) {
+ Console.WriteLine ("Variant '{0}' (", elemSig);
+ PrintValue (reader, elemSig, depth + 1);
+ Console.WriteLine (indent + ")");
+ }
+ } else if (sig.IsPrimitive) {
+ object arg = reader.ReadValue (sig[0]);
+ Type argType = sig.ToType ();
+ if (sig == Signature.StringSig || sig == Signature.ObjectPathSig)
+ Console.WriteLine ("{0} \"{1}\"", argType.Name, arg);
+ else if (sig == Signature.SignatureSig)
+ Console.WriteLine ("{0} '{1}'", argType.Name, arg);
+ else
+ Console.WriteLine ("{0} {1}", argType.Name, arg);
+ } else if (sig.IsArray) {
+ Console.WriteLine ("Array [");
+ foreach (Signature elemSig in reader.StepInto (sig))
+ PrintValue (reader, elemSig, depth + 1);
+ Console.WriteLine (indent + "]");
+ } else if (sig.IsDictEntry) {
+ Console.WriteLine ("DictEntry {");
+ foreach (Signature elemSig in reader.StepInto (sig))
+ PrintValue (reader, elemSig, depth + 1);
+ Console.WriteLine (indent + "}");
+ } else if (sig.IsStruct) {
+ Console.WriteLine ("Struct {");
+ foreach (Signature elemSig in reader.StepInto (sig))
+ PrintValue (reader, elemSig, depth + 1);
+ Console.WriteLine (indent + "}");
+ } else {
+ reader.StepOver (sig);
+ Console.WriteLine ("'{0}'?", sig);
+ }
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-cli-libs/packages/dbus-sharp-legacy.git
More information about the Pkg-cli-libs-commits
mailing list