/* 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 . */
#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_malloc(sizeof (*gp));
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 scm_sizet
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("#", port);
/* FIXME: show more details */
return 1;
}
static void
gamma_xml_parser_init()
{
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 ()
{
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_memory_error(FUNC_NAME);
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
}