diff -ruN ldmud-trunk/doc/efun/xml_generate ldmud-iksemel/doc/efun/xml_generate
--- ldmud-trunk/doc/efun/xml_generate	1970-01-01 01:00:00.000000000 +0100
+++ ldmud-iksemel/doc/efun/xml_generate	2008-05-06 20:02:16.000000000 +0200
@@ -0,0 +1,74 @@
+OPTIONAL
+SYNOPSIS
+        #include <xml.h>
+
+        string xml_generate(mixed *xml)
+
+DESCRIPTION
+        Converts the given <xml> array into an XML conform string, if 
+        possible. The <xml> argument array must have the following structure.
+
+        It must contain tag arrays of three elements, with the following 
+        indices:
+
+            string XML_TAG_NAME
+                The name of the XML tag.
+
+            mixed * XML_TAG_CONTENTS
+                The contents of this xml tag as array. This array may 
+                contain either strings, or arrags of sub-tags again with 
+                three elements (see example)
+
+                If the xml tag does not contain anything, the element is set
+                NULL.
+
+            mapping XML_TAG_ATTRIBUTES
+                All attributes given to the XML tag as mapping where the key
+                is the attribute name and the value is its string value. 
+
+                If the xml tag does not contain any attributes, this element
+                is set NULL:
+
+        In case the parameter does not follow these rules, errors are raised.
+        The method returns a valid XML string otherwise.
+
+        The function is available only if the driver is compiled with Iksemel
+        support.
+
+EXAMPLE
+        xml_generate(({ "abc", 0, 0 })) -> "<abc/>"
+        xml_generate(({ "abc", 0, ([ "xyz" : "cde" ]) })) -> "<abc xyz="cde"/>"
+
+        mixed* xml = ({ "book"
+                      , ({ ({ "title"
+                            , ({ "This is a title" })
+                            , 0
+                           })
+                         , ({ "chapter"
+                            , ({ "This is a chapter" })
+                            , 0
+                           })
+                         , ({ "chapter"
+                            , ({ "We want "
+                               , ({ "b"
+                                  , ({ "bold" })
+                                  , 0 
+                                 })
+                               , "here"
+                              })
+                            , 0
+                           })
+                        })
+                      , ([ "language" : "common" ])
+                     })
+
+        xml_generate(xml)
+            -> "<book language="common"><title>This is the title</title>"
+               "<chapter>This is a chapter</chapter><chapter>We want "
+               "<b>bold</b> here.</chapter></book>"
+
+HISTORY
+        Package created for LDMud 3.3.716
+
+SEE ALSO
+        xml_parse(E)
diff -ruN ldmud-trunk/doc/efun/xml_parse ldmud-iksemel/doc/efun/xml_parse
--- ldmud-trunk/doc/efun/xml_parse	1970-01-01 01:00:00.000000000 +0100
+++ ldmud-iksemel/doc/efun/xml_parse	2008-05-06 20:02:16.000000000 +0200
@@ -0,0 +1,78 @@
+OPTIONAL
+SYNOPSIS
+        #include <xml.h>
+
+        mixed* xml_parse(string xml)
+
+DESCRIPTION
+        Parses the given string <xml> as XML conform string. The string must
+        have only one root tag, subsequent root tags are ignored. The method
+        uses the iksemel library to parse the string.
+
+        If the xml string is correct, an array is of three elements is 
+        returned, where as the following indices are defined:
+
+            string XML_TAG_NAME
+                The name of the XML tag.
+
+            mixed * XML_TAG_CONTENTS
+                The contents of this xml tag as array. This array may 
+                contain either strings, or arrags of sub-tags again with 
+                three elements (see example)
+
+                If the xml tag does not contain anything, the element is set
+                NULL.
+
+            mapping XML_TAG_ATTRIBUTES
+                All attributes given to the XML tag as mapping where the key
+                is the attribute name and the value is its string value. 
+
+                If the xml tag does not contain any attributes, this element
+                is set NULL:
+
+        If the XML string is not well formed, or there is not enough memory to 
+        parse the whole XML structure into the array an error is raised. In case
+        the XML string can't be parsed, cause it is not valid XML, NULL is 
+        returned.
+
+        The function is available only if the driver is compiled with Iksemel
+        support.
+
+EXAMPLE
+        xml_parse("<abc/>")           -> ({ "abc", 0, 0 })
+        xml_parse("<abc xyz="cde"/>") -> ({ "abc", 0, ([ "xyz" : "cde" ]) })
+
+        xml_parse("<book language="common">" + 
+                  "    <title>This is the title</title>" + 
+                  "    <chapter>This is a chapter</chapter>" + 
+                  "    <chapter>We want <b>bold</b> here.</chapter>" +
+                  "</book>")
+
+            -> ({ "book"
+                , ({ ({ "title"
+                      , ({ "This is a title" })
+                      , 0
+                     })
+                   , ({ "chapter"
+                      , ({ "This is a chapter" })
+                      , 0
+                     })
+                   , ({ "chapter"
+                      , ({ "We want "
+                         , ({ "b"
+                            , ({ "bold" })
+                            , 0 
+                           })
+                         , "here"
+                        })
+                      , 0
+                     })
+                  })
+                , ([ "language" : "common" ])
+               })
+
+HISTORY
+        Package created for LDMud 3.3.716
+
+SEE ALSO
+        xml_generate(E)
diff -ruN ldmud-trunk/mudlib/sys/xml.h ldmud-iksemel/mudlib/sys/xml.h
--- ldmud-trunk/mudlib/sys/xml.h	1970-01-01 01:00:00.000000000 +0100
+++ ldmud-iksemel/mudlib/sys/xml.h	2008-05-06 20:01:49.000000000 +0200
@@ -0,0 +1,10 @@
+
+#ifndef XML_H__
+#define XML_H__ 1
+
+#define XML_TAG_NAME                    0 /* Name of the current tag */
+#define XML_TAG_CONTENTS                1 /* Contents of the curren tag */
+#define XML_TAG_ATTRIBUTES              2 /* Atttributes of the current tag */    
+
+#endif
+
diff -ruN ldmud-trunk/src/Makefile.in ldmud-iksemel/src/Makefile.in
--- ldmud-trunk/src/Makefile.in	2008-05-06 19:36:19.000000000 +0200
+++ ldmud-iksemel/src/Makefile.in	2008-05-06 19:41:02.000000000 +0200
@@ -91,7 +91,7 @@
       interpret.c \
       lex.c main.c mapping.c md5.c mempools.c mregex.c mstrings.c object.c \
       otable.c\
-      parser.c parse.c pkg-alists.c pkg-idna.c \
+      parser.c parse.c pkg-alists.c pgk-iksemel.c pkg-idna.c \
       pkg-mccp.c pkg-mysql.c pkg-pcre.c \
       pkg-pgsql.c pkg-sqlite.c pkg-tls.c \
       ptmalloc.c port.c ptrtable.c \
@@ -103,7 +103,7 @@
       interpret.o \
       lex.o main.o mapping.o md5.o mempools.o mregex.o mstrings.o object.o \
       otable.o \
-      parser.o parse.o pkg-alists.o pkg-idna.o \
+      parser.o parse.o pkg-alists.o pkg-iksemel.o pkg-idna.o \
       pkg-mccp.o pkg-mysql.o pkg-pcre.o \
       pkg-pgsql.o pkg-sqlite.o pkg-tls.o \
       ptmalloc.o port.o ptrtable.o \
diff -ruN ldmud-trunk/src/autoconf/acconfig.h ldmud-iksemel/src/autoconf/acconfig.h
--- ldmud-trunk/src/autoconf/acconfig.h	2008-05-06 19:36:10.000000000 +0200
+++ ldmud-iksemel/src/autoconf/acconfig.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,132 +0,0 @@
-#ifndef MACHINE_H
-#define MACHINE_H
-
-@TOP@
-
-/* Set in response to the signal handler return type, since not all
- * compilers understand direct definition comparisons
- */
-#undef RETSIGTYPE_VOID
-
-/* does the compiler provide inline functions? */
-#undef HAS_INLINE
-
-/* Is the library function inet_ntoa() compatible with the compiler?
- * TODO: Is there any platform where this is not the case?
- */
-#undef INET_NTOA_OK
-
-/* A mask that allows to extract an unsigned char from a signed */
-#define CHARBIT_MASK 0xff
-
-#undef RENAME_HANDLES_DIRECTORIES
-
-/* Does the system have a getrusage call?  */
-#undef HAVE_GETRUSAGE
-/* If so, is it restricted to user and system time? */
-#undef GETRUSAGE_RESTRICTED
-/* Is it available as a subfunction of syscall() ? */
-#undef GETRUSAGE_VIA_SYSCALL
-/* Can ru_utime / ru_stime be accessed as a timeval with tv_sec and tv_usec ? */
-#undef RUSAGE_USEC
-
-/* the atari strtol() used to consider characters '9' < c < 'A' to be numeric */
-#undef STRTOL_BROKEN
-
-/* does the libc consider it normal to free a null pointer? */
-#undef FREE_NULL_POINTER
-
-/* needs the first argument of strtol be declared as const ? */
-#undef STRTOL_CONST_CHARP
-
-/* Define if you have bcopy, and it handles overlapping ranges correctly. */
-#undef OVERLAPPING_BCOPY
-
-#define MALLOC_ALIGN 4
-
-/* does the sys/types.h define the uint*_t types? */
-#undef HAVE_INTTYPES
-
-/* does the compiler know of a 'ssize_t' type? */
-#undef HAVE_SSIZE_T
-
-/* does the compiler know of a 'long long' type? */
-#undef HAVE_LONG_LONG
-
-/* does the compiler know of a 'bool' type? */
-#undef HAVE_BOOL
-
-/* what kind of pointer is used by malloc() et al */
-#define POINTER *
-#undef FREE_RETURNS_VOID
-
-/* can we define our own malloc() safely? */
-#undef SBRK_OK
-
-/* The following is needed for smalloc without SBRK_OK to use memory
- * efficiently. smalloc will malloc blocks that are a large power of
- * two, minus EXTERN_MALLOC_OVERHEAD. If you have no idea what number to
- * choose, compile & run util/overhead.c
- */
-#define EXTERN_MALLOC_OVERHEAD 16
-
-/* How to set a socket non-blocking */
-#undef USE_IOCTL_FIONBIO
-#undef USE_FCNTL_O_NDELAY
-#undef USE_FCNTL_FNDELAY
-
-/* Can F_SETOWN be used on a socket? */
-#undef USE_FCNTL_SETOWN
-
-/* Can SO_OOBINLINE be used on a socket? */
-#undef USE_OOBINLINE
-
-/* Does the machine offer IPv6? */
-#undef HAS_IPV6
-
-/* Does the machine offer iconv? */
-#undef HAS_ICONV
-
-/* Does the machine's iconv take a non-const 'char**' as first arg? */
-#undef HAS_ICONV_NONCONST_IN
-
-/* Does the machine offer PCRE? */
-#undef HAS_PCRE
-
-/* Does the machine offer IDNA? */
-#undef HAS_IDN
-
-/* Does the machine offer mySQL? */
-#undef HAS_MYSQL
-
-/* Does the machine offer PostgreSQL? */
-#undef HAS_PGSQL
-
-/* Does the machine offer SQLite3? */
-#undef HAS_SQLITE3
-
-/* Does SQLite3 use pthreads? */
-#undef SQLITE3_USES_PTHREADS
-
-/* Does the machine offer GnuTLS? */
-#undef HAS_GNUTLS
-#undef HAS_GNUTLS_VERSION
-
-/* Does the machine offer OpenSSL/SSL? */
-#undef HAS_OPENSSL
-
-/* define the erq include file. */
-#undef ERQ_INCLUDE
-
-/* Does the machine offer pthreads? */
-#undef HAS_PTHREADS
-
-/* Does the machine offer pthread_atfork()? */
-#undef HAS_PTHREAD_ATFORK
-
-/* define the host-specific include file */
-#undef HOST_INCLUDE
-
-@BOTTOM@
-
-#endif
diff -ruN ldmud-trunk/src/autoconf/configure.in ldmud-iksemel/src/autoconf/configure.in
--- ldmud-trunk/src/autoconf/configure.in	2008-05-06 19:36:10.000000000 +0200
+++ ldmud-iksemel/src/autoconf/configure.in	2008-05-06 19:55:07.000000000 +0200
@@ -60,27 +60,27 @@
 
 AC_DEFUN([AC_FORM_HELP],[  --$1[]dnl
 ifelse([$2],,,dnl
-builtin(format,%[]builtin(eval,(len([$1])<32)*(32-len([$1])))s,)  [default=$2])[]dnl
+builtin(format,%[]builtin(eval,(len([$1])<50)*(50-len([$1])))s,)  [default=$2])[]dnl
 ifelse([$3],,,[
 ]patsubst([$3],[^],[        ]))[]dnl
 ])
 
 
-AC_DEFUN(AC_MY_ARG_ENABLE,
+AC_DEFUN([AC_MY_ARG_ENABLE],
 [DEFAULTenable_[]translit([$1],[-],[_])=ifelse($2,,no,[$2])
 AC_ARG_ENABLE([$1],AC_FORM_HELP([enable-$1]ifelse($3,,,[=($3)]),
 ifelse([$2],,[disabled],[$2],no,[disabled],[$2],yes,[enabled],[enabled($2)]),
 [$4]),[$5],[$6])
 ])
 
-AC_DEFUN(AC_MY_ARG_WITH,
+AC_DEFUN([AC_MY_ARG_WITH],
 [DEFAULTwith_[]translit([$1],[-],[_])=ifelse($2,,no,[$2])
 AC_ARG_WITH([$1],AC_FORM_HELP([with-$1]ifelse($3,,[=VALUE],[=$3]),
 [$2],
 [$4]),[$5],[$6])
 ])
 
-AC_DEFUN(AC_NOT_AVAILABLE,
+AC_DEFUN([AC_NOT_AVAILABLE],
 [if test "x$not_available" = "x"; then
     not_available="$1"
 else
@@ -123,10 +123,11 @@
 AC_MY_ARG_ENABLE(use-sqlite,no,,[Enables SQLite support])
 AC_MY_ARG_ENABLE(use-pthreads,no,,[enable using of threads for socket writes])
 AC_MY_ARG_ENABLE(use-pcre,yes,,[Enables PCRE: no/yes/builtin/no-builtin])
+AC_MY_ARG_ENABLE(use-iksemel,no,,[Enables use of iksemel for XML parsing])
 AC_MY_ARG_ENABLE(use-deprecated,yes,,[Enables obsolete and deprecated efuns])
 AC_MY_ARG_ENABLE(use-structs,yes,,[Enables structs])
 AC_MY_ARG_ENABLE(use-tls,no,,[Enables Transport Layer Security over Telnet: no/gnu/ssl/yes])
-AC_MY_ARG_WITH(tls-path,,[Optional location of the TLS include/ and lib/ directory])
+AC_MY_ARG_WITH(tls-path,,,[Optional location of the TLS include/ and lib/ directory])
 AC_MY_ARG_ENABLE(use-new-inlines,yes,,[Enables new inline syntax])
 AC_MY_ARG_ENABLE(use-set-light,yes,,[Enables efun set_light()])
 AC_MY_ARG_ENABLE(use-set-is-wizard,yes,,[Enables efun set_is_wizard()])
@@ -212,7 +213,7 @@
 AC_MY_ARG_WITH(max-byte-transfer,50000,,)
 AC_MY_ARG_WITH(catch-udp-port,4246,,)
 AC_MY_ARG_WITH(set-buffer-size-max,65536,,)
-AC_MY_ARG_WITH(malloc,default,[default/smalloc/slaballoc/sysmalloc/ptmalloc],[memory manager to use])
+AC_MY_ARG_WITH(malloc,default,,[default/smalloc/slaballoc/sysmalloc/ptmalloc],[memory manager to use])
 AC_MY_ARG_WITH(min-malloced,0,,)
 AC_MY_ARG_WITH(min-small-malloced,0,,)
 AC_MY_ARG_WITH(max-malloced,0x4000000,,)
@@ -246,7 +247,7 @@
 if test "x$enable_erq" = "xerq" || test "x$enable_erq" = "xyes"; then
   cdef_erq_demon="#define"
   erq_sub=erq
-  AC_DEFINE(ERQ_INCLUDE,"util/erq/erq.h")
+  AC_DEFINE(ERQ_INCLUDE,"util/erq/erq.h",[define the erq include file.])
 elif test "x$enable_erq" = "xxerq"; then
   cdef_erq_demon="#define"
   erq_sub=xerq
@@ -320,6 +321,20 @@
   enable_use_sqlite="yes"
 fi
 
+AC_UPDATE_VAR(enable_use_iksemel)
+if test "x$enable_use_iksemel" = "x" || test "x$enable_use_iksemel" = "xyes"; then
+  cdef_use_iksemel="#define"
+  iksemel_path=
+  enable_use_iksemel="yes"
+elif test "x$enable_use_iksemel" = "xno"; then
+  cdef_use_iksemel="#undef"
+  iksemel_path=
+else
+  cdef_use_iksemel="#define"
+  iksemel_path="$enable_use_iksemel"
+  enable_use_iksemel="yes"
+fi
+
 AC_UPDATE_VAR(enable_use_tls)
 if test "x$enable_use_tls" = "x" || test "x$enable_use_tls" = "xyes"; then
   cdef_use_tls="#define"
@@ -585,7 +600,7 @@
 ],,
 lp_cv_sys_malloc_align=8,
 lp_cv_sys_malloc_align=4))
-AC_DEFINE_UNQUOTED(MALLOC_ALIGN,$lp_cv_sys_malloc_align)
+AC_DEFINE_UNQUOTED(MALLOC_ALIGN,$lp_cv_sys_malloc_align,[word alignment])
 
 AC_CACHE_CHECK(for uint32_t and friends,lp_cv_inttypes,
 AC_TRY_COMPILE([#include <sys/types.h>
@@ -593,7 +608,7 @@
 lp_cv_inttypes=yes,
 lp_cv_inttypes=no))
 if test $lp_cv_inttypes = yes; then
-  AC_DEFINE(HAVE_INTTYPES)
+  AC_DEFINE(HAVE_INTTYPES, 1, [does the sys/types.h define the uint*_t types?])
 fi
 
 AC_CACHE_CHECK(for ssize_t,lp_cv_type_ssize_t,
@@ -602,12 +617,12 @@
 lp_cv_type_ssize_t=yes,
 lp_cv_type_ssize_t=no))
 if test $lp_cv_type_ssize_t = yes; then
-  AC_DEFINE(HAVE_SSIZE_T)
+  AC_DEFINE(HAVE_SSIZE_T, 1, [does the compiler know of a 'ssize_t' type?])
 fi
 
 AC_CHECK_SIZEOF(long long) dnl Also checks for the existance
 if test $ac_cv_type_long_long = yes; then
-  AC_DEFINE(HAVE_LONG_LONG)
+  AC_DEFINE(HAVE_LONG_LONG, 1, [does the compiler know of a 'long long' type?])
 fi
 
 AC_CACHE_CHECK(for bool,lp_cv_type_bool,
@@ -615,12 +630,12 @@
 lp_cv_type_bool=yes,
 lp_cv_type_bool=no))
 if test $lp_cv_type_bool = yes; then
-  AC_DEFINE(HAVE_BOOL)
+  AC_DEFINE(HAVE_BOOL, 1, [does the compiler know of a 'bool' type?])
 fi
 
 AC_C_INLINE
 if test "x$ac_cv_c_inline" != "xno"; then
-  AC_DEFINE(HAS_INLINE)
+  AC_DEFINE(HAS_INLINE, 1, [Does the compiler provide inline functions?])
 fi
 
 AC_TYPE_SIZE_T
@@ -628,9 +643,10 @@
 AC_TYPE_SIGNAL
 
 if test "x$ac_cv_type_signal" = "xvoid"; then
-  cat >> confdefs.h <<EOF
-#define RETSIGTYPE_VOID 1
-EOF
+  AC_DEFINE(RETSIGTYPE_VOID, 1, 
+    [Set in response to the signal handler return type, since not all
+     compilers understand direct definition comparisons.
+    ])
 fi
 
 # --- Check for common system libraries ---
@@ -742,7 +758,8 @@
 lp_cv_func_inet_ntoa_ok=yes
 )))
 if test $lp_cv_func_inet_ntoa_ok = yes ; then
-  AC_DEFINE(INET_NTOA_OK)
+dnl TODO: Is there any platform where this is not the case?
+  AC_DEFINE(INET_NTOA_OK, 1, [Is the library function inet_ntoa() compatible with the compiler?])
 fi
 
 # --- IPV6 ---
@@ -765,7 +782,7 @@
     CFLAGS="$saveflags"
 ))
 if test $lp_cv_has_ipv6 = yes; then
-    AC_DEFINE(HAS_IPV6)
+    AC_DEFINE(HAS_IPV6, 1, [Does the machine offer IPv6?])
     if test $enable_use_ipv6 = yes; then
         AC_CACHE_CHECK(if -linet6 is needed, lp_cv_need_lib_inet6,
             AC_TRY_RUN([
@@ -836,7 +853,7 @@
     if test $lp_cv_has_openssl = yes; then
         has_tls=yes
         tls_package=ssl
-        AC_DEFINE(HAS_OPENSSL)
+        AC_DEFINE(HAS_OPENSSL, 1, [Does the machine offer OpenSSL/SSL?])
 
         if test "$enable_use_tls" = "yes"; then
             AC_CACHE_CHECK(if -lssl or similar is needed, lp_cv_need_lib_ssl,
@@ -908,7 +925,7 @@
     if test $lp_cv_has_gnutls = yes; then
         has_tls=yes
         tls_package=gnu
-        AC_DEFINE(HAS_GNUTLS)
+        AC_DEFINE(HAS_GNUTLS, 1, [Does the machine offer GnuTLS?])
 
         if test "$enable_use_tls" = "yes"; then
             AC_CACHE_CHECK(if -lgnutls or similar is needed, lp_cv_need_lib_gnutls,
@@ -953,7 +970,7 @@
                 lp_cv_has_gnutls_version=7
             ))
             LIBS="$savelibs"
-            AC_DEFINE_UNQUOTED(HAS_GNUTLS_VERSION, $lp_cv_has_gnutls_version)
+            AC_DEFINE_UNQUOTED(HAS_GNUTLS_VERSION, $lp_cv_has_gnutls_version, [version of GNUTLS library])
         fi
 
     else
@@ -1000,7 +1017,7 @@
     saveflags="$CFLAGS"
     savelibs="$LIBS"
 
-    AC_DEFINE(HAS_PTHREADS)
+    AC_DEFINE(HAS_PTHREADS, 1, [Does the machine offer pthreads?])
 
     AC_CACHE_CHECK(if -lpthread or similar is needed, lp_cv_need_lib_pthread,
         AC_TRY_RUN([
@@ -1047,7 +1064,7 @@
         )
     )
     if test $lp_cv_has_pthread_atfork = yes; then
-        AC_DEFINE(HAS_PTHREAD_ATFORK)
+        AC_DEFINE(HAS_PTHREAD_ATFORK, 1, [Does the machine offer pthread_atfork()?])
     fi
 
     CFLAGS="$saveflags"
@@ -1092,7 +1109,7 @@
     CFLAGS="$saveflags"
 
     if test $lp_cv_has_pcre = yes; then
-        AC_DEFINE(HAS_PCRE)
+        AC_DEFINE(HAS_PCRE, 1, [Does the machine offer PCRE?])
         PKGLIBS="$PKGLIBS -lpcre"
     else
         if test $enable_use_builtin_pcre = no ; then
@@ -1227,11 +1244,11 @@
 fi
 
 if test "x$lp_cv_has_iconv" = "xyes"; then
-  AC_DEFINE(HAS_ICONV)
+  AC_DEFINE(HAS_ICONV, 1, [Does the machine offer iconv?])
 fi
 
 if test "x$lp_cv_has_iconv_nonconst_in" = "xyes"; then
-  AC_DEFINE(HAS_ICONV_NONCONST_IN)
+  AC_DEFINE(HAS_ICONV_NONCONST_IN, 1, [Does the machine's iconv take a non-const 'char**' as first arg?])
 fi
 
 # --- libidn ---
@@ -1283,7 +1300,7 @@
 # The system has the include files - now search for the libraries.
 if test $lp_cv_has_mysql = yes; then
   saveflags="$CFLAGS"
-  AC_DEFINE(HAS_MYSQL)
+  AC_DEFINE(HAS_MYSQL, 1, [Does the machine offer mySQL?])
 
   if test $enable_use_mysql = yes; then
     tmp=""
@@ -1431,7 +1448,7 @@
 # The system has the include files - now search for the libraries.
 if test $lp_cv_has_pgsql = yes; then
   saveflags="$CFLAGS"
-  AC_DEFINE(HAS_PGSQL)
+  AC_DEFINE(HAS_PGSQL, 1, [Does the machine offer PostgreSQL?])
 
   if test $enable_use_pgsql = yes; then
     tmp=""
@@ -1564,7 +1581,7 @@
 # The system has the include files - now search for the libraries.
 if test $lp_cv_has_sqlite3 = yes; then
   saveflags="$CFLAGS"
-  AC_DEFINE(HAS_SQLITE3)
+  AC_DEFINE(HAS_SQLITE3, 1, [Does the machine offer SQLite3?])
 
   if test $enable_use_sqlite = yes; then
     tmp=""
@@ -1588,7 +1605,7 @@
     if test "x$tmp" == "x"; then
         unset ac_cv_lib_sqlite3_main
         if test -d "/usr/local/lib"; then
-            CFLAGS="$saveflags -L/usr/local/pgsql/lib"
+            CFLAGS="$saveflags -L/usr/local/lib"
             AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L/usr/local/lib -lsqlite3")
         fi
     fi
@@ -1617,7 +1634,7 @@
       )
 
       if test $lp_cv_sqlite3_uses_pthreads = yes ; then
-           AC_DEFINE(SQLITE3_USES_PTHREADS)
+           AC_DEFINE(SQLITE3_USES_PTHREADS, 1, [Does SQLite3 use pthreads?])
       fi
 
       LIBS="$savelibs"
@@ -1632,6 +1649,88 @@
   fi
 fi
 
+# --- Iksemel ---
+
+AC_CACHE_CHECK(for Iksemel,lp_cv_has_iksemel,
+for TESTPATH in "" "$iksemel_path" "$iksemel_path/include" "/usr/local/include" ; do
+    saveflags="$CFLAGS"
+    if test "x$TESTPATH" != "x"; then
+        CFLAGS="$saveflags -I$TESTPATH"
+    fi
+AC_TRY_COMPILE([
+#include <iksemel.h>
+
+iks * foo(void)
+{
+
+    return (iks*)0;
+}
+],,
+lp_cv_has_iksemel=yes
+if test "x$TESTPATH" != "x"; then
+    EXTRA_CFLAGS="-I$TESTPATH $EXTRA_CFLAGS"
+fi
+break;
+,
+lp_cv_has_iksemel=no
+CFLAGS="$saveflags"
+)
+done
+)
+
+# The system has the include files - now search for the libraries.
+if test $lp_cv_has_iksemel = yes; then
+  saveflags="$CFLAGS"
+  AC_DEFINE(HAS_IKSEMEL, 1, [Does the machine offer iksemel?])
+
+  if test $enable_use_iksemel = yes; then
+    tmp=""
+
+    AC_CHECK_LIB(iksemel,main, tmp="$PKGLIBS -liksemel")
+
+    if test "x$iksemel_path" == "x"; then
+        unset ac_cv_lib_iksemel_main
+        if test -d "${iksemel_path}/lib/iksemel"; then
+            CFLAGS="$saveflags -L${iksemel_path}/lib/iksemel"
+            AC_CHECK_LIB(iksemel,main, tmp="$PKGLIBS -L${iksemel_path}/lib/iksemel -liksemel")
+        elif test -d "${iksemel_path}/lib"; then
+            CFLAGS="$saveflags -L${iksemel_path}/lib"
+            AC_CHECK_LIB(iksemel,main, tmp="$PKGLIBS -L${iksemel_path}/lib -liksemel")
+        elif test -d "${iksemel_patch}"; then
+            CFLAGS="$saveflags -L$iksemel_path"
+            AC_CHECK_LIB(iksemel,main, tmp="$PKGLIBS -L$iksemel_path -liksemel")
+        fi
+    fi
+
+    if test "x$tmp" == "x"; then
+        unset ac_cv_lib_iksemel_main
+        if test -d "/usr/local/lib"; then
+            CFLAGS="$saveflags -L/usr/local/lib"
+            AC_CHECK_LIB(iksemel,main, tmp="$PKGLIBS -L/usr/local/lib -liksemel")
+        fi
+    fi
+
+    if test "x$tmp" == "x"; then
+        echo "libiksemel library not found - disabling Iksemel support"
+        AC_NOT_AVAILABLE(use-iksemel)
+        cdef_use_iksemel="#undef"
+        enable_use_iksemel="no"
+        iksemel=
+        lp_cv_has_iksemel="no"
+    else
+        PKGLIBS="$tmp"
+    fi
+  fi
+
+  CFLAGS="$saveflags"
+else
+  if test $enable_use_iksemel = yes; then
+      AC_NOT_AVAILABLE(use-iksemel)
+      cdef_use_iksemel="#undef"
+      enable_use_iksemel=no
+  fi
+fi
+
 # --- Check if we need zlib libraries for mccp ---
 
 if test "x$enable_use_mccp" = "x" || test "x$enable_use_mccp" = "xyes"; then
@@ -1662,7 +1761,7 @@
 lp_cv_sys_rename_handles_directories=yes,
 lp_cv_sys_rename_handles_directories=no))
 if test $lp_cv_sys_rename_handles_directories = yes; then
-  AC_DEFINE(RENAME_HANDLES_DIRECTORIES)
+  AC_DEFINE(RENAME_HANDLES_DIRECTORIES,1,[Can rename handle directories?])
 fi
 rmdir conftestdirfrom conftestdirto 2> /dev/null
 
@@ -1699,7 +1798,7 @@
     *v++ = rus.ru_nivcsw;
 ],lp_cv_struct_rusage_full=yes,lp_cv_struct_rusage_full=no))
 if test $lp_cv_struct_rusage_full = no; then
-  AC_DEFINE(GETRUSAGE_RESTRICTED)
+  AC_DEFINE(GETRUSAGE_RESTRICTED, 1, [If so, is it restricted to user and system time?])
 fi
 AC_CACHE_CHECK(struct rusage timeval members with tv_usec,
 lp_cv_struct_rusage_usec,
@@ -1721,7 +1820,7 @@
     *v++ = rus.ru_stime.tv_sec * 1000 + rus.ru_stime.tv_usec / 1000;
 ], lp_cv_struct_rusage_usec=yes, lp_cv_struct_rusage_usec=no))
 if test $lp_cv_struct_rusage_usec = yes; then
-  AC_DEFINE(RUSAGE_USEC)
+  AC_DEFINE(RUSAGE_USEC, 1, [Can ru_utime / ru_stime be accessed as a timeval with tv_sec and tv_usec?])
 fi
 else
 AC_CACHE_CHECK(for getrusage() via syscall(),
@@ -1738,7 +1837,8 @@
 syscall(SYS_GETRUSAGE, RUSAGE_SELF, rus);
 ], lp_cv_func_getrusage_via_syscall=yes, lp_cv_func_getrusage_via_syscall=no))
 if test $lp_cv_func_getrusage_via_syscall=yes; then
-  AC_DEFINE(GETRUSAGE_VIA_SYSCALL) AC_DEFINE(HAVE_GETRUSAGE)
+  AC_DEFINE(HAVE_GETRUSAGE, 1, [Does the system have a getrusage call?])
+  AC_DEFINE(GETRUSAGE_VIA_SYSCALL, 1, [Is it available as a subfunction of syscall()?])
 fi
 fi
 
@@ -1758,7 +1858,7 @@
 void free();
 ],, lp_cv_prop_free_returns_void=yes, lp_cv_prop_free_returns_void=no))
 if test $lp_cv_prop_free_returns_void = yes; then
-  AC_DEFINE(FREE_RETURNS_VOID)
+  AC_DEFINE(FREE_RETURNS_VOID, 1, [does free() have void as its returntype?])
 fi
 
 AC_CACHE_CHECK(if void* or char* from malloc,
@@ -1788,7 +1888,7 @@
 #endif
 ],,lp_cv_prop_malloc_return_type="void *",
 lp_cv_prop_malloc_return_type="char *"))
-AC_DEFINE_UNQUOTED(POINTER,$lp_cv_prop_malloc_return_type)
+AC_DEFINE_UNQUOTED(POINTER,$lp_cv_prop_malloc_return_type,[what kind of pointer is used by malloc() et al])
 
 AC_CACHE_CHECK(if CHAR_BIT == 8 or undef,
 lp_cv_prop_charbits_eq_8,
@@ -1803,7 +1903,7 @@
 int i=[1/(CHAR_BIT-8)];
 ],,lp_cv_prop_charbits_eq_8=no, lp_cv_prop_charbits_eq_8=yes))
 if test $lp_cv_prop_charbits_eq_8 = yes; then
-  AC_DEFINE(CHARBIT_MASK, 0xff)
+  AC_DEFINE(CHARBIT_MASK, 0xff, [A mask that allows to extract an unsigned char from a signed])
 else
 dnl TODO: this is something I don't really understand... am I too stupid?
 dnl TODO:: bitmask set to number of bits ?????? *shudder* [Mubo]
@@ -1827,7 +1927,7 @@
 ], lp_cv_prop_strtol_broken=no,
 lp_cv_prop_strtol_broken=yes))
 if test $lp_cv_prop_strtol_broken = yes; then
-  AC_DEFINE(STRTOL_BROKEN)
+  AC_DEFINE(STRTOL_BROKEN, 1, [the atari strtol() used to consider characters '9' < c < 'A' to be numeric])
 fi
 
 dnl the following three tests would better be nested, but it seems to overflow
@@ -1908,7 +2008,7 @@
 AC_MSG_WARN(You have to supply the correct way to set sockets non-blocking by hand.)
 ))
 if test $lp_cv_prop_use_ioctl_fionbio = yes; then
-  AC_DEFINE(USE_IOCTL_FIONBIO)
+  AC_DEFINE(USE_IOCTL_FIONBIO, 1, [How to set a socket non-blocking])
 fi
 
 AC_CACHE_CHECK(nonblocking using fcntl with O_NDELAY,
@@ -1968,7 +2068,7 @@
 lp_cv_prop_use_fnctl_o_ndelay=no,
 lp_cv_prop_use_fnctl_o_ndelay=unknown))
 if test $lp_cv_prop_use_fnctl_o_ndelay = yes; then
-  AC_DEFINE(USE_FCNTL_O_NDELAY)
+  AC_DEFINE(USE_FCNTL_O_NDELAY,1,[nonblocking using fcntl with O_NDELAY])
 fi
 
 AC_CACHE_CHECK(nonblocking using fcntl with FNDELAY,
@@ -2028,7 +2128,7 @@
 lp_cv_prop_use_fcntl_fndelay=no,
 lp_cv_prop_use_fcntl_fndelay=unknown))
 if test $lp_cv_prop_use_fcntl_fndelay = yes; then
-  AC_DEFINE(USE_FCNTL_FNDELAY)
+  AC_DEFINE(USE_FCNTL_FNDELAY,1,[nonblocking using fcntl with FNDELAY])
 fi
 
 
@@ -2086,7 +2186,7 @@
 lp_cv_prop_use_fcntl_setown=no,
 lp_cv_prop_use_fcntl_setown=unknown))
 if test $lp_cv_prop_use_fcntl_setown = yes; then
-  AC_DEFINE(USE_FCNTL_SETOWN)
+  AC_DEFINE(USE_FCNTL_SETOWN, 1, [Can F_SETOWN be used on a socket?])
 fi
 
 AC_CACHE_CHECK(if OOBINLINE works,
@@ -2146,7 +2246,7 @@
 lp_cv_prop_use_oobinline=no,
 lp_cv_prop_use_oobinline=unknown))
 if test $lp_cv_prop_use_oobinline = yes; then
-  AC_DEFINE(USE_OOBINLINE)
+  AC_DEFINE(USE_OOBINLINE, 1, [Can SO_OOBINLINE be used on a socket?])
 fi
 
 
@@ -2167,7 +2267,7 @@
 lp_cv_prop_overlapping_bcopy=no,
 lp_cv_prop_overlapping_bcopy=yes))
 if test $lp_cv_prop_overlapping_bcopy = yes; then
-  AC_DEFINE(OVERLAPPING_BCOPY)
+  AC_DEFINE(OVERLAPPING_BCOPY, 1, [Define if you have bcopy, and it handles overlapping ranges correctly.])
 fi
 
 AC_CACHE_CHECK(if strtol needs const char*,
@@ -2179,7 +2279,7 @@
 ],,lp_cv_prop_strtol_const_charp=no,
 lp_cv_prop_strtol_const_charp=yes))
 if test $lp_cv_prop_strtol_const_charp = yes; then
-  AC_DEFINE(STRTOL_CONST_CHARP)
+  AC_DEFINE(STRTOL_CONST_CHARP, 1, [needs the first argument of strtol be declared as const?])
 fi
 
 # --- Check for compiler options ---
@@ -2545,7 +2645,7 @@
 ],SBRK_OK=1)
 if test -n "${SBRK_OK}"; then
   if test -z "${TESTFLAG}"; then
-    AC_DEFINE(SBRK_OK)
+    AC_DEFINE(SBRK_OK, 1, [can we define our own malloc() safely?])
   else
     LDFLAGS="${LDFLAGS} ${TESTFLAG}"
     EXTRA_CFLAGS="${EXTRA_CFLAGS} -DSBRK_OK"
@@ -2585,14 +2685,19 @@
 lp_cv_sys_malloc_overhead=`./conftest --terse`
 rm -f conftest*
 )
-AC_DEFINE_UNQUOTED(EXTERN_MALLOC_OVERHEAD,$lp_cv_sys_malloc_overhead)
+AC_DEFINE_UNQUOTED(EXTERN_MALLOC_OVERHEAD,$lp_cv_sys_malloc_overhead,
+    [The following is needed for smalloc without SBRK_OK to use memory            
+     efficiently. smalloc will malloc blocks that are a large power of            
+     two, minus EXTERN_MALLOC_OVERHEAD. If you have no idea what number to        
+     choose, compile & run util/overhead.c
+    ])
 
 if test -z "${CONFIG_SHELL}"; then
   CONFIG_SHELL='/bin/sh'
 fi
 if test "${OSTYPE}" = 'win32'; then
   EXEEXT='.exe'
-  AC_DEFINE(HOST_INCLUDE,"hosts/GnuWin32/GnuWin32.h")
+  AC_DEFINE(HOST_INCLUDE,"hosts/GnuWin32/GnuWin32.h",[define the host-specific include file])
 fi
 
 
@@ -2644,6 +2749,7 @@
 AC_SUBST(cdef_use_mysql)
 AC_SUBST(cdef_use_pgsql)
 AC_SUBST(cdef_use_sqlite)
+AC_SUBST(cdef_use_iksemel)
 AC_SUBST(cdef_use_pthreads)
 AC_SUBST(cdef_use_alists)
 AC_SUBST(cdef_use_mccp)
diff -ruN ldmud-trunk/src/config.h.in ldmud-iksemel/src/config.h.in
--- ldmud-trunk/src/config.h.in	2008-05-06 19:36:19.000000000 +0200
+++ ldmud-iksemel/src/config.h.in	2008-05-06 19:38:53.000000000 +0200
@@ -370,6 +370,10 @@
  */
 @cdef_use_builtin_pcre@ USE_BUILTIN_PCRE
 
+/* Define this if you want iksemel library support.
+ */
+@cdef_use_iksemel@ USE_IKSEMEL
+
 /* Define this if you want the obsolete and deprecated efuns.
  */
 @cdef_use_deprecated@ USE_DEPRECATED
@@ -434,6 +438,16 @@
 #define ALLOWED_ED_CMDS           @val_allowed_ed_cmds@
 /* TODO: ALLOWED_ED_CMDS: make this a runtime option */
 
+/* Limit the amount of recursion in the PCRE code. Setting it to low will
+ * prevent certain regexps to be executed properly, setting it too high can
+ * cause that regexps to crash the driver. Set it according to the
+ * available maximum stack size for the driver process. (Rule of thumb:
+ * The memory used for a recursion on the stack seems to be within 466 and
+ * 1008 bytes. If you have 8M of stack size, choose 7000 - 8000.)
+ * Defaults to 7000
+ */                                                                                       
+#define PCRE_RECURSION_LIMIT    @val_pcre_recursion_limit@                                
+			
 
 /* --- Compiler --- */
 
diff -ruN ldmud-trunk/src/func_spec ldmud-iksemel/src/func_spec
--- ldmud-trunk/src/func_spec	2008-05-06 19:36:19.000000000 +0200
+++ ldmud-iksemel/src/func_spec	2008-05-06 19:43:19.000000000 +0200
@@ -699,6 +699,14 @@
 #endif /* USE_MCCP */
 
 
+#ifdef USE_IKSEMEL
+
+string  xml_generate(mixed *);
+mixed  *xml_parse(string);
+
+#endif /* USE_IKSEMEL */
+
+
 #ifdef USE_MYSQL
 
 int     db_affected_rows(int);
diff -ruN ldmud-trunk/src/main.c ldmud-iksemel/src/main.c
--- ldmud-trunk/src/main.c	2008-05-06 19:36:19.000000000 +0200
+++ ldmud-iksemel/src/main.c	2008-05-06 19:50:19.000000000 +0200
@@ -76,6 +76,10 @@
 #include "pkg-mysql.h"
 #endif
 
+#ifdef USE_IKSEMEL
+#include "pkg-iksemel.h"
+#endif
+
 #include "i-eval_cost.h"
 
 #include "../mudlib/sys/regexp.h"
@@ -445,6 +449,10 @@
         }
 #endif
 
+#ifdef USE_IKSEMEL
+        pkg_iksemel_init();
+#endif
+
         /* If the master_name hasn't been set, select a sensible default */
         if ('\0' == master_name[0])
         {
@@ -1787,6 +1795,9 @@
 #ifdef HAS_IDN
                               , "idna supported\n"
 #endif
+#ifdef USE_IKSEMEL
+                              , "iksemel supported\n"
+#endif
 #ifdef USE_IPV6
                               , "IPv6 supported\n"
 #endif
diff -ruN ldmud-trunk/src/pkg-iksemel.c ldmud-iksemel/src/pkg-iksemel.c
--- ldmud-trunk/src/pkg-iksemel.c	1970-01-01 01:00:00.000000000 +0100
+++ ldmud-iksemel/src/pkg-iksemel.c	2008-05-06 19:39:12.000000000 +0200
@@ -0,0 +1,519 @@
+/*------------------------------------------------------------------
+ * iksemel Efuns
+ *
+ *------------------------------------------------------------------
+ * This file holds the efuns interfacing with iksemel and provides 
+ * functions for handling xml files and converting them between 
+ * mappings and xml data strings.
+ *
+ *   efun: xml_
+ *------------------------------------------------------------------
+ */
+#include "driver.h"
+
+#ifdef USE_IKSEMEL
+
+#include <iksemel.h>
+#include "array.h"
+#include "xalloc.h"
+#include "mapping.h"
+#include "mstrings.h"
+#include "simulate.h"
+#include "interpret.h"
+#include "pkg-iksemel.h"
+#include "typedefs.h"
+
+#include "../mudlib/sys/xml.h"
+
+typedef struct attribute_walk_extra_s attribute_walk_extra_t;
+
+/* This structure is used to walk all attributes as well as for error handling.
+ * In case an error happens, this structure is called too.
+ */
+struct attribute_walk_extra_s
+{
+    iks *node;
+    int size;
+
+    char *tag_name;
+};
+
+/* This structure is used for error handling. In case of an error our handler
+ * called with a pointer ot this structure.
+ */
+struct xml_generate_xml_node_cleanup_s
+{
+    svalue_t head; /* push_error_handler saves the link to our handler here. */
+
+    iks *node;
+};
+
+void *
+iksemel_alloc(size_t size)
+{
+    return xalloc(size);
+}
+
+void
+iksemel_free(void *ptr)
+{
+    xfree(ptr);
+}
+
+void
+add_string_to_mapping(mapping_t *map, char *skey, char *svalue)
+
+/*
+ * Adds a string value under the given key to the given mapping. In case the 
+ * value already exists, it is overriden.
+ */
+{
+    svalue_t key;
+    svalue_t *value;
+
+    /* change the c string into an string_t */
+    put_c_string(&key, skey);
+
+    /* get or insert key */
+    value = get_map_lvalue(map, &key);
+
+    /* free the string_t again */
+    free_svalue(&key);
+
+    /* free maybe existing value (should not happen, i hope) */
+    free_svalue(value);
+
+    /* change the value of the key to the given value */
+    put_c_string(value, svalue);
+}
+
+void
+parse_node(svalue_t *result, iks *node)
+
+/*
+ * Parses the xml DOM starting at node and returns the information on the 
+ * stack.
+ */
+{
+    int i = 0;
+    int num_attributes = 0;
+    int num_children = 0;
+
+    iks *attribute;
+    iks *child;
+
+    vector_t *root = NULL;
+    vector_t *children = NULL;
+    mapping_t *attributes = NULL;
+
+    /* lets figure out if the node is cdata or another tag */
+    switch (iks_type(node))
+    {
+        case IKS_NONE:
+        case IKS_ATTRIBUTE:
+            /* we ignore those, as they will not occure for us */
+
+            return;
+        case IKS_CDATA:
+            /* Add the string as result, and return */
+            put_c_string(result, iks_cdata(node));
+
+            return;
+        case IKS_TAG:
+            break;
+    }
+
+    /* We have a tag here, so allocate a tag array with three elements 
+     * (name, contents and attributes 
+     */
+    memsafe(root = allocate_array(3), sizeof(*root), "new tag array");
+
+    /* Put the array as result */
+    put_array(result, root);
+
+    /* add name to array */
+    put_c_string(&root->item[XML_TAG_NAME], iks_name(node));
+
+    /* check if the node has any children */
+    child = iks_child(node);
+    if (child != NULL)
+    {
+        do
+        {
+            ++num_children;
+        }
+        while ((child = iks_next(child)));
+    }
+
+    if (0 < num_children)
+    {
+        /* children need to stay in the right order, so we create another
+         * for them
+         */
+        memsafe(children = allocate_array(num_children), sizeof(*children)
+                , "new tag contents array");
+
+        /* Add the array of all children to the node */
+        put_array(&root->item[XML_TAG_CONTENTS], children);
+
+        /* get the first child */
+        child = iks_child(node);
+
+        do
+        {
+            /* recurse here cause the child can be a string or another node */
+            parse_node(&children->item[i++], child);        
+        }
+        while ((child = iks_next(child)));
+    }
+
+    /* Finally, lets handle the attributes, we need to find out how many
+     * attributes the node has, to allocate enough memory for them. If
+     * no attributes exist, the part in the array will be empty */
+
+    attribute = iks_attrib(node);
+    if (attribute != NULL)
+    {
+        do 
+        {
+            ++num_attributes;
+        }
+        while ((attribute = iks_next(attribute)));
+    }
+
+    if (0 < num_attributes)
+    {
+        /* allocate new mapping */
+        memsafe(attributes = allocate_mapping(num_attributes, 1), sizeof(*attributes)
+                , "new attributes mapping");
+
+        /* add the attributes to the array */
+        put_mapping(&root->item[XML_TAG_ATTRIBUTES], attributes);
+
+        /* get the first one */
+        attribute = iks_attrib(node);
+
+        do
+        {
+            add_string_to_mapping(attributes, iks_name(attribute), iks_cdata(attribute));
+        }
+        while ((attribute = iks_next(attribute)));
+   }
+}
+
+void
+walk_attribute_mapping(svalue_t *key, svalue_t *val, void *pextra)
+
+/*
+ * Callback for walk_mapping() used in generate_xml_node to add iks
+ * attribute nodes to the node given in the pextra. 
+ */
+{
+    char *ckey;
+    attribute_walk_extra_t *extra = pextra;
+
+    if (key->type == T_STRING)
+    {
+        ckey = get_txt(key->u.str);
+    }
+    else
+    {
+        errorf("Bad argument 1 to xml_generate(): expected string for attribute key of tag '%s'.\n"
+                , extra->tag_name);
+
+        /* NOTREACHED */
+        return;
+    }
+
+    if (val->type == T_STRING)
+    {
+        memsafe(iks_insert_attrib(extra->node, ckey, get_txt(val->u.str))
+                , sizeof(*ckey), "new iksemel attribute");
+    }
+    else
+    {
+        errorf("Bad argument 1 to xml_generate(): expected string for value of attribute '%s' of tag '%s'.\n"
+                , ckey, extra->tag_name);
+    }
+}
+
+static void
+xml_generate_xml_node_cleanup(svalue_t * arg)
+    
+/*
+ * Takes care, that the node without parent (root node) is correctly freed in
+ * case of an error and at the end of the f_generate_xml().
+ */
+{
+    struct xml_generate_xml_node_cleanup_s * data;
+
+    data = (struct xml_generate_xml_node_cleanup_s *)arg;
+
+    if (data->node)
+    {
+        iks_delete(data->node);
+    }
+
+    xfree(data);
+} /* xml_generate_xml_node_cleanup() */
+
+iks *
+generate_xml_node(vector_t *vnode, iks *parent)
+
+/* 
+ * Generates a new iks node from the given array structure with the three 
+ * elements (name, contents, attributes) and adds the node to the parent,
+ * or in case this is empty, simply returns it. The contents element may 
+ * contain other tags, so recursion may occur.
+ */
+{
+    iks *node;
+    svalue_t *element;
+    char *name;
+    struct xml_generate_xml_node_cleanup_s * rec_data;
+
+    if ((mp_int) VEC_SIZE(vnode) != 3)
+    {
+        errorf("Bad arg 1 to xml_generate(): tag is not an array with 3 "
+               "elements.\n");
+
+        /* NOTREACHED */
+        return NULL;
+    }
+
+    /* get the name, as this is essential */
+    element = &vnode->item[XML_TAG_NAME];
+
+    if (element->type != T_STRING)
+    {
+        errorf("Bad arg 1 to xml_generate(): first element of tag array not a "
+               "string.\n");
+
+        /* NOTREACHED */
+        return NULL;
+    }
+
+    /* get the name */
+    name = get_txt(element->u.str);
+
+    /* depending whether there is a parent or not, we start the structure 
+     * or add the node to the given one */
+    if (parent == NULL)
+    {
+        memsafe(node = iks_new(name), 30, "new iksemel node");
+
+        rec_data = xalloc(sizeof(*rec_data));
+        if (rec_data == NULL)
+        {
+            iks_delete(node);
+
+            errorf("generate_xml() Out of memory: (%lu bytes) for cleanup structure\n"
+                    , (unsigned long) sizeof(*rec_data));
+
+            /* NOTREACHED */
+            return NULL;
+        }
+        rec_data->node = node;
+
+        push_error_handler(xml_generate_xml_node_cleanup, &(rec_data->head));
+    }
+    else
+    {
+        memsafe(node = iks_insert(parent, name), 30, "insert new iksemel node");
+    }
+
+    /* now handle the attributes of this one */
+    element = &vnode->item[XML_TAG_ATTRIBUTES];
+
+    /* this might be absent */
+    if (element->type == T_MAPPING)
+    {
+        attribute_walk_extra_t extra;
+
+        extra.node = node;
+        extra.size = element->u.map->num_values;
+        extra.tag_name = name;
+
+        /* walk the mapping and add all attributes */
+        walk_mapping(element->u.map, &walk_attribute_mapping, &extra);
+    }
+    else if (element->type != T_NUMBER || element->u.number != 0)
+    {
+        errorf("Bad arg 1 to xml_generate(): third element of tag array not "
+               "NULL/mapping.\n");
+
+        /* NOTREACHED */
+        return NULL;
+    }
+
+    /* now check, if the node has a contents */
+    element = &vnode->item[XML_TAG_CONTENTS];
+
+    /* this might even be absent */
+    if (element->type == T_POINTER)
+    {
+        int size;
+        int i;
+        vector_t *contents;
+
+        /* get the vector */
+        contents = element->u.vec;
+
+        /* get its size */
+        size = (mp_int)VEC_SIZE(contents);
+        
+        for (i = 0; i < size; i++)
+        {
+            element = &contents->item[i];
+
+            if (element->type == T_STRING)
+            {
+                /* found a cdata */
+                memsafe(iks_insert_cdata(node, get_txt(element->u.str), 0)
+                            , mstrsize(element->u.str)
+                            , "new iksemel node cdata");
+            }
+            else if (element->type == T_POINTER)
+            {
+                /* found a sub tag, as iks_insert will handle the insert we do
+                 * not have anything to do with the result
+                 */
+                generate_xml_node(element->u.vec, node);
+            }
+        }
+    }
+    else if (element->type != T_NUMBER || element->u.number != 0)
+    {
+        errorf("Bad arg 1 to xml_generate(): second element of tag array not "
+               "NULL/array.\n");
+
+        /* NOTREACHED */
+        return NULL;
+    }
+
+    return node;
+}
+
+void
+pkg_iksemel_init()
+{
+    iks_set_mem_funcs(iksemel_alloc, iksemel_free);
+}
+
+/*=========================================================================*/
+
+/*                           EFUNS                                         */
+
+/*-------------------------------------------------------------------------*/
+
+svalue_t *
+f_xml_generate(svalue_t *sp)
+
+/* EFUN xml_generate()
+ *
+ *     string xml_generate(string root_handle, mapping children)
+ *
+ * Generates an XML string starting with the given root handle and the 
+ * tokens in the children mapping. The string is returned. In case the
+ * children mapping 
+ */
+{
+    char *xml_string;
+    iks *node;
+    vector_t *root;
+
+    /* get the root of the structure to be used */
+    root = sp->u.vec;
+
+    /* start generating the tree */
+    node = generate_xml_node(root, NULL);
+    
+    /* Clean up and return result */
+    free_svalue(sp);
+
+    /* get the xml string out of the stack */
+    memsafe(xml_string = iks_string(iks_stack(node), node)
+            , sizeof(*xml_string), "new xml string from node");
+
+    /* send the xml string back onto the stack */
+    put_c_string(sp, xml_string);
+
+    /* clean up, this will free the root node too, as it calles our error handler */
+    pop_stack();
+
+    return sp;
+}
+
+svalue_t *
+f_xml_parse(svalue_t * sp)
+
+/* EFUN xml_parse()
+ *
+ *     mixed * xml_parse(string xml_text)
+ *
+ * Parses the string <xml_text> into a mapping of the following type. This 
+ * method is not able to parse an xml tree with multiple root nodes, so only
+ * first root node is used.
+ *
+ *    ([ name (string)        : the name of the tag
+ *       attributes (mapping) : a mapping where the key is the name and the
+ *                              value is the value of the attribute
+ *       contents (mixed)     : the contents that may be an array of mappings
+ *                              in case the tag contains subtags
+ *    ])
+ */
+{
+    iks *tree;
+    iksparser *parser;
+    int err;
+
+    memsafe(parser = iks_dom_new(&tree), 50, "new iksemel parser");
+
+    err = iks_parse(parser, get_txt(sp->u.str), 0, 1);
+    switch (err)
+    {
+    case IKS_OK:
+        break;
+
+    case IKS_NOMEM:
+        errorf("Out of memory.\n");
+
+        iks_parser_delete(parser);
+
+        /* NOTREACHED */
+        return sp;
+    case IKS_BADXML:
+        errorf("Bad arg 1 to xml_parse(): XML document not well formed (error "
+               "in line %ld, byte %ld).\n", iks_nr_lines(parser)
+               , iks_nr_bytes(parser));
+        
+        iks_parser_delete(parser);
+
+        /* NOTREACHED */
+        return sp;
+    case IKS_HOOK:
+        /* actually only used for a sax parser? */
+
+        break;
+    }
+
+    /* we no longer need the string */
+    free_svalue(sp);
+
+    /* set 0 to always have a valid return */
+    put_number(sp, 0);
+
+    if (tree != NULL)
+    {
+        /* tree contains the tree now, this will put the resulting a */
+        parse_node(sp, tree);
+    }
+
+    /* At the end, be nice and remove the rest */
+    iks_delete(tree);
+    iks_parser_delete(parser);
+ 
+    return sp;
+}
+ 
+#endif /* USE_IKSEMEL */
diff -ruN ldmud-trunk/src/pkg-iksemel.h ldmud-iksemel/src/pkg-iksemel.h
--- ldmud-trunk/src/pkg-iksemel.h	1970-01-01 01:00:00.000000000 +0100
+++ ldmud-iksemel/src/pkg-iksemel.h	2008-05-06 19:39:12.000000000 +0200
@@ -0,0 +1,19 @@
+#ifndef PKG_IKSEMEL_H__
+#define PKG_IKSEMEL_H__ 1
+
+#include "driver.h"
+
+#ifdef USE_IKSEMEL
+
+#ifndef HAS_IKSEMEL
+#error "pkg-iksemel configured even though the machine doesn't support iksemel."
+#endif
+
+/* --- Prototypes --- */
+
+void pkg_iksemel_init();
+
+#endif /* USE_IKSEMEL */
+
+#endif /* PKG_IKSEMEL_H__ */
+
