diff options
| author | Paul Eggert | 2012-04-09 15:54:59 -0700 |
|---|---|---|
| committer | Paul Eggert | 2012-04-09 15:54:59 -0700 |
| commit | 45e9f7da84c1bd3fc0d36d05c5708ed3b2d3a193 (patch) | |
| tree | 5bc87a8b5a3c754b8eb44a612cc6c03561d6b968 /src/xml.c | |
| parent | 9d6b4d53469a9ffd67bd770fabc6fe254e35c21d (diff) | |
| parent | 05920a43fc18e696b464387e781e7cfdcea5b5af (diff) | |
| download | emacs-45e9f7da84c1bd3fc0d36d05c5708ed3b2d3a193.tar.gz emacs-45e9f7da84c1bd3fc0d36d05c5708ed3b2d3a193.zip | |
Merge from trunk.
Diffstat (limited to 'src/xml.c')
| -rw-r--r-- | src/xml.c | 132 |
1 files changed, 118 insertions, 14 deletions
| @@ -28,6 +28,97 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 28 | #include "lisp.h" | 28 | #include "lisp.h" |
| 29 | #include "buffer.h" | 29 | #include "buffer.h" |
| 30 | 30 | ||
| 31 | |||
| 32 | static Lisp_Object Qlibxml2_dll; | ||
| 33 | |||
| 34 | #ifdef WINDOWSNT | ||
| 35 | |||
| 36 | #include <windows.h> | ||
| 37 | #include "w32.h" | ||
| 38 | |||
| 39 | /* Macro for defining functions that will be loaded from the libxml2 DLL. */ | ||
| 40 | #define DEF_XML2_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args | ||
| 41 | |||
| 42 | /* Macro for loading libxml2 functions from the library. */ | ||
| 43 | #define LOAD_XML2_FN(lib,func) { \ | ||
| 44 | fn_##func = (void *) GetProcAddress (lib, #func); \ | ||
| 45 | if (!fn_##func) goto bad_library; \ | ||
| 46 | } | ||
| 47 | |||
| 48 | DEF_XML2_FN (htmlDocPtr, htmlReadMemory, | ||
| 49 | (const char *, int, const char *, const char *, int)); | ||
| 50 | DEF_XML2_FN (xmlDocPtr, xmlReadMemory, | ||
| 51 | (const char *, int, const char *, const char *, int)); | ||
| 52 | DEF_XML2_FN (xmlNodePtr, xmlDocGetRootElement, (xmlDocPtr)); | ||
| 53 | DEF_XML2_FN (void, xmlFreeDoc, (xmlDocPtr)); | ||
| 54 | DEF_XML2_FN (void, xmlCleanupParser, (void)); | ||
| 55 | DEF_XML2_FN (void, xmlCheckVersion, (int)); | ||
| 56 | |||
| 57 | static int | ||
| 58 | libxml2_loaded_p (void) | ||
| 59 | { | ||
| 60 | Lisp_Object found = Fassq (Qlibxml2_dll, Vlibrary_cache); | ||
| 61 | |||
| 62 | if (CONSP (found)) | ||
| 63 | return EQ (XCDR (found), Qt) ? 1 : 0; | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | #else /* !WINDOWSNT */ | ||
| 68 | |||
| 69 | #define fn_htmlReadMemory htmlReadMemory | ||
| 70 | #define fn_xmlReadMemory xmlReadMemory | ||
| 71 | #define fn_xmlDocGetRootElement xmlDocGetRootElement | ||
| 72 | #define fn_xmlFreeDoc xmlFreeDoc | ||
| 73 | #define fn_xmlCleanupParser xmlCleanupParser | ||
| 74 | #define fn_xmlCheckVersion xmlCheckVersion | ||
| 75 | |||
| 76 | static inline int | ||
| 77 | libxml2_loaded_p (void) | ||
| 78 | { | ||
| 79 | return 1; | ||
| 80 | } | ||
| 81 | |||
| 82 | #endif /* !WINDOWSNT */ | ||
| 83 | |||
| 84 | static int | ||
| 85 | init_libxml2_functions (Lisp_Object libraries) | ||
| 86 | { | ||
| 87 | #ifdef WINDOWSNT | ||
| 88 | if (libxml2_loaded_p ()) | ||
| 89 | return 1; | ||
| 90 | else | ||
| 91 | { | ||
| 92 | HMODULE library; | ||
| 93 | |||
| 94 | if (!(library = w32_delayed_load (libraries, Qlibxml2_dll))) | ||
| 95 | { | ||
| 96 | message ("%s", "libxml2 library not found"); | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* LOAD_XML2_FN jumps to bad_library if it fails to find the | ||
| 101 | named function. */ | ||
| 102 | LOAD_XML2_FN (library, htmlReadMemory); | ||
| 103 | LOAD_XML2_FN (library, xmlReadMemory); | ||
| 104 | LOAD_XML2_FN (library, xmlDocGetRootElement); | ||
| 105 | LOAD_XML2_FN (library, xmlFreeDoc); | ||
| 106 | LOAD_XML2_FN (library, xmlCleanupParser); | ||
| 107 | LOAD_XML2_FN (library, xmlCheckVersion); | ||
| 108 | |||
| 109 | Vlibrary_cache = Fcons (Fcons (Qlibxml2_dll, Qt), Vlibrary_cache); | ||
| 110 | return 1; | ||
| 111 | } | ||
| 112 | |||
| 113 | bad_library: | ||
| 114 | Vlibrary_cache = Fcons (Fcons (Qlibxml2_dll, Qnil), Vlibrary_cache); | ||
| 115 | |||
| 116 | return 0; | ||
| 117 | #else /* !WINDOWSNT */ | ||
| 118 | return 1; | ||
| 119 | #endif /* !WINDOWSNT */ | ||
| 120 | } | ||
| 121 | |||
| 31 | static Lisp_Object | 122 | static Lisp_Object |
| 32 | make_dom (xmlNode *node) | 123 | make_dom (xmlNode *node) |
| 33 | { | 124 | { |
| @@ -92,7 +183,7 @@ parse_region (Lisp_Object start, Lisp_Object end, Lisp_Object base_url, int html | |||
| 92 | ptrdiff_t bytes; | 183 | ptrdiff_t bytes; |
| 93 | ptrdiff_t istart, iend; | 184 | ptrdiff_t istart, iend; |
| 94 | 185 | ||
| 95 | LIBXML_TEST_VERSION; | 186 | fn_xmlCheckVersion (LIBXML_VERSION); |
| 96 | 187 | ||
| 97 | validate_region (&start, &end); | 188 | validate_region (&start, &end); |
| 98 | 189 | ||
| @@ -111,16 +202,16 @@ parse_region (Lisp_Object start, Lisp_Object end, Lisp_Object base_url, int html | |||
| 111 | bytes = CHAR_TO_BYTE (iend) - CHAR_TO_BYTE (istart); | 202 | bytes = CHAR_TO_BYTE (iend) - CHAR_TO_BYTE (istart); |
| 112 | 203 | ||
| 113 | if (htmlp) | 204 | if (htmlp) |
| 114 | doc = htmlReadMemory ((char *) BYTE_POS_ADDR (CHAR_TO_BYTE (istart)), | 205 | doc = fn_htmlReadMemory ((char *) BYTE_POS_ADDR (CHAR_TO_BYTE (istart)), |
| 115 | bytes, burl, "utf-8", | 206 | bytes, burl, "utf-8", |
| 116 | HTML_PARSE_RECOVER|HTML_PARSE_NONET| | 207 | HTML_PARSE_RECOVER|HTML_PARSE_NONET| |
| 117 | HTML_PARSE_NOWARNING|HTML_PARSE_NOERROR| | 208 | HTML_PARSE_NOWARNING|HTML_PARSE_NOERROR| |
| 118 | HTML_PARSE_NOBLANKS); | 209 | HTML_PARSE_NOBLANKS); |
| 119 | else | 210 | else |
| 120 | doc = xmlReadMemory ((char *) BYTE_POS_ADDR (CHAR_TO_BYTE (istart)), | 211 | doc = fn_xmlReadMemory ((char *) BYTE_POS_ADDR (CHAR_TO_BYTE (istart)), |
| 121 | bytes, burl, "utf-8", | 212 | bytes, burl, "utf-8", |
| 122 | XML_PARSE_NONET|XML_PARSE_NOWARNING| | 213 | XML_PARSE_NONET|XML_PARSE_NOWARNING| |
| 123 | XML_PARSE_NOBLANKS |XML_PARSE_NOERROR); | 214 | XML_PARSE_NOBLANKS |XML_PARSE_NOERROR); |
| 124 | 215 | ||
| 125 | if (doc != NULL) | 216 | if (doc != NULL) |
| 126 | { | 217 | { |
| @@ -139,19 +230,26 @@ parse_region (Lisp_Object start, Lisp_Object end, Lisp_Object base_url, int html | |||
| 139 | if (NILP (result)) { | 230 | if (NILP (result)) { |
| 140 | /* The document isn't just comments, so get the tree the | 231 | /* The document isn't just comments, so get the tree the |
| 141 | proper way. */ | 232 | proper way. */ |
| 142 | xmlNode *node = xmlDocGetRootElement (doc); | 233 | xmlNode *node = fn_xmlDocGetRootElement (doc); |
| 143 | if (node != NULL) | 234 | if (node != NULL) |
| 144 | result = make_dom (node); | 235 | result = make_dom (node); |
| 145 | } else | 236 | } else |
| 146 | result = Fcons (intern ("top"), | 237 | result = Fcons (intern ("top"), |
| 147 | Fcons (Qnil, Fnreverse (Fcons (r, result)))); | 238 | Fcons (Qnil, Fnreverse (Fcons (r, result)))); |
| 148 | 239 | ||
| 149 | xmlFreeDoc (doc); | 240 | fn_xmlFreeDoc (doc); |
| 150 | } | 241 | } |
| 151 | 242 | ||
| 152 | return result; | 243 | return result; |
| 153 | } | 244 | } |
| 154 | 245 | ||
| 246 | void | ||
| 247 | xml_cleanup_parser (void) | ||
| 248 | { | ||
| 249 | if (libxml2_loaded_p ()) | ||
| 250 | fn_xmlCleanupParser (); | ||
| 251 | } | ||
| 252 | |||
| 155 | DEFUN ("libxml-parse-html-region", Flibxml_parse_html_region, | 253 | DEFUN ("libxml-parse-html-region", Flibxml_parse_html_region, |
| 156 | Slibxml_parse_html_region, | 254 | Slibxml_parse_html_region, |
| 157 | 2, 3, 0, | 255 | 2, 3, 0, |
| @@ -159,7 +257,9 @@ DEFUN ("libxml-parse-html-region", Flibxml_parse_html_region, | |||
| 159 | If BASE-URL is non-nil, it is used to expand relative URLs. */) | 257 | If BASE-URL is non-nil, it is used to expand relative URLs. */) |
| 160 | (Lisp_Object start, Lisp_Object end, Lisp_Object base_url) | 258 | (Lisp_Object start, Lisp_Object end, Lisp_Object base_url) |
| 161 | { | 259 | { |
| 162 | return parse_region (start, end, base_url, 1); | 260 | if (init_libxml2_functions (Vdynamic_library_alist)) |
| 261 | return parse_region (start, end, base_url, 1); | ||
| 262 | return Qnil; | ||
| 163 | } | 263 | } |
| 164 | 264 | ||
| 165 | DEFUN ("libxml-parse-xml-region", Flibxml_parse_xml_region, | 265 | DEFUN ("libxml-parse-xml-region", Flibxml_parse_xml_region, |
| @@ -169,7 +269,9 @@ DEFUN ("libxml-parse-xml-region", Flibxml_parse_xml_region, | |||
| 169 | If BASE-URL is non-nil, it is used to expand relative URLs. */) | 269 | If BASE-URL is non-nil, it is used to expand relative URLs. */) |
| 170 | (Lisp_Object start, Lisp_Object end, Lisp_Object base_url) | 270 | (Lisp_Object start, Lisp_Object end, Lisp_Object base_url) |
| 171 | { | 271 | { |
| 172 | return parse_region (start, end, base_url, 0); | 272 | if (init_libxml2_functions (Vdynamic_library_alist)) |
| 273 | return parse_region (start, end, base_url, 0); | ||
| 274 | return Qnil; | ||
| 173 | } | 275 | } |
| 174 | 276 | ||
| 175 | 277 | ||
| @@ -181,6 +283,8 @@ syms_of_xml (void) | |||
| 181 | { | 283 | { |
| 182 | defsubr (&Slibxml_parse_html_region); | 284 | defsubr (&Slibxml_parse_html_region); |
| 183 | defsubr (&Slibxml_parse_xml_region); | 285 | defsubr (&Slibxml_parse_xml_region); |
| 286 | |||
| 287 | DEFSYM (Qlibxml2_dll, "libxml2"); | ||
| 184 | } | 288 | } |
| 185 | 289 | ||
| 186 | #endif /* HAVE_LIBXML2 */ | 290 | #endif /* HAVE_LIBXML2 */ |