View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000538 | LDMud 3.3 | Efuns | public | 2008-05-06 12:34 | 2018-01-29 21:57 |
Reporter | Bardioc | Assigned To | Gnomi | ||
Priority | normal | Severity | feature | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | 3.3 | ||||
Fixed in Version | 3.3.719 | ||||
Summary | 0000538: New Package pkg-iksemel for driver that adds xml_parse() as well as xml_generate() (using libiksemel) | ||||
Description | New Package that adds XML functionality to the driver in the way of parsing an xml document into a array-based structure and back. Based on bug report 326, but heavily modified (I did not include any of the socket stuff of the old patch) The patch introduces two new efuns: xml_parse() and xml_generate(). While the first parses an XML document into an array-based structure, the second generates one out of this structure, thus x == xml_generate(xml_parse(x)) Currently only DOM is supported, however libiksemel even provides SAX methods, so if interested, I can extend it. Patch includes documentation in doc/efun as well as a new mudlib/sys/xml.h header file. To use the patch, apply it first and afterwards call 'autoreconf' inside src/autoconf. Then move the newly generated files src/autoconf/configure and src/autoconf/machine.h.in to src/ The newly generated 'configure' will include a --enable-use-iksemel. You need the libiksemel, a lightweight iksemel library from Google. I choose it, cause Gawain used it and it turned out to be fairly useful. Please tell me if you like it. Greetings, Bardioc@Evermore | ||||
Additional Information | I would like to thank Gnomi for his support in the development of this patch. Additionally the patch includes a recreation of the src/autoconf/configure.in that obsoletes the second file aclocal.h in that directory. This is necessary as m4 as well as autoconf/autoreconf do in some versions no longer run properly. This patch has been done by Gnomi too, well again Thanx! | ||||
Tags | No tags attached. | ||||
Attached Files | pkg-iksemel.diff (46,448 bytes)
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__ */ + pkg-iksemel-v2.diff (45,637 bytes)
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 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__ */ + pkg-xml2-2505.diff (30,932 bytes)
Index: src/version.sh =================================================================== --- src/version.sh (Revision 2505) +++ src/version.sh (Arbeitskopie) @@ -17,7 +17,7 @@ # A timestamp, to be used by bumpversion and other scripts. # It can be used, for example, to 'touch' this file on every build, thus # forcing revision control systems to add it on every checkin automatically. -version_stamp="2009-01-12 21:08:13" +version_stamp="So 18. Jan 01:12:24 CET 2009" # The version number information version_micro=718 Index: src/settings/evermore =================================================================== --- src/settings/evermore (Revision 2505) +++ src/settings/evermore (Arbeitskopie) @@ -67,6 +67,9 @@ # we want mysql enable_use_mysql=yes +# we want iksemel +enable_use_xml2=yes + # but we do not want old names for efuns enable_use_deprecated=no Index: src/main.c =================================================================== --- src/main.c (Revision 2505) +++ src/main.c (Arbeitskopie) @@ -80,6 +80,10 @@ #include "pkg-iksemel.h" #endif +#ifdef USE_XML2 +#include "pkg-xml2.h" +#endif + #include "i-eval_cost.h" #include "../mudlib/sys/regexp.h" @@ -453,6 +457,10 @@ pkg_iksemel_init(); #endif +#ifdef USE_XML2 + pkg_xml2_init(); +#endif + /* If the master_name hasn't been set, select a sensible default */ if ('\0' == master_name[0]) { @@ -1803,6 +1811,9 @@ #ifdef USE_IKSEMEL , "iksemel supported\n" #endif +#ifdef USE_XML2 + , "libxml2 supported\n" +#endif #ifdef USE_IPV6 , "IPv6 supported\n" #endif Index: src/lex.c =================================================================== --- src/lex.c (Revision 2505) +++ src/lex.c (Arbeitskopie) @@ -846,7 +846,7 @@ #ifdef USE_SQLITE add_permanent_define("__SQLITE__", -1, string_copy("1"), MY_FALSE); #endif -#ifdef USE_IKSEMEL +#if defined(USE_IKSEMEL) || defined(USE_XML2) add_permanent_define("__XML_DOM__", -1, string_copy("1"), MY_FALSE); #endif #ifdef USE_ALISTS Index: src/Makefile.in =================================================================== --- src/Makefile.in (Revision 2505) +++ src/Makefile.in (Arbeitskopie) @@ -99,7 +99,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 pgk-iksemel.c pkg-idna.c \ + parser.c parse.c pkg-alists.c pgk-iksemel.c pkg-xml2.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 \ @@ -111,7 +111,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-iksemel.o pkg-idna.o \ + parser.o parse.o pkg-alists.o pkg-iksemel.o pkg-xml2.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 \ Index: src/autoconf/configure.in =================================================================== --- src/autoconf/configure.in (Revision 2505) +++ src/autoconf/configure.in (Arbeitskopie) @@ -123,7 +123,8 @@ 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-iksemel,no,,[Enables use of iksemel for XML parsing (exclusive to xml2)]) +AC_MY_ARG_ENABLE(use-xml2,no,,[Enables use of libxml2 for XML parsing (exclusive to iksemel)]) 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]) @@ -327,18 +328,50 @@ 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" + if test "x$enable_use_xml2" = "x" || test "x$enable_use_xml2" = "xyes" ; then + echo "WARNING: iksemel and xml2 support are mutual exclusive." + echo " Disabling iksemel support" + + cdef_use_iksemel="#undef" + enable_use_iksemel="no" + iksemel_path= + else + cdef_use_iksemel="#define" + iksemel_path= + enable_use_iksemel="yes" + fi 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" + if test "x$enable_use_xml2" != "xno"; then + echo "WARNING: iksemel and xml2 support are mutual exclusive." + echo " Disabling iksemel support" + + cdef_use_iksemel="#undef" + enable_use_iksemel="no" + iksemel_path= + else + cdef_use_iksemel="#define" + iksemel_path="$enable_use_iksemel" + enable_use_iksemel="yes" + fi fi +AC_UPDATE_VAR(enable_use_xml2) +if test "x$enable_use_xml2" = "x" || test "x$enable_use_xml2" = "xyes"; then + cdef_use_xml2="#define" + xml2_path= + enable_use_xml2="yes" +elif test "x$enable_use_xml2" = "xno"; then + cdef_use_xml2="yes" + xml2_path= +else + cdef_use_xml2="#define" + xml2_path="$enable_use_xml2" + enable_use_xml2="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" @@ -1747,6 +1780,184 @@ fi fi +# --- libxml2 --- + +if test x$xml2_path != x ; then + xml_config_args="$xml_config_args" + if test x${XML2_CONFIG+set} != xset ; then + XML2_CONFIG=$xml2_path/bin/xml2-config + fi +fi + +AC_PATH_PROG(XML2_CONFIG, xml2-config, no) +min_xml_version=2.0.0 +AC_MSG_CHECKING(for libxml - version >= $min_xml_version) +lp_cv_has_xml2=yes +if test "$XML2_CONFIG" = "no" ; then + lp_cv_has_xml2=no +else + XML_CPPFLAGS=`$XML2_CONFIG $xml_config_args --cflags` + XML_LIBS=`$XML2_CONFIG $xml_config_args --libs` + xml_config_major_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + xml_config_minor_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + xml_config_micro_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" + LIBS="$XML_LIBS $LIBS" + +dnl +dnl Now check if the installed libxml is sufficiently new. +dnl (Also sanity checks the results of xml2-config to some extent) +dnl + + rm -f conf.xmltest + AC_TRY_RUN([ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <libxml/xmlversion.h> + +int +main() +{ + int xml_major_version; + int xml_minor_version; + int xml_micro_version; + int major, minor, micro; + char *tmp_version; + + system("touch conf.xmltest"); + + /* Capture xml2-config output via autoconf/configure variables */ + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = (char *)strdup("$min_xml_version"); + + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) + { + printf("%s, bad version string from xml2-config\n", "$min_xml_version"); + exit(1); + } + free(tmp_version); + + /* Capture the version information from the header files */ + tmp_version = (char *)strdup(LIBXML_DOTTED_VERSION); + + if (sscanf(tmp_version, "%d.%d.%d", &xml_major_version, &xml_minor_version, &xml_micro_version) != 3) + { + printf("%s, bad version string from libxml includes\n", "LIBXML_DOTTED_VERSION"); + exit(1); + } + free(tmp_version); + + /* Compare xml2-config output to the libxml headers */ + if ((xml_major_version != $xml_config_major_version) + || (xml_minor_version != $xml_config_minor_version) + || (xml_micro_version != $xml_config_micro_version)) + { + printf("*** libxml header files (version %d.%d.%d) do not match\n", + xml_major_version, xml_minor_version, xml_micro_version); + printf("*** xml2-config (version %d.%d.%d)\n", + $xml_config_major_version, $xml_config_minor_version, $xml_config_micro_version); + + return 1; + } + + /* Compare the headers to the library to make sure we match */ + /* Less than ideal -- doesn't provide us with return value feedback, + * only exits if there's a serious mismatch between header and library. + */ + LIBXML_TEST_VERSION; + + /* Test that the library is greater than our minimum version */ + if ((xml_major_version > major) + || ((xml_major_version == major) && (xml_minor_version > minor)) + || ((xml_major_version == major) && (xml_minor_version == minor) + && (xml_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of libxml (%d.%d.%d) was found.\n", + xml_major_version, xml_minor_version, xml_micro_version); + printf("*** You need a version of libxml newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** libxml is always available from ftp://ftp.xmlsoft.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the xml2-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of LIBXML, but you can also set the XML2_CONFIG environment to point to the\n"); + printf("*** correct copy of xml2-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + + return 1; +} +],, lp_cv_has_xml2=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" +fi + +if test $lp_cv_has_xml2 = yes ; then + AC_MSG_RESULT(yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)) + AC_DEFINE(HAS_XML2, 1, [Does the machine offer xml2?]) + PKGLIBS="$PKGLIBS $XML_LIBS" + EXTRA_CFLAGS="$XML_CPPFLAGS $EXTRA_CFLAGS" +else + AC_MSG_RESULT(no) + if test "$XML2_CONFIG" = "no" ; then + echo "*** The xml2-config script installed by LIBXML could not be found" + echo "*** If libxml was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the XML2_CONFIG environment variable to the" + echo "*** full path to xml2-config." + else + if test -f conf.xmltest ; then + : + else + echo "*** Could not run libxml test program, checking why..." + CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" + LIBS="$LIBS $XML_LIBS" + AC_TRY_LINK([ +#include <libxml/xmlversion.h> +#include <stdio.h> +], [ LIBXML_TEST_VERSION; return 0;], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding LIBXML or finding the wrong" + echo "*** version of LIBXML. If it is not finding LIBXML, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means LIBXML was incorrectly installed" + echo "*** or that you have moved LIBXML since it was installed. In the latter case, you" + echo "*** may want to edit the xml2-config script: $XML2_CONFIG" ]) + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + + XML_CPPFLAGS="" + XML_LIBS="" + + AC_NOT_AVAILABLE(use-xml2) + cdef_use_xml2="#undef" + enable_use_xml2="no" + xml2= + lp_cv_has_xml2=no +fi +AC_SUBST(XML_CPPFLAGS) +AC_SUBST(XML_LIBS) +rm -f conf.xmltest + # --- Check if we need zlib libraries for mccp --- if test "x$enable_use_mccp" = "x" || test "x$enable_use_mccp" = "xyes"; then @@ -2727,6 +2938,7 @@ AC_SUBST(cdef_use_pgsql) AC_SUBST(cdef_use_sqlite) AC_SUBST(cdef_use_iksemel) +AC_SUBST(cdef_use_xml2) AC_SUBST(cdef_use_pthreads) AC_SUBST(cdef_use_alists) AC_SUBST(cdef_use_mccp) Index: src/pkg-xml2.c =================================================================== --- src/pkg-xml2.c (Revision 0) +++ src/pkg-xml2.c (Revision 0) @@ -0,0 +1,602 @@ +/*------------------------------------------------------------------ + * xml_* Efuns + * + *------------------------------------------------------------------ + * This file holds the efuns interfacing with libxml2 and provides + * functions for handling xml files and converting them between + * mappings and xml data strings. + * + * efun: xml_ + *------------------------------------------------------------------ + */ +#include "driver.h" + +#ifdef USE_XML2 + +#include <libxml/parser.h> +#include <libxml/tree.h> +#include "array.h" +#include "xalloc.h" +#include "mapping.h" +#include "mstrings.h" +#include "simulate.h" +#include "interpret.h" +#include "pkg-xml2.h" +#include "typedefs.h" + +#include "../mudlib/sys/xml.h" + +/* Structure to walk over the attribute (properties in libxml2 jargon) to + * create property-nodes + */ +typedef struct attribute_walk_extra_s attribute_walk_extra_t; + +/* 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 +{ + xmlNodePtr node; + int size; + + char *tag_name; +}; + +/* Used for error handling. In case of an error our handler called with a + * pointer ot this structure. + */ +struct xml_cleanup_s +{ + svalue_t head; /* push_error_handler saves the link to our handler here. */ + + xmlDocPtr doc; +}; + +static void * +xml_pkg_malloc(size_t size) + +/* + * Realize malloc with the driver-internal xalloc rather than a direct malloc() + */ +{ + return xalloc(size); +} + +static void +xml_pkg_free(void * ptr) + +/* + * Realize free with the driver-internal xfree rather than a direct free() + */ +{ + xfree(ptr); +} + +static void * +xml_pkg_realloc(void * ptr, size_t size) + +/* + * Realize realloc() with the driver-internal rexalloc_traced() including file + * and line rather the direct realloc() + */ +{ + return rexalloc(ptr, size); +} + +static char * +xml_pkg_strdup(const char * str) + +/* + * Realize strdup with the driver interal string_copy instead of the direct + * strdup() + */ +{ + return string_copy(str); +} + +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, xmlNodePtr node) + +/* + * Parses the xml document beginning at <node> and returns the information + * on the stack in <result>. + */ +{ + int i = 0; + int num_attributes = 0; + int num_children = 0; + + xmlAttrPtr attrib; + xmlNodePtr 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 (node->type) + { + case XML_TEXT_NODE: + put_c_n_string(result + , (char *) node->content + , strlen((char *) node->content)); + + return; + case XML_ELEMENT_NODE: + break; + + default: + /* we ignore all others */ + return; + } + + /* We have a tag here, so allocate a tag array with three elements + * (name, contents and attributes) + */ + memsafe(root = allocate_array(XML_TAG_SIZE), 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], (char *) node->name); + + /* check if the node has any children */ + child = node->children; + if (child != NULL) + { + do + { + if (child->type == XML_ELEMENT_NODE || child->type == XML_TEXT_NODE) + { + ++num_children; + } + } + while ((child = child->next) != NULL); + } + + if (0 < num_children) + { + /* children need to stay in the right order, so we create another + * array 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 = node->children; + + do + { + if (child->type == XML_ELEMENT_NODE || child->type == XML_TEXT_NODE) + { + /* recurse here cause the child can be a string or another node */ + parse_node(&children->item[i++], child); + } + } + while ((child = child->next) != NULL); + } + + /* 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 + */ + attrib = node->properties; + if (attrib != NULL) + { + do + { + ++num_attributes; + } + while ((attrib = attrib->next) != NULL); + } + + 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 */ + attrib = node->properties; + + do + { + xmlChar * value = xmlGetProp(node, attrib->name); + + add_string_to_mapping(attributes, (char *) attrib->name + , (char *) value); + + // we need to free the old one as the driver creates an + // lpc string and thus copies it + xmlFree(value); + } + while ((attrib = attrib->next) != NULL); + } +} + +void +walk_attribute_mapping(svalue_t *key, svalue_t *val, void *pextra) + +/* + * Callback for walk_mapping() used in generate_xml_node to add + * property-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(xmlSetProp(extra->node + , (xmlChar *) ckey + , (xmlChar *) get_txt(val->u.str)) + , sizeof(*ckey), "new 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_cleanup(svalue_t * arg) + +/* + * Takes care, that the xml document is correctly freed in case of an error + * and at the end of the f_generate_xml(). Additionally the xml-parser + * is cleaned up + */ +{ + struct xml_cleanup_s * data; + + data = (struct xml_cleanup_s *) arg; + + if (data->doc) + { + xmlFreeDoc(data->doc); + } + + xmlCleanupParser(); + + xfree(data); +} /* xml_cleanup() */ + +void +generate_xml_node(vector_t * vnode, xmlNodePtr parent, xmlDocPtr doc) + +/* + * Generates a new xml node from the given array structure with the three + * elements (name, contents, attributes) and adds the node to the <parent> + * if it already exists, or to the xml <doc>ument, The contents element may + * contain other tags, so recursion may occur. + */ +{ + xmlNodePtr node; + svalue_t *element; + char *name; + struct xml_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; + } + + /* 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; + } + + /* 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) + { + rec_data = xalloc(sizeof(*rec_data)); + if (rec_data == NULL) + { + xmlFreeDoc(doc); + + errorf("generate_xml() Out of memory: (%lu bytes) for \ + cleanup structure\n", (unsigned long) sizeof(*rec_data)); + + /* NOTREACHED */ + return; + } + + rec_data->doc = doc; + + push_error_handler(xml_cleanup, &(rec_data->head)); + + /** Create first node */ + memsafe(doc->children = xmlNewDocNode(doc, NULL, (xmlChar *) name, NULL) + , 30, "new root node"); + + node = doc->children; + } + else + { + memsafe(node = xmlNewChild(parent, NULL, (xmlChar *) name, NULL), 30 + , "insert new child 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(): second element of tag array not " + "NULL/mapping.\n"); + + /* NOTREACHED */ + return; + } + + /* 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 content */ + xmlNodePtr text; + + memsafe(text = xmlNewTextLen((xmlChar *) get_txt(element->u.str) + , mstrsize(element->u.str)) + , mstrsize(element->u.str), "new text content"); + + xmlAddChild(node, text); + } + 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, doc); + } + } + } + else if (element->type != T_NUMBER || element->u.number != 0) + { + errorf("Bad arg 1 to xml_generate(): third element of tag array not " + "NULL/array.\n"); + + /* NOTREACHED */ + } +} + +void +pkg_xml2_init() +{ + xmlMemSetup(xml_pkg_free, xml_pkg_malloc, xml_pkg_realloc, xml_pkg_strdup); +} + +/*=========================================================================*/ + +/* EFUNS */ + +/*-------------------------------------------------------------------------*/ + +svalue_t * +f_xml_generate(svalue_t *sp) + +/* EFUN xml_generate() + * + * string xml_generate(mixed *xml) + * + * Converts the given <xml> array into an XML conform string, if + * possible. The <xml> argument array must have the same structure + * as xml_parse returns. + * + * In case the parameter does not follow these rules, errors are raised. + * The method returns a valid XML string otherwise. + */ +{ + xmlChar * xml_string; + xmlDocPtr doc; + vector_t * root; + int bufferSize; + + /* get the root of the structure to be used */ + root = sp->u.vec; + + /* create the document itself */ + doc = xmlNewDoc((xmlChar *) "1.0"); + + /* start generating the tree */ + generate_xml_node(root, NULL, doc); + + /* Clean up and return result */ + free_svalue(sp); + + xmlDocDumpFormatMemory(doc, &xml_string, &bufferSize, 1); + + /* send the xml string back onto the stack */ + put_c_string(sp, (char *) xml_string); + + /* free the value once again */ + xmlFree(xml_string); + + /* clean up, this will free the root node too, as it calls our + * error handler */ + pop_stack(); + + return sp; +} + +void +xml_pkg_error_handler(void * userData, xmlErrorPtr error) +{ + if (error) + { + errorf("Bad arg 1 to xml_parse(): %s", error->message); + } +} + +svalue_t * +f_xml_parse(svalue_t * sp) + +/* EFUN xml_parse() + * + * mixed * xml_parse(string xml_text) + * + * Parses the given string <xml> as a XML conform string. The string must + * have only one root tag, subsequent root tags are ignored. + * + * 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 0. + * + * 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 0. + * + * 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, 0 is returned. + */ +{ + struct xml_cleanup_s * rec_data; + + memsafe(rec_data = xalloc(sizeof(*rec_data)), sizeof(*rec_data) + , "xml cleanup structure"); + rec_data->doc = NULL; + push_error_handler(xml_cleanup, &(rec_data->head)); + + /* Disable standard error functions, as they will print out errors + * to stderr automatically. We do not want that. + */ + xmlSetGenericErrorFunc(NULL, NULL); + xmlSetStructuredErrorFunc(NULL, xml_pkg_error_handler); + + rec_data->doc = xmlReadMemory(get_txt(sp->u.str), mstrsize(sp->u.str) + , NULL, NULL, 0); + + if (rec_data->doc == NULL) + { + /* Unfortunately, the error handler is not always called */ + errorf("Bad arg 1 to xml_parse(): not a valid XML document.\n"); + + /* NOT REACHED */ + return sp; + } + + /* we no longer need the string */ + free_svalue(sp); + + /* set 0 to always have a valid return */ + put_number(sp, 0); + + /* tree contains the tree now, this will put the resulting a */ + parse_node(sp, xmlDocGetRootElement(rec_data->doc)); + + /* At the end, be nice and remove the rest using our error handler. */ + pop_stack(); + + return sp; +} + +#endif /* USE_XML2 */ Index: src/pkg-xml2.h =================================================================== --- src/pkg-xml2.h (Revision 0) +++ src/pkg-xml2.h (Revision 0) @@ -0,0 +1,19 @@ +#ifndef PKG_XML2_H__ +#define PKG_XML2_H__ 1 + +#include "driver.h" + +#ifdef USE_XML2 + +#ifndef HAS_XML2 +#error "pkg-xml2 configured even though the machine doesn't support libxml2." +#endif + +/* --- Prototypes --- */ + +void pkg_xml2_init(); + +#endif /* USE_XML2 */ + +#endif /* PKG_XML2_H__ */ + Index: src/config.h.in =================================================================== --- src/config.h.in (Revision 2505) +++ src/config.h.in (Arbeitskopie) @@ -382,6 +382,10 @@ */ @cdef_use_iksemel@ USE_IKSEMEL +/* Define this if you want libxml2 support. + */ +@cdef_use_xml2@ USE_XML2 + /* Define this if you want the obsolete and deprecated efuns. */ @cdef_use_deprecated@ USE_DEPRECATED Index: src/func_spec =================================================================== --- src/func_spec (Revision 2505) +++ src/func_spec (Arbeitskopie) @@ -701,14 +701,13 @@ #endif /* USE_MCCP */ -#ifdef USE_IKSEMEL +#if defined(USE_IKSEMEL) || defined(USE_XML2) string xml_generate(mixed *); mixed *xml_parse(string); -#endif /* USE_IKSEMEL */ +#endif /* USE_IKSEMEL || USE_XML2 */ - #ifdef USE_MYSQL int db_affected_rows(int); bug538.diff (39,464 bytes)
Index: trunk.xml/src/settings/evermore =================================================================== --- trunk.xml/src/settings/evermore (Revision 2554) +++ trunk.xml/src/settings/evermore (Arbeitskopie) @@ -67,6 +67,9 @@ # we want mysql enable_use_mysql=yes +# we want xml2 +enable_use_xml=xml2 + # but we do not want old names for efuns enable_use_deprecated=no Index: trunk.xml/src/settings/unitopia =================================================================== --- trunk.xml/src/settings/unitopia (Revision 2554) +++ trunk.xml/src/settings/unitopia (Arbeitskopie) @@ -62,7 +62,7 @@ enable_use_parse_command=no enable_use_mysql=no enable_use_sqlite=yes -enable_use_iksemel=yes +enable_use_xml=yes enable_use_deprecated=no enable_use_pcre=no enable_lpc_array_calls=yes Index: trunk.xml/src/arraylist.c =================================================================== --- trunk.xml/src/arraylist.c (Revision 0) +++ trunk.xml/src/arraylist.c (Revision 0) @@ -0,0 +1,155 @@ +/*--------------------------------------------------------------------------- + * Arraylist utility functions. + * + *--------------------------------------------------------------------------- + * These functions help to assemble an array whose length is unknown at the + * beginning. So at first all elements are kept in a singly linked list + * until finalize_arraylist is called. + * + * The linked list is saved as an error handler in a svalue_t, so it will + * destruct itself and all of its elements automatically when the svalue_t + * is freed. + * + * This structure is not designed to survive a garbage_collection. + * It should always be finalized or freed in the same execution thread. + *--------------------------------------------------------------------------- + */ + +#include "driver.h" +#include "typedefs.h" + +#include "array.h" +#include "arraylist.h" +#include "interpret.h" +#include "simulate.h" +#include "svalue.h" +#include "xalloc.h" + +/*-------------------------------------------------------------------------*/ +/* Types */ + +typedef struct arraylist_s arraylist_t; +typedef struct arraylist_element_s arraylist_element_t; + +struct arraylist_s +{ + svalue_t head; /* The error handler. */ + + arraylist_element_t *first; + arraylist_element_t *last; + int num; +}; + +struct arraylist_element_s +{ + svalue_t value; + arraylist_element_t * next; +}; + +/*-------------------------------------------------------------------------*/ +static void +cleanup_arraylist (svalue_t * list) + +/* Our cleanup handler, called when the arraylist is freed. + */ +{ + arraylist_t * data = (arraylist_t *) list; + arraylist_element_t * element = data->first; + + while (element) + { + arraylist_element_t * temp = element; + + element = element->next; + + free_svalue(&(temp->value)); + xfree(temp); + } + + xfree(data); +} + +/*-------------------------------------------------------------------------*/ +void +put_arraylist (svalue_t * list) + +/* Create an arraylist and put it into <list>. + */ +{ + arraylist_t * data; + + memsafe(data = xalloc(sizeof(*data)), sizeof(*data), "arraylist"); + + data->head.type = T_ERROR_HANDLER; + data->head.u.error_handler = cleanup_arraylist; + data->num = 0; + data->first = NULL; + data->last = NULL; + + list->type = T_LVALUE; + list->u.lvalue = &(data->head); +} /* put_arraylist() */ + +/*-------------------------------------------------------------------------*/ +svalue_t * +enhance_arraylist (svalue_t * list) + +/* Add an element to the arraylist to <list>. + * It is the responsibility of the caller to ensure + * that <list> is in fact an arraylist. + */ +{ + arraylist_t * data = (arraylist_t *) list->u.lvalue; + arraylist_element_t * element; + + memsafe(element = xalloc(sizeof(*element)), sizeof(*element), "arraylist element"); + element->next = NULL; + put_number(&(element->value), 0); + + if (data->last == NULL) + { + data->first = element; + data->last = element; + } + else + { + data->last->next = element; + data->last = element; + } + data->num++; + + return &(element->value); + +} /* enhance_arraylist() */ + +/*-------------------------------------------------------------------------*/ +void +finalize_arraylist (svalue_t * list) + +/* Turn the arraylist in <list> into a proper array. + */ +{ + arraylist_t * data = (arraylist_t *) list->u.lvalue; + arraylist_element_t * element; + vector_t * result; + svalue_t * item; + + result = allocate_array(data->num); + + element = data->first; + item = result->item; + + while (element) + { + arraylist_element_t * temp = element; + + *item = element->value; + + item++; + element = element->next; + xfree(temp); + } + + xfree(data); + put_array(list, result); +} /* finalize_arraylist() */ Index: trunk.xml/src/arraylist.h =================================================================== --- trunk.xml/src/arraylist.h (Revision 0) +++ trunk.xml/src/arraylist.h (Revision 0) @@ -0,0 +1,14 @@ +#ifndef ARRAYLIST_H__ +#define ARRAYLIST_H__ 1 + +#include "driver.h" +#include <stddef.h> + +#include "typedefs.h" +#include "svalue.h" + +extern void put_arraylist(svalue_t * list); +extern svalue_t * enhance_arraylist(svalue_t * list); +extern void finalize_arraylist(svalue_t * list); + +#endif /* ARRAYLIST_H__ */ Index: trunk.xml/src/main.c =================================================================== --- trunk.xml/src/main.c (Revision 2554) +++ trunk.xml/src/main.c (Arbeitskopie) @@ -77,8 +77,16 @@ #include "pkg-mysql.h" #endif -#ifdef USE_IKSEMEL -#include "pkg-iksemel.h" +#ifdef USE_XML +# if defined(HAS_XML2) && defined(HAS_IKSEMEL) +# error Both, libxml2 and iksemel enabled. +# endif +# ifdef HAS_XML2 +# include "pkg-xml2.h" +# endif +# ifdef HAS_IKSEMEL +# include "pkg-iksemel.h" +# endif #endif #ifdef USE_GCRYPT @@ -469,10 +477,16 @@ } #endif -#ifdef USE_IKSEMEL +#ifdef USE_XML +#ifdef HAS_IKSEMEL pkg_iksemel_init(); #endif +#ifdef HAS_XML2 + pkg_xml2_init(); +#endif +#endif + /* If the master_name hasn't been set, select a sensible default */ if ('\0' == master_name[0]) { @@ -1852,8 +1866,16 @@ #ifdef HAS_IDN , "idna supported\n" #endif -#ifdef USE_IKSEMEL - , "iksemel supported\n" +#ifdef USE_XML + , "XML supported (" +# if defined(HAS_XML2) + "libxml2" +# elif defined(HAS_IKSEMEL) + "iksemel" +# else + "<unknown>" +# endif + ")\n" #endif #ifdef USE_IPV6 , "IPv6 supported\n" Index: trunk.xml/src/lex.c =================================================================== --- trunk.xml/src/lex.c (Revision 2554) +++ trunk.xml/src/lex.c (Arbeitskopie) @@ -849,7 +849,7 @@ #ifdef USE_SQLITE add_permanent_define("__SQLITE__", -1, string_copy("1"), MY_FALSE); #endif -#ifdef USE_IKSEMEL +#ifdef USE_XML add_permanent_define("__XML_DOM__", -1, string_copy("1"), MY_FALSE); #endif #ifdef USE_ALISTS Index: trunk.xml/src/pkg-iksemel.c =================================================================== --- trunk.xml/src/pkg-iksemel.c (Revision 2554) +++ trunk.xml/src/pkg-iksemel.c (Arbeitskopie) @@ -10,8 +10,9 @@ *------------------------------------------------------------------ */ #include "driver.h" +#include "machine.h" -#ifdef USE_IKSEMEL +#if defined(USE_XML) && defined(HAS_IKSEMEL) #include <iksemel.h> #include "array.h" @@ -557,4 +558,4 @@ return sp; } -#endif /* USE_IKSEMEL */ +#endif /* USE_XML && HAS_IKSEMEL */ Index: trunk.xml/src/pkg-iksemel.h =================================================================== --- trunk.xml/src/pkg-iksemel.h (Revision 2554) +++ trunk.xml/src/pkg-iksemel.h (Arbeitskopie) @@ -2,18 +2,15 @@ #define PKG_IKSEMEL_H__ 1 #include "driver.h" +#include "machine.h" -#ifdef USE_IKSEMEL +#if defined(USE_XML) && defined(HAS_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 /* USE_XML && HAS_IKSEMEL */ #endif /* PKG_IKSEMEL_H__ */ Index: trunk.xml/src/autoconf/configure.in =================================================================== --- trunk.xml/src/autoconf/configure.in (Revision 2554) +++ trunk.xml/src/autoconf/configure.in (Arbeitskopie) @@ -87,6 +87,83 @@ not_available="[$not_available], $1" fi]) +dnl Search for library $2. +dnl First try using pkg-config, put its results into $1_LIBS and $1_CFLAGS. +dnl Then try searching in /usr/include, /usr/include/$4 and ${$5}. +dnl Try to compile $6. +dnl Look for library $7. +dnl If successful set $3 to yes, otherwise to no. +AC_DEFUN([AC_MY_SEARCH_LIB], +[ + saveflags="$CFLAGS" + saveeflags="$EXTRA_CFLAGS" + + ifdef([PKG_CHECK_MODULES],[ + PKG_CHECK_MODULES([$1],[$2],[$3]=yes,[$3]=no) + ],[ + [$3]=no + ]) + + # No pkg-config, search manually. + if test $[$3] = no; then + AC_MSG_CHECKING(for [$4] support) + for TESTPATH in "" "${[$5]}" "${[$5]}/include" "${[$5]}/include/[$4]" "/usr/include/[$4]" "/usr/local/include" "/usr/local/include/[$4]" ; do + if test "x$TESTPATH" != "x"; then + CFLAGS="$saveflags -I$TESTPATH" + else + CFLAGS="$saveflags" + fi + AC_TRY_COMPILE([$6],, + [$3]=yes + if test "x$TESTPATH" != "x"; then + EXTRA_CFLAGS="-I$TESTPATH $EXTRA_CFLAGS" + fi + break; + , + CFLAGS="$saveflags" + ) + done + AC_MSG_RESULT($[$3]) + elif test "x$[$1]_CFLAGS" != "x"; then + EXTRA_CFLAGS="$[$1]_CFLAGS $EXTRA_CFLAGS" + fi + + if test $[$3] = yes; then + if test "x$[$1]_LIBS" != "x"; then + PKGLIBS="$PKGLIBS $[$1]_LIBS" + else + tmp="" + + for TESTPATH in "" "${[$5]}" "${[$5]}/lib" "${[$5]}/lib/[$4]" "/usr/lib/[$4]" "/usr/local/lib" "/usr/local/lib/[$4]" ; do + if test "x$TESTPATH" != "x"; then + CFLAGS="$saveflags -L$TESTPATH" + else + CFLAGS="$saveflags" + fi + + AC_CHECK_LIB([$7],xmlParseFile, + if test "x$TESTPATH" != "x"; then + tmp="$PKGLIBS -L$TESTPATH -l[$7]" + else + tmp="$PKGLIBS -l[$7]" + fi + break + ) + done + + if test "x$tmp" == "x"; then + [$3]=no + + EXTRA_CFLAGS="$saveeflags" + else + PKGLIBS="$tmp" + fi + fi + + CFLAGS="$saveflags" + fi +]) + dnl dnl let's start AC_INIT(prolang.y) @@ -120,7 +197,8 @@ AC_MY_ARG_ENABLE(use-pgsql,no,,[Enables PostgreSQL support]) AC_MY_ARG_ENABLE(use-sqlite,no,,[Enables SQLite support]) 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-xml,no,,[Enables XML support: no/xml2/iksemel/yes]) +AC_MY_ARG_WITH(xml-path,,,[Optional location of the XML include/ and lib/ directory]) 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]) @@ -324,19 +402,25 @@ 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= +AC_UPDATE_VAR(enable_use_xml) +if test "x$enable_use_xml" = "x" || test "x$enable_use_xml" = "xyes"; then + cdef_use_xml="#define" + xml_package="any" + enable_use_xml="yes" +elif test "x$enable_use_xml" = "xno"; then + cdef_use_xml="#undef" + xml_package="any" else - cdef_use_iksemel="#define" - iksemel_path="$enable_use_iksemel" - enable_use_iksemel="yes" + cdef_use_xml="#define" + xml_package="$enable_use_xml" + enable_use_xml="yes" fi +AC_UPDATE_VAR(with_xml_path) +if test "x$with_xml_path" = "x" -o "x$with_xml_path" = "xno" ; then + xml_path="" +else + xml_path="$with_xml_path" +fi AC_UPDATE_VAR(enable_use_tls) if test "x$enable_use_tls" = "x" || test "x$enable_use_tls" = "xyes"; then @@ -385,7 +469,6 @@ AC_CDEF_FROM_ENABLE(use_ipv6) AC_CDEF_FROM_ENABLE(use_deprecated) AC_CDEF_FROM_ENABLE(use_structs) -AC_CDEF_FROM_ENABLE(use_tls) AC_CDEF_FROM_ENABLE(use_new_inlines) AC_CDEF_FROM_ENABLE(use_set_light) AC_CDEF_FROM_ENABLE(use_set_is_wizard) @@ -1567,189 +1650,107 @@ # --- SQLite3 --- -# Note: Some compilers don't have /usr/local/include in their standard -# searchpath. +ifdef([PKG_PROG_PKG_CONFIG],[PKG_PROG_PKG_CONFIG()],[]) -AC_CACHE_CHECK(for SQLite3,lp_cv_has_sqlite3, -for TESTPATH in "" "$sqlite_path" "$sqlite_path/include" "/usr/local/include" ; do - saveflags="$CFLAGS" - if test "x$TESTPATH" != "x"; then - CFLAGS="$saveflags -I$TESTPATH" - fi -AC_TRY_COMPILE([ -#include <sqlite3.h> +AC_MY_SEARCH_LIB(SQLITE3,sqlite3,lp_cv_has_sqlite3,sqlite3,xml_path, +[ + #include <sqlite3.h> -sqlite3 * foo(void) -{ + sqlite3 * foo(void) + { + return (sqlite3*)0; + } +],sqlite3) - return (sqlite3*)0; -} -],, -lp_cv_has_sqlite3=yes -if test "x$TESTPATH" != "x"; then - EXTRA_CFLAGS="-I$TESTPATH $EXTRA_CFLAGS" -fi -break; -, -lp_cv_has_sqlite3=no -CFLAGS="$saveflags" -) -done -) -# 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, 1, [Does the machine offer SQLite3?]) + AC_DEFINE(HAS_SQLITE3, 1, [Does the machine offer SQLite3?]) - if test $enable_use_sqlite = yes; then - tmp="" + if test "x$enable_use_sqlite" = "xyes"; then + savelibs="$LIBS" + LIBS="$LIBS $PKGLIBS" - AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -lsqlite3") + # Check if it uses pthreads - if test "x$sqlite_path" == "x"; then - unset ac_cv_lib_sqlite3_main - if test -d "${sqlite_path}/lib/sqlite"; then - CFLAGS="$saveflags -L${sqlite_path}/lib/sqlite" - AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L${sqlite_path}/lib/sqlite -lsqlite3") - elif test -d "${sqlite_path}/lib"; then - CFLAGS="$saveflags -L${sqlite_path}/lib" - AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L${sqlite_path}/lib -lsqlite3") - elif test -d "${sqlite_patch}"; then - CFLAGS="$saveflags -L$sqlite_path" - AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L$sqlite_path -lsqlite3") + AC_SEARCH_LIBS(pthread_create,, + lp_cv_sqlite3_uses_pthreads=yes, + lp_cv_sqlite3_uses_pthreads=no + ) + + if test $lp_cv_sqlite3_uses_pthreads = yes ; then + AC_DEFINE(SQLITE3_USES_PTHREADS, 1, [Does SQLite3 use pthreads?]) fi - fi - if test "x$tmp" == "x"; then - unset ac_cv_lib_sqlite3_main - if test -d "/usr/local/lib"; then - CFLAGS="$saveflags -L/usr/local/lib" - AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L/usr/local/lib -lsqlite3") - fi + LIBS="$savelibs" fi - - if test "x$tmp" == "x"; then +else + if test $enable_use_sqlite = yes; then echo "libsqlite3 library not found - disabling SQLite support" AC_NOT_AVAILABLE(use-sqlite) - cdef_use_sqlite="#undef" - enable_use_sqlite="no" - sqlite= - lp_cv_has_sqlite="no" - else - PKGLIBS="$tmp" fi - fi - if test "x$enable_use_sqlite" = "xyes"; then - savelibs="$LIBS" - LIBS="$LIBS $PKGLIBS" - - # Check if it uses pthreads + cdef_use_sqlite="#undef" + enable_use_sqlite="no" + sqlite= +fi - AC_CHECK_LIB(sqlite3, pthread_create, - lp_cv_sqlite3_uses_pthreads=yes, - lp_cv_sqlite3_uses_pthreads=no - ) +# --- XML --- - if test $lp_cv_sqlite3_uses_pthreads = yes ; then - AC_DEFINE(SQLITE3_USES_PTHREADS, 1, [Does SQLite3 use pthreads?]) - fi +has_xml=no - LIBS="$savelibs" - fi +if test "$xml_package" = "any" -o "$xml_package" = "xml2"; then - CFLAGS="$saveflags" -else - if test $enable_use_sqlite = yes; then - AC_NOT_AVAILABLE(use-sqlite) - cdef_use_sqlite="#undef" - enable_use_sqlite=no - fi -fi + AC_MY_SEARCH_LIB(XML2,libxml-2.0,lp_cv_has_xml2,libxml2,xml_path, + [ + #include <libxml/parser.h> -# --- Iksemel --- + void foo(void) + { + xmlElementType type = XML_ELEMENT_NODE; + } + ],xml2) -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" + if test $lp_cv_has_xml2 = yes; then + if test "$enable_use_xml" = "yes"; then + has_xml=yes + xml_package=xml2 + AC_DEFINE(HAS_XML2, 1, [Does the machine have libxml2?]) + fi 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 "$xml_package" = "any" -o "$xml_package" = "iksemel"; then - if test $enable_use_iksemel = yes; then - tmp="" + AC_MY_SEARCH_LIB(IKSEMEL,iksemel,lp_cv_has_iksemel,iksemel,xml_path, + [ + #include <iksemel.h> - AC_CHECK_LIB(iksemel,main, tmp="$PKGLIBS -liksemel") + iks * foo(void) + { + return (iks*)0; + } + ],iksemel) - 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") + if test $lp_cv_has_iksemel = yes; then + if test "$enable_use_xml" = "yes"; then + has_xml=yes + xml_package=iksemel + AC_DEFINE(HAS_IKSEMEL, 1, [Does the machine have Iksemel?]) fi 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 +if test "$has_xml" = no; then + if test $enable_use_xml = yes; then + echo "XML not supported - disabling XML support." + AC_NOT_AVAILABLE(use-xml) 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 + cdef_use_xml="#undef" + enable_use_xml=no fi + # --- Check if we need zlib libraries for mccp --- if test "x$enable_use_mccp" = "x" || test "x$enable_use_mccp" = "xyes"; then @@ -2323,7 +2324,7 @@ # above correct program, we still can't use it. So check for that. if echo `eval $tcomp2` | egrep '[a-z]' >/dev/null; then : - # Success means 'we got output' here :-( + # Success means 'we got output' here :-( else CFLAGS="$CFLAGS $TESTFLAG" fi @@ -2729,7 +2730,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_xml) AC_SUBST(cdef_use_alists) AC_SUBST(cdef_use_mccp) AC_SUBST(cdef_use_pcre) Index: trunk.xml/src/pkg-xml2.c =================================================================== --- trunk.xml/src/pkg-xml2.c (Revision 0) +++ trunk.xml/src/pkg-xml2.c (Revision 0) @@ -0,0 +1,572 @@ +/*------------------------------------------------------------------ + * xml_* Efuns + * + *------------------------------------------------------------------ + * This file holds the efuns interfacing with libxml2 and provides + * functions for handling xml files and converting them between + * mappings and xml data strings. + * + * efun: xml_ + *------------------------------------------------------------------ + */ +#include "driver.h" +#include "machine.h" + +#if defined(USE_XML) && defined(HAS_XML2) + +#include <libxml/parser.h> +#include <libxml/xmlwriter.h> +#include <libxml/xmlreader.h> +#include "array.h" +#include "arraylist.h" +#include "xalloc.h" +#include "mapping.h" +#include "mstrings.h" +#include "simulate.h" +#include "interpret.h" +#include "pkg-xml2.h" +#include "typedefs.h" + +#include "../mudlib/sys/xml.h" + +/* Structure to walk over the attribute (properties in libxml2 jargon) to + * create property-nodes + */ +typedef struct attribute_walk_extra_s attribute_walk_extra_t; + +/* 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 +{ + xmlTextWriterPtr writer; + char *tag_name; +}; + +/* Used for error handling. In case of an error our handler called with a + * pointer ot this structure. + */ +struct xml_cleanup_s +{ + svalue_t head; /* push_error_handler saves the link to our handler here. */ + + xmlTextReaderPtr reader; + xmlTextWriterPtr writer; + xmlBufferPtr buf; +}; + +static void * +xml_pkg_malloc (size_t size) + +/* + * Realize malloc with the driver-internal xalloc rather than a direct malloc() + */ +{ + return xalloc(size); +} + +static void +xml_pkg_free (void * ptr) + +/* + * Realize free with the driver-internal xfree rather than a direct free() + */ +{ + xfree(ptr); +} + +static void * +xml_pkg_realloc (void * ptr, size_t size) + +/* + * Realize realloc() with the driver-internal rexalloc_traced() including file + * and line rather the direct realloc() + */ +{ + return rexalloc(ptr, size); +} + +static char * +xml_pkg_strdup (const char * str) + +/* + * Realize strdup with the driver interal string_copy instead of the direct + * strdup() + */ +{ + return string_copy(str); +} + +static void +add_string_to_mapping (mapping_t *map, const char *skey, const 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); +} + +static void +parse_node (svalue_t *result, xmlTextReaderPtr reader) + +/* + * Parses the xml document beginning at <node> and returns the information + * on the stack in <result>. + */ +{ + vector_t *element = NULL; + svalue_t *children = NULL; + /* We have a tag here, so allocate a tag array with three elements + * (name, contents and attributes) + */ + memsafe(element = allocate_array(XML_TAG_SIZE), sizeof(*element) + , "new tag array"); + + /* Put the array as result */ + put_array(result, element); + + /* add name to array */ + put_c_string(&element->item[XML_TAG_NAME] + , (const char *) xmlTextReaderConstName(reader)); + + + if (xmlTextReaderHasAttributes(reader)) + { + mapping_t *attributes = NULL; + + /* allocate new mapping */ + memsafe(attributes = allocate_mapping(xmlTextReaderAttributeCount(reader), 1) + , sizeof(*attributes), "new attributes mapping"); + + /* add the attributes to the array */ + put_mapping(&element->item[XML_TAG_ATTRIBUTES], attributes); + + while (MY_TRUE) + { + int ret; + + ret = xmlTextReaderMoveToNextAttribute(reader); + if (ret == 0) + break; + else if (ret < 0) + errorf("(xml_parse) Error reading XML node.\n"); + + add_string_to_mapping(attributes + , (const char *) xmlTextReaderConstName(reader) + , (const char *) xmlTextReaderConstValue(reader)); + } + + xmlTextReaderMoveToElement(reader); + } + + if (!xmlTextReaderIsEmptyElement(reader)) + while (MY_TRUE) + { + int ret; + int is_node = 0; + + ret = xmlTextReaderRead(reader); + if (ret == 0) + errorf("Bad arg 1 to xml_parse(): Premature end of data.\n"); + else if(ret < 0) + errorf("(xml_parse) Error reading XML node.\n"); + + switch (xmlTextReaderNodeType(reader)) + { + case XML_READER_TYPE_END_ELEMENT: + if (children != NULL) + finalize_arraylist(children); + return; + + case XML_READER_TYPE_ELEMENT: + is_node = 1; + /* FALLTHROUGH */ + case XML_READER_TYPE_TEXT: + case XML_READER_TYPE_CDATA: + if (children == NULL) + { + children = &(element->item[XML_TAG_CONTENTS]); + put_arraylist(children); + } + + if (is_node) + parse_node(enhance_arraylist(children), reader); + else + put_c_string(enhance_arraylist(children) + , (const char *) xmlTextReaderConstValue(reader)); + + break; + } + } +} + +static void +walk_attribute_mapping(svalue_t *key, svalue_t *val, void *pextra) + +/* + * Callback for walk_mapping() used in generate_xml_node to add + * property-nodes to the node given in the <pextra>. + */ +{ + attribute_walk_extra_t *extra = pextra; + int rc; + + if (key->type != T_STRING) + errorf("Bad argument 1 to xml_generate(): expected string \ + for attribute key of tag '%s'.\n", extra->tag_name); + + if (val->type != T_STRING) + errorf("Bad argument 1 to xml_generate(): expected string for \ + value of attribute '%s' of tag '%s'.\n" + , get_txt(key->u.str), extra->tag_name); + + rc = xmlTextWriterWriteAttribute( extra->writer + , (xmlChar *) get_txt(key->u.str) + , (xmlChar *) get_txt(val->u.str)); + if (rc < 0) + errorf("(xml_generate) Error writing attribute.\n"); +} + +static void +xml_cleanup (svalue_t * arg) + +/* + * Takes care, that the xml document is correctly freed in case of an error + * and at the end of the f_generate_xml(). Additionally the xml-parser + * is cleaned up + */ +{ + struct xml_cleanup_s * data; + + data = (struct xml_cleanup_s *) arg; + + if (data->buf) + { + xmlBufferFree(data->buf); + } + + if (data->writer) + { + xmlFreeTextWriter(data->writer); + } + + if (data->reader) + { + xmlFreeTextReader(data->reader); + } + + xmlCleanupParser(); + + xfree(data); +} /* xml_cleanup() */ + +static void +write_xml_node(vector_t * vnode, xmlTextWriterPtr writer) + +/* Writes a new xml node from the given array structure with the three + * elements (name, contents, attributes) using <writer>. + * The contents element may contain other tags, so recursion may occur. + */ +{ + svalue_t *element; + char *name; + int rc; + + 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; + } + + /* 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; + } + + name = get_txt(element->u.str); + rc = xmlTextWriterStartElement(writer, (xmlChar *) name); + if (rc < 0) + errorf("(xml_generate) Error writing XML element.\n"); + + /* 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.writer = writer; + 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(): second element of tag array not " + "NULL/mapping.\n"); + + /* NOTREACHED */ + return; + } + + /* 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 content */ + rc = xmlTextWriterWriteString(writer, (xmlChar *) get_txt(element->u.str)); + if (rc < 0) + errorf("(xml_generate) Error writing plain text.\n"); + } + else if (element->type == T_POINTER) + { + /* found a sub tag */ + write_xml_node(element->u.vec, writer); + } + } + } + else if (element->type != T_NUMBER || element->u.number != 0) + { + errorf("Bad arg 1 to xml_generate(): third element of tag array not " + "NULL/array.\n"); + + /* NOTREACHED */ + } + + rc = xmlTextWriterEndElement(writer); + if (rc < 0) + errorf("(xml_generate) Error finishing XML element.\n"); +} + +void +pkg_xml2_init () +{ + /* Check for correct libxml version. */ + LIBXML_TEST_VERSION + + xmlMemSetup(xml_pkg_free, xml_pkg_malloc, xml_pkg_realloc, xml_pkg_strdup); +} + +/*=========================================================================*/ + +/* EFUNS */ + +/*-------------------------------------------------------------------------*/ + +svalue_t * +f_xml_generate (svalue_t *sp) + +/* EFUN xml_generate() + * + * string xml_generate(mixed *xml) + * + * Converts the given <xml> array into an XML conform string, if + * possible. The <xml> argument array must have the same structure + * as xml_parse returns. + * + * In case the parameter does not follow these rules, errors are raised. + * The method returns a valid XML string otherwise. + */ +{ + struct xml_cleanup_s * rec_data; + int rc; + + memsafe(rec_data = xalloc(sizeof(*rec_data)), sizeof(*rec_data) + , "xml cleanup structure"); + rec_data->buf = NULL; + rec_data->writer = NULL; + rec_data->reader = NULL; + push_error_handler(xml_cleanup, &(rec_data->head)); + + /* the output buffer. */ + rec_data->buf = xmlBufferCreate(); + if (rec_data->buf == NULL) + errorf("(xml_generate) Out of memory: temporary buffer.\n"); + + rec_data->writer = xmlNewTextWriterMemory(rec_data->buf, 0); + if (rec_data->writer == NULL) + errorf("(xml_generate) Out of memory: XML writer.\n"); + + rc = xmlTextWriterStartDocument(rec_data->writer, NULL, NULL, NULL); + if (rc < 0) + errorf("(xml_generate) Error starting XML document.\n"); + + write_xml_node(sp->u.vec, rec_data->writer); + + rc = xmlTextWriterEndDocument(rec_data->writer); + if (rc < 0) + errorf("(xml_generate) Error finishing XML document.\n"); + + /* Free the array. */ + free_svalue(sp); + + put_c_string(sp, (char *) rec_data->buf->content); + + /* The error handler will free the buffer + * and XML writer. + */ + pop_stack(); + + return sp; +} + +static void +xml_pkg_error_handler(void * userData, xmlErrorPtr error) +{ + if (error) + { + errorf("Bad arg 1 to xml_parse(): %s", error->message); + } +} + +svalue_t * +f_xml_parse(svalue_t * sp) + +/* EFUN xml_parse() + * + * mixed * xml_parse(string xml_text) + * + * Parses the given string <xml> as a XML conform string. The string must + * have only one root tag, subsequent root tags are ignored. + * + * 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 0. + * + * 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 0. + * + * 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, 0 is returned. + */ +{ + struct xml_cleanup_s * rec_data; + + memsafe(rec_data = xalloc(sizeof(*rec_data)), sizeof(*rec_data) + , "xml cleanup structure"); + rec_data->buf = NULL; + rec_data->writer = NULL; + rec_data->reader = NULL; + push_error_handler(xml_cleanup, &(rec_data->head)); + + /* Disable standard error functions, as they will print out errors + * to stderr automatically. We do not want that. + */ + xmlSetGenericErrorFunc(NULL, NULL); + xmlSetStructuredErrorFunc(NULL, xml_pkg_error_handler); + + rec_data->reader = xmlReaderForMemory(get_txt(sp->u.str) + , mstrsize(sp->u.str) + , NULL, NULL, XML_PARSE_NOENT); + + if (rec_data->reader == NULL) + errorf("(xml_generate) Out of memory: XML reader.\n"); + + /* Put the result on top of the stack. */ + push_number(inter_sp, 0); + + /* Look for the first element. */ + do + { + int ret; + + ret = xmlTextReaderRead(rec_data->reader); + if (ret == 0) + errorf("Bad arg 1 to xml_parse(): Premature end of data.\n"); + else if(ret < 0) + errorf("(xml_parse) Error reading XML node.\n"); + + switch (xmlTextReaderNodeType(rec_data->reader)) + { + case XML_READER_TYPE_ATTRIBUTE: + case XML_READER_TYPE_TEXT: + case XML_READER_TYPE_CDATA: + errorf("Bad arg 1 to xml_parse(): Start tag expected.\n"); + + case XML_READER_TYPE_ELEMENT: + break; + + default: + continue; + } + } while (MY_FALSE); + + /* Now parse the XML string. */ + parse_node(inter_sp, rec_data->reader); + + /* we no longer need the string */ + free_svalue(sp); + + *sp = *inter_sp; + inter_sp--; + + /* At the end, be nice and remove the rest using our error handler. */ + pop_stack(); + + return sp; +} + +#endif /* USE_XML && HAS_XML2 */ Index: trunk.xml/src/pkg-xml2.h =================================================================== --- trunk.xml/src/pkg-xml2.h (Revision 0) +++ trunk.xml/src/pkg-xml2.h (Revision 0) @@ -0,0 +1,16 @@ +#ifndef PKG_XML2_H__ +#define PKG_XML2_H__ 1 + +#include "driver.h" +#include "machine.h" + +#if defined(USE_XML) && defined(HAS_XML2) + +/* --- Prototypes --- */ + +void pkg_xml2_init(); + +#endif /* USE_XML && HAS_XML2 */ + +#endif /* PKG_XML2_H__ */ + Index: trunk.xml/src/config.h.in =================================================================== --- trunk.xml/src/config.h.in (Revision 2554) +++ trunk.xml/src/config.h.in (Arbeitskopie) @@ -381,7 +381,7 @@ /* Define this if you want iksemel library support. */ -@cdef_use_iksemel@ USE_IKSEMEL +@cdef_use_xml@ USE_XML /* Define this if you want the obsolete and deprecated efuns. */ Index: trunk.xml/src/func_spec =================================================================== --- trunk.xml/src/func_spec (Revision 2554) +++ trunk.xml/src/func_spec (Arbeitskopie) @@ -706,12 +706,12 @@ #endif /* USE_MCCP */ -#ifdef USE_IKSEMEL +#ifdef USE_XML string xml_generate(mixed *); mixed *xml_parse(string); -#endif /* USE_IKSEMEL */ +#endif /* USE_XML */ #ifdef USE_MYSQL Index: trunk.xml/mudlib/sys/xml.h =================================================================== --- trunk.xml/mudlib/sys/xml.h (Revision 2554) +++ trunk.xml/mudlib/sys/xml.h (Arbeitskopie) @@ -2,8 +2,8 @@ #define XML_H__ 1 #define XML_TAG_NAME 0 /* Name of the current tag */ -#define XML_TAG_ATTRIBUTES 1 /* Atttributes of the current tag */ -#define XML_TAG_CONTENTS 2 /* Contents of the curren tag */ +#define XML_TAG_ATTRIBUTES 1 /* Atttributes of the current tag */ +#define XML_TAG_CONTENTS 2 /* Contents of the current tag */ #define XML_TAG_SIZE 3 | ||||
related to | 0000326 | closed | XML Support |
|
Nice. Mhmm, the XMPP parser may be interesting for our friends from psyced, maybe they don't have to maintain a own implementation then but use the external lib. I had only a quick glance, but could you check the diff for acconfig.h, config.h.in and configure.in in the patch? There seem to be more changes than only the ones for pkg-iksemel, e.g. config.h.in contains stuff from my patch for bug 0000527. ;-) |
|
Thank you very much Zesstra. I appologize for the part from your patch. I removed it in the new version 'pkg-iksemel-v2.diff' The file acconfig.h however is removed by this patch as Gnomi integrated all necessary parts directly into configure.h.in. |
|
Applied as r2445. |
|
Fippo wants to comment on the choice of iksemel and offer an alternative, so I reopen this bug. |
|
thanks gnomi iksemel seems to be no longer maintained. If I recall correctly it was even 'dead' (in the sense of few/no commits) when it was hosted on jabberstudio.org. And there is only the initial import at google code. In psyclpc we have an expat package which might be interesting. We never switched from our LPC parser to that because it was not really faster. Most of the processing (building the data structures) was done in LPC via a set of callbacks, which made this very flexible (needed for parsing XMPP) but comparatively slow. Building the data structures on C level would probably make this better. I still have a diff against an unmodified ldmud at http://hancke.name/ldmud/expat2/ The configure bits are missing the but should be in psyclpc ( http://lpc.pages.de ). I am not sure if I really like the structure of your XML nodes. For working with it I always found xpath-style expressions useful. For example if you have XML like <foo bar='baz'><q/><c/></foo> and then access 'baz' as node["@bar"], the node "q" as node["/q"], "c" as node["/c"] and the first child of the node (q in this case) as node[1]. But that is mostly a matter of taste :-) zesstra: we would have to maintain iksemel, too. And XMPP is - despite it's name - not really XML and you need lots of hacks to parse and generate it ;-) |
|
I don't mind supporting more than one XML library, but they should present the same interface to LPC. And as such I don't really like the SAX interface, because LPC is an amateur language and so reading an XML file should be as easy as xml_parse(read_file("a.xml")). |
|
I uploaded a new Package that has the exact same interface as the old one, but now uses libxml2 instead of libiksemel. It does not remove pkg-iksemel.c but introduces a new pkg-xml2.c The diff inside of the tar.bz2 will modify autoconf/configure.in and integrate a new configuration option --enable-with-xml2. It also checks that only xml2 or iksemel is used, as they define the same efuns (mutually exclusive). Gnomi is currently checking this. Hope it will be added to the driver soon. |
|
Ok now the diff-file includes even the new files. This patch was made against revision 2498 |
|
Added new version against revision 2505 that fixes a small bug in the xml parsing (added 0 elements for comments). |
|
I attached a modified version of Bardioc's patch that uses the xmlreader/xmlwriter API, so there's no need to build an intermediate DOM representation anymore. It adds an arraylist.c which helps to build an array whose size is unknown. |
|
libxml2 support committed as r2585. |
Date Modified | Username | Field | Change |
---|---|---|---|
2008-05-06 12:34 | Bardioc | New Issue | |
2008-05-06 12:34 | Bardioc | File Added: pkg-iksemel.diff | |
2008-05-06 12:52 | zesstra | Note Added: 0000612 | |
2008-05-06 14:11 | Bardioc | Note Added: 0000615 | |
2008-05-06 14:11 | Bardioc | File Added: pkg-iksemel-v2.diff | |
2008-12-12 16:32 | Gnomi | Status | new => assigned |
2008-12-12 16:32 | Gnomi | Assigned To | => Gnomi |
2008-12-14 09:31 | Gnomi | Status | assigned => resolved |
2008-12-14 09:31 | Gnomi | Fixed in Version | => 3.3.718 |
2008-12-14 09:31 | Gnomi | Resolution | open => fixed |
2008-12-14 09:31 | Gnomi | Note Added: 0000816 | |
2008-12-14 09:34 | Gnomi | Relationship added | related to 0000326 |
2008-12-29 12:19 | Gnomi | Status | resolved => feedback |
2008-12-29 12:19 | Gnomi | Resolution | fixed => reopened |
2008-12-29 12:19 | Gnomi | Note Added: 0000840 | |
2008-12-29 13:14 | fippo | Note Added: 0000841 | |
2008-12-29 13:15 | fippo | Note Edited: 0000841 | |
2008-12-29 13:16 | fippo | Note Edited: 0000841 | |
2009-01-05 09:12 | Gnomi | Note Added: 0000852 | |
2009-01-17 06:37 | Bardioc | File Added: pkg-xml2-files-and-diff.tar.bz2 | |
2009-01-17 06:39 | Bardioc | Note Added: 0000912 | |
2009-01-17 06:44 | Bardioc | File Added: pkg-xml2.diff | |
2009-01-17 06:45 | Bardioc | Note Added: 0000913 | |
2009-01-17 18:18 | Bardioc | File Added: pkg-xml2-2505.diff | |
2009-01-17 18:19 | Bardioc | Note Added: 0000924 | |
2009-01-18 03:07 | zesstra | File Deleted: pkg-xml2-files-and-diff.tar.bz2 | |
2009-01-18 03:07 | zesstra | File Deleted: pkg-xml2.diff | |
2009-05-04 14:18 | Gnomi | File Added: bug538.diff | |
2009-05-04 14:21 | Gnomi | Note Added: 0001077 | |
2009-05-18 01:43 | Gnomi | Note Added: 0001108 | |
2009-05-18 01:43 | Gnomi | Status | feedback => resolved |
2009-05-18 01:43 | Gnomi | Fixed in Version | 3.3.718 => 3.3.719 |
2009-05-18 01:43 | Gnomi | Resolution | reopened => fixed |
2010-11-16 09:42 | Gnomi | Source_changeset_attached | => ldmud.git master 3e4b7818 |
2010-11-16 09:42 | Gnomi | Source_changeset_attached | => ldmud.git master aa028a91 |
2018-01-29 18:59 | Gnomi | Source_changeset_attached | => ldmud.git master 3e4b7818 |
2018-01-29 18:59 | Gnomi | Source_changeset_attached | => ldmud.git master aa028a91 |
2018-01-29 21:57 | Gnomi | Source_changeset_attached | => ldmud.git master 3e4b7818 |
2018-01-29 21:57 | Gnomi | Source_changeset_attached | => ldmud.git master aa028a91 |