diff options
Diffstat (limited to 'gamma/gamma-expat.c')
-rw-r--r-- | gamma/gamma-expat.c | 1004 |
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> + +} + |