diff options
Diffstat (limited to 'src/xml.c')
-rw-r--r-- | src/xml.c | 134 |
1 files changed, 120 insertions, 14 deletions
diff --git a/src/xml.c b/src/xml.c index 5c4b6ee35f0..7be8613f74a 100644 --- a/src/xml.c +++ b/src/xml.c @@ -28,6 +28,99 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "lisp.h" #include "buffer.h" + +static Lisp_Object Qlibxml2_dll; + +#ifdef WINDOWSNT + +#include <windows.h> +#include "w32.h" + +/* Macro for defining functions that will be loaded from the libxml2 DLL. */ +#define DEF_XML2_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args + +/* Macro for loading libxml2 functions from the library. */ +#define LOAD_XML2_FN(lib,func) { \ + fn_##func = (void *) GetProcAddress (lib, #func); \ + if (!fn_##func) goto bad_library; \ + } + +DEF_XML2_FN (htmlDocPtr, htmlReadMemory, + (const char *, int, const char *, const char *, int)); +DEF_XML2_FN (xmlDocPtr, xmlReadMemory, + (const char *, int, const char *, const char *, int)); +DEF_XML2_FN (xmlNodePtr, xmlDocGetRootElement, (xmlDocPtr)); +DEF_XML2_FN (void, xmlFreeDoc, (xmlDocPtr)); +DEF_XML2_FN (void, xmlCleanupParser, (void)); +DEF_XML2_FN (void, xmlCheckVersion, (int)); + +static int +libxml2_loaded_p (void) +{ + Lisp_Object found = Fassq (Qlibxml2_dll, Vlibrary_cache); + + if (CONSP (found)) + return EQ (XCDR (found), Qt) ? 1 : 0; + return 0; +} + +#else /* !WINDOWSNT */ + +#define fn_htmlReadMemory htmlReadMemory +#define fn_xmlReadMemory xmlReadMemory +#define fn_xmlDocGetRootElement xmlDocGetRootElement +#define fn_xmlFreeDoc xmlFreeDoc +#define fn_xmlCleanupParser xmlCleanupParser +#define fn_xmlCheckVersion xmlCheckVersion + +static inine int +libxml2_loaded_p (void) +{ + return 1; +} + +#endif /* !WINDOWSNT */ + +static int +init_libxml2_functions (Lisp_Object libraries) +{ +#ifdef WINDOWSNT + Lisp_Object found = Fassq (Qlibxml2_dll, Vlibrary_cache); + + if (libxml2_loaded_p ()) + return 1; + else + { + HMODULE library; + + if (!(library = w32_delayed_load (libraries, Qlibxml2_dll))) + { + message ("%s", "libxml2 library not found"); + return 0; + } + + /* LOAD_XML2_FN jumps to bad_library if it fails to find the + named function. */ + LOAD_XML2_FN (library, htmlReadMemory); + LOAD_XML2_FN (library, xmlReadMemory); + LOAD_XML2_FN (library, xmlDocGetRootElement); + LOAD_XML2_FN (library, xmlFreeDoc); + LOAD_XML2_FN (library, xmlCleanupParser); + LOAD_XML2_FN (library, xmlCheckVersion); + + Vlibrary_cache = Fcons (Fcons (Qlibxml2_dll, Qt), Vlibrary_cache); + return 1; + } + + bad_library: + Vlibrary_cache = Fcons (Fcons (Qlibxml2_dll, Qnil), Vlibrary_cache); + + return 0; +#else /* !WINDOWSNT */ + return 1; +#endif /* !WINDOWSNT */ +} + static Lisp_Object make_dom (xmlNode *node) { @@ -92,7 +185,7 @@ parse_region (Lisp_Object start, Lisp_Object end, Lisp_Object base_url, int html EMACS_INT bytes; EMACS_INT istart, iend; - LIBXML_TEST_VERSION; + fn_xmlCheckVersion (LIBXML_VERSION); validate_region (&start, &end); @@ -111,16 +204,16 @@ parse_region (Lisp_Object start, Lisp_Object end, Lisp_Object base_url, int html bytes = CHAR_TO_BYTE (iend) - CHAR_TO_BYTE (istart); if (htmlp) - doc = htmlReadMemory ((char *) BYTE_POS_ADDR (CHAR_TO_BYTE (istart)), - bytes, burl, "utf-8", - HTML_PARSE_RECOVER|HTML_PARSE_NONET| - HTML_PARSE_NOWARNING|HTML_PARSE_NOERROR| - HTML_PARSE_NOBLANKS); + doc = fn_htmlReadMemory ((char *) BYTE_POS_ADDR (CHAR_TO_BYTE (istart)), + bytes, burl, "utf-8", + HTML_PARSE_RECOVER|HTML_PARSE_NONET| + HTML_PARSE_NOWARNING|HTML_PARSE_NOERROR| + HTML_PARSE_NOBLANKS); else - doc = xmlReadMemory ((char *) BYTE_POS_ADDR (CHAR_TO_BYTE (istart)), - bytes, burl, "utf-8", - XML_PARSE_NONET|XML_PARSE_NOWARNING| - XML_PARSE_NOBLANKS |XML_PARSE_NOERROR); + doc = fn_xmlReadMemory ((char *) BYTE_POS_ADDR (CHAR_TO_BYTE (istart)), + bytes, burl, "utf-8", + XML_PARSE_NONET|XML_PARSE_NOWARNING| + XML_PARSE_NOBLANKS |XML_PARSE_NOERROR); if (doc != NULL) { @@ -139,19 +232,26 @@ parse_region (Lisp_Object start, Lisp_Object end, Lisp_Object base_url, int html if (NILP (result)) { /* The document isn't just comments, so get the tree the proper way. */ - xmlNode *node = xmlDocGetRootElement (doc); + xmlNode *node = fn_xmlDocGetRootElement (doc); if (node != NULL) result = make_dom (node); } else result = Fcons (intern ("top"), Fcons (Qnil, Fnreverse (Fcons (r, result)))); - xmlFreeDoc (doc); + fn_xmlFreeDoc (doc); } return result; } +void +xml_cleanup_parser (void) +{ + if (libxml2_loaded_p ()) + fn_xmlCleanupParser (); +} + DEFUN ("libxml-parse-html-region", Flibxml_parse_html_region, Slibxml_parse_html_region, 2, 3, 0, @@ -159,7 +259,9 @@ DEFUN ("libxml-parse-html-region", Flibxml_parse_html_region, If BASE-URL is non-nil, it is used to expand relative URLs. */) (Lisp_Object start, Lisp_Object end, Lisp_Object base_url) { - return parse_region (start, end, base_url, 1); + if (init_libxml2_functions (Vdynamic_library_alist)) + return parse_region (start, end, base_url, 1); + return Qnil; } DEFUN ("libxml-parse-xml-region", Flibxml_parse_xml_region, @@ -169,7 +271,9 @@ DEFUN ("libxml-parse-xml-region", Flibxml_parse_xml_region, If BASE-URL is non-nil, it is used to expand relative URLs. */) (Lisp_Object start, Lisp_Object end, Lisp_Object base_url) { - return parse_region (start, end, base_url, 0); + if (init_libxml2_functions (Vdynamic_library_alist)) + return parse_region (start, end, base_url, 0); + return Qnil; } @@ -181,6 +285,8 @@ syms_of_xml (void) { defsubr (&Slibxml_parse_html_region); defsubr (&Slibxml_parse_xml_region); + + DEFSYM (Qlibxml2_dll, "libxml2"); } #endif /* HAVE_LIBXML2 */ |