aboutsummaryrefslogtreecommitdiff
path: root/gamma/gamma-expat.c
diff options
context:
space:
mode:
Diffstat (limited to 'gamma/gamma-expat.c')
-rw-r--r--gamma/gamma-expat.c1004
1 files changed, 1004 insertions, 0 deletions
diff --git a/gamma/gamma-expat.c b/gamma/gamma-expat.c
new file mode 100644
index 0000000..cd3efaa
--- /dev/null
+++ b/gamma/gamma-expat.c
@@ -0,0 +1,1004 @@
+/* This file is part of Gamma.
+ Copyright (C) 2010, 2015 Sergey Poznyakoff
+
+ Gamma is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Gamma is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Gamma. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "gamma-expat.h"
+
+
+static long gamma_xml_parser_tag;
+
+struct gamma_xml_parser
+{
+ XML_Parser parser;
+};
+
+#define gamma_scm_is_xml_parser(s) \
+ (!SCM_IMP(s) && SCM_CELL_TYPE(s) == gamma_xml_parser_tag)
+
+static SCM
+gamma_xml_parser_create(XML_Parser parser)
+{
+ struct gamma_xml_parser *gp;
+
+ gp = scm_gc_malloc(sizeof (*gp), "xml_parser");
+ gp->parser = parser;
+ SCM_RETURN_NEWSMOB(gamma_xml_parser_tag, gp);
+}
+
+#define GAMMA_XML_PARSER_PTR(smob) \
+ ((struct gamma_xml_parser *)SCM_CDR(smob))
+
+static size_t
+gamma_xml_parser_free(SCM smob)
+{
+ struct gamma_xml_parser *gp = GAMMA_XML_PARSER_PTR(smob);
+ if (gp->parser) {
+ struct gamma_expat_user_data *udata =
+ XML_GetUserData(gp->parser);
+ free(udata);
+ XML_ParserFree(gp->parser);
+ }
+ free(gp);
+ return 0;
+}
+
+static SCM
+gamma_xml_parser_mark(SCM smob)
+{
+ struct gamma_xml_parser *gp = GAMMA_XML_PARSER_PTR(smob);
+ struct gamma_expat_user_data *udata;
+ int i;
+
+ if (!gp->parser)
+ return SCM_BOOL_F;
+ udata = XML_GetUserData(gp->parser);
+ for (i = 0; i < gamma_expat_handler_count; i++) {
+ if (!SCM_UNBNDP(udata->handler[i]))
+ scm_gc_mark(udata->handler[i]);
+ }
+ if (!SCM_UNBNDP(udata->external_entity_ref_handler_arg))
+ scm_gc_mark(udata->external_entity_ref_handler_arg);
+ return SCM_BOOL_F;
+}
+
+static int
+gamma_xml_parser_print(SCM smob, SCM port, scm_print_state *pstate)
+{
+/* struct gamma_xml_parser *gp = GAMMA_XML_PARSER_PTR(smob);*/
+
+ scm_puts("#<XML_Parser>", port);
+ /* FIXME: show more details */
+ return 1;
+}
+
+static void
+gamma_xml_parser_init(void)
+{
+ gamma_xml_parser_tag =
+ scm_make_smob_type("XML_Parser",
+ sizeof(struct gamma_xml_parser));
+ scm_set_smob_mark(gamma_xml_parser_tag, gamma_xml_parser_mark);
+ scm_set_smob_free(gamma_xml_parser_tag, gamma_xml_parser_free);
+ scm_set_smob_print(gamma_xml_parser_tag, gamma_xml_parser_print);
+}
+
+
+static struct gamma_expat_user_data *
+make_user_data(void)
+{
+ int i;
+
+ struct gamma_expat_user_data *p = scm_malloc(sizeof (*p));
+ for (i = 0; i < gamma_expat_handler_count; i++)
+ p->handler[i] = SCM_UNSPECIFIED;
+ p->external_entity_ref_handler_arg = SCM_UNSPECIFIED;
+ return p;
+}
+
+SCM_GLOBAL_SYMBOL(gamma_xml_error, "gamma-xml-error");
+
+SCM_DEFINE_PUBLIC(scm_xml_expat_version_string, "xml-expat-version-string",
+ 0, 0, 0,
+ (),
+ "Return the version of the expat library as a string.")
+{
+ return scm_from_locale_string(XML_ExpatVersion());
+}
+
+SCM_DEFINE_PUBLIC(scm_xml_expat_version, "xml-expat-version", 0, 0, 0,
+ (),
+ "Return expat library version information.")
+{
+ XML_Expat_Version vinfo = XML_ExpatVersionInfo();
+ return scm_list_3(scm_from_int(vinfo.major),
+ scm_from_int(vinfo.minor),
+ scm_from_int(vinfo.micro));
+}
+
+SCM_DEFINE_PUBLIC(scm_xml_primitive_make_parser, "xml-primitive-make-parser",
+ 0, 2, 0,
+ (SCM enc, SCM sep),
+"Return a new parser. If @var{enc} is given, it must be one of: "
+"@samp{US-ASCII}, @samp{UTF-8}, @samp{UTF-16}, @samp{ISO-8859-1}. If @var{sep} "
+"is given, the returned parser has namespace processing in effect. "
+"In that case, @var{sep} is a character which is used as a "
+"separator between the namespace @acronym{URI} and the local part "
+"of the name in returned namespace element and attribute names.")
+#define FUNC_NAME s_scm_xml_primitive_make_parser
+{
+ XML_Char *encoding = NULL;
+ XML_Char separator = 0;
+ XML_Parser parser;
+
+ if (!SCM_UNBNDP(enc)) {
+ SCM_VALIDATE_STRING(1, enc);
+ encoding = scm_to_locale_string(enc);
+ }
+ if (!SCM_UNBNDP(sep)) {
+ SCM_VALIDATE_CHAR(2, sep);
+ separator = SCM_CHAR(sep);
+ parser = XML_ParserCreateNS(encoding, separator);
+ } else
+ parser = XML_ParserCreate(encoding);
+ if (!parser)
+ scm_report_out_of_memory();
+ XML_SetUserData(parser, make_user_data());
+ free(encoding);
+ return gamma_xml_parser_create(parser);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE_PUBLIC(scm_xml_set_encoding, "xml-set-encoding", 2, 0, 0,
+ (SCM parser, SCM enc),
+ "Set the encoding to be used by the @var{parser}.")
+#define FUNC_NAME s_scm_xml_set_encoding
+{
+ struct gamma_xml_parser *gp;
+ char *encoding;
+ enum XML_Status status;
+
+ SCM_ASSERT(gamma_scm_is_xml_parser(parser), parser,
+ SCM_ARG1, FUNC_NAME);
+ SCM_VALIDATE_STRING(2, enc);
+
+ gp = GAMMA_XML_PARSER_PTR(parser);
+ encoding = scm_to_locale_string(enc);
+ status = XML_SetEncoding(gp->parser, encoding);
+ free(encoding);
+ if (status == XML_STATUS_ERROR) {
+ enum XML_Error error = XML_GetErrorCode(gp->parser);
+ scm_error(gamma_xml_error, FUNC_NAME,
+ "~A",
+ scm_list_1(scm_from_locale_string(XML_ErrorString(error))),
+ SCM_BOOL_F);
+ }
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE_PUBLIC(scm_xml_primitive_parse, "xml-primitive-parse", 3, 0, 0,
+ (SCM parser, SCM input, SCM isfinal),
+ "Parse next piece of input")
+#define FUNC_NAME s_scm_xml_primitive_parse
+{
+ struct gamma_xml_parser *gp;
+ char *str;
+ enum XML_Status status;
+
+ SCM_ASSERT(gamma_scm_is_xml_parser(parser), parser,
+ SCM_ARG1, FUNC_NAME);
+ SCM_VALIDATE_STRING(2, input);
+ SCM_VALIDATE_BOOL(3, isfinal);
+
+ gp = GAMMA_XML_PARSER_PTR(parser);
+ str = scm_to_locale_string(input);
+ status = XML_Parse(gp->parser, str, strlen(str),
+ isfinal == SCM_BOOL_T);
+ free(str);
+ if (status == XML_STATUS_ERROR) {
+ enum XML_Error error = XML_GetErrorCode(gp->parser);
+ int line = XML_GetCurrentLineNumber(gp->parser);
+ int column = XML_GetCurrentColumnNumber(gp->parser);
+ int offset, size;
+ const char *bufptr;
+
+ bufptr = XML_GetInputContext(gp->parser, &offset, &size);
+ scm_error(gamma_xml_error, FUNC_NAME,
+ "~A near line ~A",
+ scm_list_2(scm_from_locale_string(XML_ErrorString(error)),
+ scm_from_int(line)),
+ bufptr ?
+ scm_list_5(scm_from_int(error),
+ scm_from_int(line),
+ scm_from_int(column),
+ scm_from_locale_stringn(bufptr, size),
+ scm_from_int(offset)) :
+ scm_list_3(scm_from_int(error),
+ scm_from_int(line),
+ scm_from_int(column)));
+ }
+ return SCM_UNSPECIFIED;
+
+}
+#undef FUNC_NAME
+
+SCM_DEFINE_PUBLIC(scm_xml_default_current, "xml-default-current", 1, 0, 0,
+ (SCM parser),
+"Pass current markup to the default handler.")
+#define FUNC_NAME s_scm_xml_default_current
+{
+ struct gamma_xml_parser *gp;
+
+ SCM_ASSERT(gamma_scm_is_xml_parser(parser), parser,
+ SCM_ARG1, FUNC_NAME);
+ gp = GAMMA_XML_PARSER_PTR(parser);
+ XML_DefaultCurrent(gp->parser);
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE_PUBLIC(scm_xml_error_string, "xml-error-string", 1, 0, 0,
+ (SCM code),
+"Return a textual description of the error @code{code}.")
+#define FUNC_NAME s_scm_xml_error_string
+{
+ const char *p;
+ SCM_ASSERT(scm_is_integer(code), code, SCM_ARG1, FUNC_NAME);
+ p = XML_ErrorString(scm_to_int(code));
+ return scm_from_locale_string(p);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE_PUBLIC(scm_xml_current_line_number, "xml-current-line-number",
+ 1, 0, 0,
+ (SCM parser),
+"Return current line number in the input stream. "
+"The first line is reported as 1.")
+#define FUNC_NAME s_scm_xml_current_line_number
+{
+ struct gamma_xml_parser *gp;
+
+ SCM_ASSERT(gamma_scm_is_xml_parser(parser), parser,
+ SCM_ARG1, FUNC_NAME);
+ gp = GAMMA_XML_PARSER_PTR(parser);
+ return scm_from_int(XML_GetCurrentLineNumber(gp->parser));
+}
+#undef FUNC_NAME
+
+SCM_DEFINE_PUBLIC(scm_xml_current_column_number, "xml-current-column-number",
+ 1, 0, 0,
+ (SCM parser),
+"Return current column number in the input stream. "
+"The first column is reported as 0.")
+#define FUNC_NAME s_scm_xml_current_column_number
+{
+ struct gamma_xml_parser *gp;
+
+ SCM_ASSERT(gamma_scm_is_xml_parser(parser), parser,
+ SCM_ARG1, FUNC_NAME);
+ gp = GAMMA_XML_PARSER_PTR(parser);
+ return scm_from_int(XML_GetCurrentColumnNumber(gp->parser));
+}
+#undef FUNC_NAME
+
+SCM_DEFINE_PUBLIC(scm_xml_current_byte_count, "xml-current-byte-count",
+ 1, 0, 0,
+ (SCM parser),
+"Return the number of bytes in the current event. "
+"Returns 0 if the event is inside a reference to an internal "
+"entity and for the end-tag event for empty element tags "
+"(the later can be used to distinguish empty-element tags "
+"from empty elements using separate start and end tags).")
+#define FUNC_NAME s_scm_xml_current_byte_count
+{
+ struct gamma_xml_parser *gp;
+
+ SCM_ASSERT(gamma_scm_is_xml_parser(parser), parser,
+ SCM_ARG1, FUNC_NAME);
+ gp = GAMMA_XML_PARSER_PTR(parser);
+ return scm_from_int(XML_GetCurrentByteCount(gp->parser));
+}
+#undef FUNC_NAME
+
+
+
+static SCM
+attrs_to_scm(const XML_Char **attr)
+{
+ int i;
+ SCM scm_first = SCM_EOL, scm_last = SCM_EOL;
+
+ for (i = 0; attr[i]; i += 2) {
+ SCM new = scm_cons(scm_cons(scm_from_locale_string(attr[i]),
+ scm_from_locale_string(attr[i + 1])),
+ SCM_EOL);
+ if (scm_first == SCM_EOL)
+ scm_last = scm_first = new;
+ else {
+ SCM_SETCDR(scm_last, new);
+ scm_last = new;
+ }
+ }
+ return scm_first;
+}
+
+struct apply_data {
+ SCM proc;
+ SCM arg;
+};
+
+SCM
+gamma_apply_catch_body(void *data)
+{
+ struct apply_data *xp = data;
+ return scm_apply_0(xp->proc, xp->arg);
+}
+
+typedef void (*generic_handler_setter_t) (XML_Parser);
+
+
+static void XMLCALL
+generic_start_handler(void *user_data, const XML_Char *name,
+ const XML_Char **attrs)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[start_element_handler];
+ xdata.arg = scm_list_2(scm_from_locale_string(name),
+ attrs_to_scm(attrs));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_start_element_handler(XML_Parser parser)
+{
+ XML_SetStartElementHandler(parser, generic_start_handler);
+}
+
+static void XMLCALL
+generic_end_handler(void *user_data, const XML_Char *name)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[end_element_handler];
+ xdata.arg = scm_list_1(scm_from_locale_string(name));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_end_element_handler(XML_Parser parser)
+{
+ XML_SetEndElementHandler(parser, generic_end_handler);
+}
+
+static void XMLCALL
+data_chunk_handler(SCM proc, const XML_Char *chunk, int len)
+{
+ struct apply_data xdata;
+ xdata.proc = proc;
+ xdata.arg = scm_list_1(scm_from_locale_stringn(chunk, len));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void XMLCALL
+generic_character_data_handler(void *user_data, const XML_Char *chunk,
+ int len)
+{
+ struct gamma_expat_user_data *udata = user_data;
+ data_chunk_handler(udata->handler[character_data_handler],
+ chunk, len);
+}
+
+static void
+set_generic_character_data_handler(XML_Parser parser)
+{
+ XML_SetCharacterDataHandler(parser, generic_character_data_handler);
+}
+
+static void XMLCALL
+generic_processing_instruction_handler(void *user_data,
+ const XML_Char *target,
+ const XML_Char *data)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[processing_instruction_handler];
+ xdata.arg = scm_list_2(scm_from_locale_string(target),
+ scm_from_locale_string(data));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_processing_instruction_handler(XML_Parser parser)
+{
+ XML_SetProcessingInstructionHandler(parser,
+ generic_processing_instruction_handler);
+}
+
+static void XMLCALL
+generic_comment_handler(void *user_data, const XML_Char *data)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[comment_handler];
+ xdata.arg = scm_list_1(scm_from_locale_string(data));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_comment_handler(XML_Parser parser)
+{
+ XML_SetCommentHandler(parser, generic_comment_handler);
+}
+
+static void XMLCALL
+generic_start_cdata_section_handler(void *user_data)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[start_cdata_section_handler];
+ xdata.arg = SCM_EOL;
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_start_cdata_section_handler(XML_Parser parser)
+{
+ XML_SetStartCdataSectionHandler(parser,
+ generic_start_cdata_section_handler);
+}
+
+static void XMLCALL
+generic_end_cdata_section_handler(void *user_data)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[end_cdata_section_handler];
+ xdata.arg = SCM_EOL;
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_end_cdata_section_handler(XML_Parser parser)
+{
+ XML_SetEndCdataSectionHandler(parser,
+ generic_end_cdata_section_handler);
+}
+
+static void XMLCALL
+generic_default_handler(void *user_data, const XML_Char *chunk,
+ int len)
+{
+ struct gamma_expat_user_data *udata = user_data;
+ data_chunk_handler(udata->handler[default_handler], chunk, len);
+}
+
+static void
+set_generic_default_handler(XML_Parser parser)
+{
+ XML_SetDefaultHandler(parser, generic_default_handler);
+}
+
+static void XMLCALL
+generic_default_handler_expand(void *user_data, const XML_Char *chunk,
+ int len)
+{
+ struct gamma_expat_user_data *udata = user_data;
+ data_chunk_handler(udata->handler[default_handler_expand], chunk, len);
+}
+
+static void
+set_generic_default_handler_expand(XML_Parser parser)
+{
+ XML_SetDefaultHandlerExpand(parser, generic_default_handler_expand);
+}
+
+static void XMLCALL
+generic_unparsed_entity_decl_handler(void *user_data,
+ const XML_Char *entity_name,
+ const XML_Char *base,
+ const XML_Char *system_id,
+ const XML_Char *public_id,
+ const XML_Char *notation_name)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[unparsed_entity_decl_handler];
+ xdata.arg = scm_list_5(scm_from_locale_string(entity_name),
+ scm_from_locale_string(base),
+ scm_from_locale_string(system_id),
+ scm_from_locale_string(public_id),
+ scm_from_locale_string(notation_name));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_unparsed_entity_decl_handler(XML_Parser parser)
+{
+ XML_SetUnparsedEntityDeclHandler(parser,
+ generic_unparsed_entity_decl_handler);
+}
+
+static void XMLCALL
+generic_notation_decl_handler(void *user_data,
+ const XML_Char *notation_name,
+ const XML_Char *base,
+ const XML_Char *system_id,
+ const XML_Char *public_id)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[notation_decl_handler];
+ xdata.arg = scm_list_4(scm_from_locale_string(notation_name),
+ scm_from_locale_string(base),
+ scm_from_locale_string(system_id),
+ scm_from_locale_string(public_id));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_notation_decl_handler(XML_Parser parser)
+{
+ XML_SetNotationDeclHandler(parser,
+ generic_notation_decl_handler);
+}
+
+static void XMLCALL
+generic_start_namespace_decl_handler(void *user_data,
+ const XML_Char *prefix,
+ const XML_Char *uri)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[start_namespace_decl_handler];
+ xdata.arg = scm_list_2(scm_from_locale_string(prefix),
+ scm_from_locale_string(uri));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_start_namespace_decl_handler(XML_Parser parser)
+{
+ XML_SetStartNamespaceDeclHandler(parser,
+ generic_start_namespace_decl_handler);
+}
+
+static void XMLCALL
+generic_end_namespace_decl_handler(void *user_data,
+ const XML_Char *prefix)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[end_namespace_decl_handler];
+ xdata.arg = scm_list_1(scm_from_locale_string(prefix));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_end_namespace_decl_handler(XML_Parser parser)
+{
+ XML_SetEndNamespaceDeclHandler(parser,
+ generic_end_namespace_decl_handler);
+}
+
+
+static void XMLCALL
+generic_skipped_entity_handler(void *user_data,
+ const XML_Char *entity_name,
+ int is_parameter_entity)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[skipped_entity_handler];
+ xdata.arg = scm_list_2(scm_from_locale_string(entity_name),
+ is_parameter_entity ? SCM_BOOL_T : SCM_BOOL_F);
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_skipped_entity_handler(XML_Parser parser)
+{
+ XML_SetSkippedEntityHandler(parser, generic_skipped_entity_handler);
+}
+
+
+static int XMLCALL
+generic_not_standalone_handler(void *user_data)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[not_standalone_handler];
+ xdata.arg = SCM_EOL;
+ /* FIXME: Result? */
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+ return 0;
+}
+
+static void
+set_generic_not_standalone_handler(XML_Parser parser)
+{
+ XML_SetNotStandaloneHandler(parser,
+ generic_not_standalone_handler);
+}
+
+static void XMLCALL
+generic_xml_decl_handler(void *user_data,
+ const XML_Char *version,
+ const XML_Char *encoding,
+ int standalone)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[xml_decl_handler];
+ xdata.arg = scm_list_3(version ?
+ scm_from_locale_string(version) : SCM_BOOL_F,
+ encoding ?
+ scm_from_locale_string(encoding) : SCM_BOOL_F,
+ standalone == -1 ?
+ SCM_UNSPECIFIED :
+ scm_list_1 (standalone ?
+ SCM_BOOL_T : SCM_BOOL_F));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_xml_decl_handler(XML_Parser parser)
+{
+ XML_SetXmlDeclHandler(parser, generic_xml_decl_handler);
+}
+
+static void XMLCALL
+generic_start_doctype_decl_handler(void *user_data,
+ const XML_Char *doctype_name,
+ const XML_Char *sysid,
+ const XML_Char *pubid,
+ int has_internal_subset)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[start_doctype_decl_handler];
+ xdata.arg = scm_list_4(scm_from_locale_string(doctype_name),
+ sysid ? scm_from_locale_string(sysid) :
+ SCM_BOOL_F,
+ pubid ? scm_from_locale_string(pubid) :
+ SCM_BOOL_F,
+ (has_internal_subset ? SCM_BOOL_T : SCM_BOOL_F));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_start_doctype_decl_handler(XML_Parser parser)
+{
+ XML_SetStartDoctypeDeclHandler(parser,
+ generic_start_doctype_decl_handler);
+}
+
+static void XMLCALL
+generic_end_doctype_decl_handler(void *user_data)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[end_doctype_decl_handler];
+ xdata.arg = SCM_EOL;
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_end_doctype_decl_handler(XML_Parser parser)
+{
+ XML_SetEndDoctypeDeclHandler(parser,
+ generic_end_doctype_decl_handler);
+}
+
+static void XMLCALL
+generic_attlist_decl_handler(void *user_data,
+ const XML_Char *elname,
+ const XML_Char *attname,
+ const XML_Char *att_type,
+ const XML_Char *dflt,
+ int isrequired)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[attlist_decl_handler];
+ xdata.arg = scm_list_4(scm_from_locale_string(elname),
+ scm_from_locale_string(attname),
+ scm_from_locale_string(att_type),
+ dflt ? scm_from_locale_string(dflt) :
+ (isrequired ? SCM_BOOL_T : SCM_BOOL_F));
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_attlist_decl_handler(XML_Parser parser)
+{
+ XML_SetAttlistDeclHandler(parser,
+ generic_attlist_decl_handler);
+}
+
+static void XMLCALL
+generic_entity_decl_handler(void *user_data,
+ const XML_Char *entity_name,
+ int is_parameter_entity,
+ const XML_Char *value,
+ int value_length,
+ const XML_Char *base,
+ const XML_Char *system_id,
+ const XML_Char *public_id,
+ const XML_Char *notation_name)
+{
+ struct apply_data xdata;
+ struct gamma_expat_user_data *udata = user_data;
+
+ xdata.proc = udata->handler[attlist_decl_handler];
+ xdata.arg = scm_list_n(scm_from_locale_string(entity_name),
+ is_parameter_entity ? SCM_BOOL_T : SCM_BOOL_F,
+ value ? scm_from_locale_stringn(value,
+ value_length) :
+ SCM_BOOL_F,
+ scm_from_locale_string(base),
+ scm_from_locale_string(system_id),
+ scm_from_locale_string(public_id),
+ notation_name ?
+ scm_from_locale_string(notation_name) :
+ SCM_BOOL_F,
+ SCM_UNDEFINED);
+ gamma_safe_exec(gamma_apply_catch_body, &xdata, NULL);
+}
+
+static void
+set_generic_entity_decl_handler(XML_Parser parser)
+{
+ XML_SetEntityDeclHandler(parser, generic_entity_decl_handler);
+}
+
+static void
+FIXME_set_handler(XML_Parser parser)
+{
+ scm_misc_error (NULL, "handler not implemented yet", SCM_EOL);
+}
+
+
+
+struct set_handler_def {
+ char *name;
+ SCM key;
+ generic_handler_setter_t setter;
+};
+
+struct set_handler_def handler_setter_tab[gamma_expat_handler_count+1] = {
+ { "start-element-handler",
+ SCM_EOL,
+ set_generic_start_element_handler },
+ { "end-element-handler",
+ SCM_EOL,
+ set_generic_end_element_handler },
+ { "character-data-handler",
+ SCM_EOL,
+ set_generic_character_data_handler },
+ { "processing-instruction-handler",
+ SCM_EOL,
+ set_generic_processing_instruction_handler },
+ { "comment-handler",
+ SCM_EOL,
+ set_generic_comment_handler },
+ { "start-cdata-section-handler",
+ SCM_EOL,
+ set_generic_start_cdata_section_handler },
+ { "end-cdata-section-handler",
+ SCM_EOL,
+ set_generic_end_cdata_section_handler },
+ { "default-handler",
+ SCM_EOL,
+ set_generic_default_handler },
+ { "default-handler-expand",
+ SCM_EOL,
+ set_generic_default_handler_expand },
+ { "external-entity-ref-handler",
+ SCM_EOL,
+ FIXME_set_handler },
+ { "skipped-entity-handler",
+ SCM_EOL,
+ set_generic_skipped_entity_handler },
+ { "unknown-encoding-handler",
+ SCM_EOL,
+ FIXME_set_handler },
+ { "start-namespace-decl-handler",
+ SCM_EOL,
+ set_generic_start_namespace_decl_handler },
+ { "end-namespace-decl-handler",
+ SCM_EOL,
+ set_generic_end_namespace_decl_handler },
+ { "xml-decl-handler",
+ SCM_EOL,
+ set_generic_xml_decl_handler },
+ { "start-doctype-decl-handler",
+ SCM_EOL,
+ set_generic_start_doctype_decl_handler },
+ { "end-doctype-decl-handler",
+ SCM_EOL,
+ set_generic_end_doctype_decl_handler },
+ { "element-decl-handler",
+ SCM_EOL,
+ FIXME_set_handler },
+ { "attlist-decl-handler",
+ SCM_EOL,
+ set_generic_attlist_decl_handler },
+ { "entity-decl-handler",
+ SCM_EOL,
+ set_generic_entity_decl_handler },
+ { "unparsed-entity-decl-handler",
+ SCM_EOL,
+ set_generic_unparsed_entity_decl_handler },
+ { "notation-decl-handler",
+ SCM_EOL,
+ set_generic_notation_decl_handler },
+ { "not-standalone-handler",
+ SCM_EOL,
+ set_generic_not_standalone_handler },
+ { NULL }
+};
+
+static void
+init_generic_handler_setter()
+{
+ struct set_handler_def *p;
+
+ for (p = handler_setter_tab; p->name; p++)
+ p->key = scm_permanent_object(scm_from_locale_keyword(p->name));
+}
+
+
+static int
+find_generic_handler_setter(SCM key)
+{
+ int i;
+
+ for (i = 0; handler_setter_tab[i].name; i++)
+ if (handler_setter_tab[i].key == key)
+ return i;
+ return -1;
+}
+
+SCM_DEFINE_PUBLIC(scm_xml_primitive_set_handler, "xml-primitive-set-handler",
+ 3, 0, 0,
+ (SCM parser, SCM key, SCM handler),
+"Set XML callback handler for event @code{key} in parser @var{parser} "
+"to @var{handler}.")
+#define FUNC_NAME s_scm_xml_primitive_set_handler
+{
+ struct gamma_xml_parser *gp;
+ struct gamma_expat_user_data *udata;
+ int sn;
+
+ SCM_ASSERT(gamma_scm_is_xml_parser(parser), parser,
+ SCM_ARG1, FUNC_NAME);
+ SCM_ASSERT(scm_is_keyword(key), key, SCM_ARG2, FUNC_NAME);
+ SCM_VALIDATE_PROC(3, handler);
+
+ sn = find_generic_handler_setter (key);
+ if (sn == -1)
+ scm_out_of_range(FUNC_NAME, key);
+
+ gp = GAMMA_XML_PARSER_PTR(parser);
+ udata = XML_GetUserData(gp->parser);
+ udata->handler[sn] = handler;
+ handler_setter_tab[sn].setter(gp->parser);
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+
+
+
+struct gamma_int_trans {
+ int val;
+ const char *name;
+};
+
+static struct gamma_int_trans expat_code_tab[] = {
+#define GAMMA_CONST(s) { s, #s }
+ /* XML_Status */
+ GAMMA_CONST(XML_STATUS_ERROR),
+ GAMMA_CONST(XML_STATUS_OK),
+ GAMMA_CONST(XML_STATUS_SUSPENDED),
+ /* XML_Error */
+ GAMMA_CONST(XML_ERROR_NONE),
+ GAMMA_CONST(XML_ERROR_NO_MEMORY),
+ GAMMA_CONST(XML_ERROR_SYNTAX),
+ GAMMA_CONST(XML_ERROR_NO_ELEMENTS),
+ GAMMA_CONST(XML_ERROR_INVALID_TOKEN),
+ GAMMA_CONST(XML_ERROR_UNCLOSED_TOKEN),
+ GAMMA_CONST(XML_ERROR_PARTIAL_CHAR),
+ GAMMA_CONST(XML_ERROR_TAG_MISMATCH),
+ GAMMA_CONST(XML_ERROR_DUPLICATE_ATTRIBUTE),
+ GAMMA_CONST(XML_ERROR_JUNK_AFTER_DOC_ELEMENT),
+ GAMMA_CONST(XML_ERROR_PARAM_ENTITY_REF),
+ GAMMA_CONST(XML_ERROR_UNDEFINED_ENTITY),
+ GAMMA_CONST(XML_ERROR_RECURSIVE_ENTITY_REF),
+ GAMMA_CONST(XML_ERROR_ASYNC_ENTITY),
+ GAMMA_CONST(XML_ERROR_BAD_CHAR_REF),
+ GAMMA_CONST(XML_ERROR_BINARY_ENTITY_REF),
+ GAMMA_CONST(XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF),
+ GAMMA_CONST(XML_ERROR_MISPLACED_XML_PI),
+ GAMMA_CONST(XML_ERROR_UNKNOWN_ENCODING),
+ GAMMA_CONST(XML_ERROR_INCORRECT_ENCODING),
+ GAMMA_CONST(XML_ERROR_UNCLOSED_CDATA_SECTION),
+ GAMMA_CONST(XML_ERROR_EXTERNAL_ENTITY_HANDLING),
+ GAMMA_CONST(XML_ERROR_NOT_STANDALONE),
+ GAMMA_CONST(XML_ERROR_UNEXPECTED_STATE),
+ GAMMA_CONST(XML_ERROR_ENTITY_DECLARED_IN_PE),
+ GAMMA_CONST(XML_ERROR_FEATURE_REQUIRES_XML_DTD),
+ GAMMA_CONST(XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING),
+ GAMMA_CONST(XML_ERROR_UNBOUND_PREFIX),
+ GAMMA_CONST(XML_ERROR_UNDECLARING_PREFIX),
+ GAMMA_CONST(XML_ERROR_INCOMPLETE_PE),
+ GAMMA_CONST(XML_ERROR_XML_DECL),
+ GAMMA_CONST(XML_ERROR_TEXT_DECL),
+ GAMMA_CONST(XML_ERROR_PUBLICID),
+ GAMMA_CONST(XML_ERROR_SUSPENDED),
+ GAMMA_CONST(XML_ERROR_NOT_SUSPENDED),
+ GAMMA_CONST(XML_ERROR_ABORTED),
+ GAMMA_CONST(XML_ERROR_FINISHED),
+ GAMMA_CONST(XML_ERROR_SUSPEND_PE),
+ /* XML_Content_Type */
+ GAMMA_CONST(XML_CTYPE_EMPTY),
+ GAMMA_CONST(XML_CTYPE_ANY),
+ GAMMA_CONST(XML_CTYPE_MIXED),
+ GAMMA_CONST(XML_CTYPE_NAME),
+ GAMMA_CONST(XML_CTYPE_CHOICE),
+ GAMMA_CONST(XML_CTYPE_SEQ),
+ /* XML_Content_Quant */
+ GAMMA_CONST(XML_CQUANT_NONE),
+ GAMMA_CONST(XML_CQUANT_OPT),
+ GAMMA_CONST(XML_CQUANT_REP),
+ GAMMA_CONST(XML_CQUANT_PLUS)
+#undef GAMMA_CONST
+};
+
+
+void
+gamma_expat_init()
+{
+ int i;
+
+ for (i = 0; i < sizeof(expat_code_tab)/sizeof(expat_code_tab[0]); i++) {
+ scm_c_define (expat_code_tab[i].name,
+ scm_from_int(expat_code_tab[i].val));
+ scm_c_export (expat_code_tab[i].name, NULL);
+ }
+
+ gamma_xml_parser_init();
+ init_generic_handler_setter();
+#include <gamma-expat.x>
+
+}
+

Return to:

Send suggestions and report system problems to the System administrator.