ext/xml/ruby_xml_parser.c in libxml-ruby-0.3.6 vs ext/xml/ruby_xml_parser.c in libxml-ruby-0.3.8

- old
+ new

@@ -1,11 +1,14 @@ -/* $Id: ruby_xml_parser.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */ +/* $Id: ruby_xml_parser.c,v 1.3 2006/03/27 20:49:19 roscopeco Exp $ */ /* Please see the LICENSE file for copyright and distribution information */ #include "libxml.h" +static VALUE libxml_xmlRubyErrorProc = Qnil; +static int id_call; + int ruby_xml_parser_count = 0; VALUE cXMLParser; VALUE eXMLParserParseError; static int @@ -216,11 +219,11 @@ } /* * call-seq: - * XML::Parser.enabled_catalog? => (true|false) + * XML::Parser.enabled_regexp? => (true|false) * * Determine whether libxml regular expression support is enabled. */ VALUE ruby_xml_parser_enabled_regexp_q(VALUE class) { @@ -265,11 +268,11 @@ } /* * call-seq: - * XML::Parser.enabled_catalog? => (true|false) + * XML::Parser.enabled_unicode? => (true|false) * * Determine whether libxml unicode support is enabled. */ VALUE ruby_xml_parser_enabled_unicode_q(VALUE class) { @@ -281,11 +284,11 @@ } /* * call-seq: - * XML::Parser.enabled_catalog? => (true|false) + * XML::Parser.enabled_xinclude? => (true|false) * * Determine whether libxml xinclude support is enabled. */ VALUE ruby_xml_parser_enabled_xinclude_q(VALUE class) { @@ -297,11 +300,11 @@ } /* * call-seq: - * XML::Parser.enabled_catalog? => (true|false) + * XML::Parser.enabled_xpath? => (true|false) * * Determine whether libxml xpath support is enabled. */ VALUE ruby_xml_parser_enabled_xpath_q(VALUE class) { @@ -313,11 +316,11 @@ } /* * call-seq: - * XML::Parser.enabled_catalog? => (true|false) + * XML::Parser.enabled_xpointer? => (true|false) * * Determine whether libxml xpointer support is enabled. */ VALUE ruby_xml_parser_enabled_xpointer_q(VALUE class) { @@ -329,11 +332,11 @@ } /* * call-seq: - * XML::Parser.enabled_catalog? => (true|false) + * XML::Parser.enabled_zlib? => (true|false) * * Determine whether libxml zlib support is enabled. */ VALUE ruby_xml_parser_enabled_zlib_q(VALUE class) { @@ -1214,11 +1217,57 @@ rxpc->ctxt = xmlCreateMemoryParserCtxt(StringValuePtr(data->str), RSTRING(data->str)->len); return(data->str); } +/* + * call-seq: + * XML::Parser.register_error_handler(lambda { |msg| ... }) => old_handler + * XML::Parser.register_error_handler(nil) => old_handler + * + * Register the attached block as the handler for parser errors. + * A message describing parse errors is passed to the block. + * Libxml passes error messages to the handler in parts, one per call. + * A typical error results in six calls to this proc, with arguments: + * + * "Entity: line 1: ", + * "parser ", + * "error : ", + * "Opening and ending tag mismatch: foo line 1 and foz\n", + * "<foo><bar/></foz>\n", + * " ^\n" + * + * Note that the error handler is shared by all threads. + */ +VALUE +ruby_xml_parser_registerErrorHandler(VALUE self, VALUE proc) { + VALUE old_block = libxml_xmlRubyErrorProc; + libxml_xmlRubyErrorProc = proc; + return(old_block); +} +static void +libxml_xmlErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, const char *msg, ...) +{ + va_list ap; + char str[1000]; + VALUE rstr; + + if (libxml_xmlRubyErrorProc == Qnil) { + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + } else { + va_start(ap, msg); + if (vsnprintf(str, 999, msg, ap) >= 998) str[999] = 0; + va_end(ap); + + rstr = rb_str_new2(str); + rb_funcall2(libxml_xmlRubyErrorProc, id_call, 1, &rstr); + } +} + /* #define RUBY_XML_PARSER_ENABLED_INIT(func, method) \ rb_define_singleton_method(cXMLParser, method, \ ruby_xml_parser_enabled_##func##_q, 0); */ ///#include "cbg.c" @@ -1349,15 +1398,20 @@ ruby_xml_parser_memory_dump, 0); rb_define_singleton_method(cXMLParser, "memory_used", ruby_xml_parser_memory_used, 0); rb_define_singleton_method(cXMLParser, "new", ruby_xml_parser_new, 0); rb_define_singleton_method(cXMLParser, "string", ruby_xml_parser_new_string, 1); - + rb_define_singleton_method(cXMLParser, "register_error_handler", ruby_xml_parser_registerErrorHandler, 1); rb_define_method(cXMLParser, "filename", ruby_xml_parser_filename_get, 0); rb_define_method(cXMLParser, "filename=", ruby_xml_parser_filename_set, 1); rb_define_method(cXMLParser, "io", ruby_xml_parser_io_get, 0); rb_define_method(cXMLParser, "io=", ruby_xml_parser_io_set, 1); rb_define_method(cXMLParser, "parse", ruby_xml_parser_parse, 0); rb_define_method(cXMLParser, "parser_context", ruby_xml_parser_parser_context_get, 0); rb_define_method(cXMLParser, "string", ruby_xml_parser_str_get, 0); rb_define_method(cXMLParser, "string=", ruby_xml_parser_str_set, 1); + + // set up error handling + xmlSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler); + xmlThrDefSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler); + id_call = rb_intern("call"); }