psyclpc/src/pkg-expat.c

243 lines
5.8 KiB
C

/*---------------------------------------------------------------------------
* fippo's lightweight wrapper for the expat xml parser
*---------------------------------------------------------------------------
*/
#include "driver.h"
#ifdef USE_EXPAT
#include<stdio.h>
#include<sys/time.h>
#include "machine.h"
#include "typedefs.h"
#include "my-alloca.h"
#include "actions.h"
#include "array.h"
#include "gcollect.h"
#include "instrs.h"
#include "interpret.h"
#include "main.h"
#include "mapping.h"
#include "mstrings.h"
#include "simulate.h"
#include "stdstrings.h"
#include "xalloc.h"
#include "closure.h"
#include "object.h"
#include "mapping.h"
#include "pkg-expat.h"
#include<expat.h>
#include<stdio.h>
// TODO: these are copied from pkg-tls.c
static void *
expat_xalloc (size_t size)
/* Wrapper function so that expat will use the driver's allocator.
* The wrapper is required as 'pxalloc' itself is a macro.
*/
{
return pxalloc(size);
} /* expat_xalloc() */
/*-------------------------------------------------------------------------*/
static void *
expat_rexalloc (void *old, size_t size)
/* Wrapper function so that expat will use the driver's allocator.
* The wrapper is required as 'prexalloc' itself is a macro.
*/
{
return prexalloc(old, size);
} /* expat_rexalloc() */
/*-------------------------------------------------------------------------*/
static void
expat_xfree (void *p)
/* Wrapper function so that expat will use the driver's allocator.
* The wrapper is not exactly required for pfree(), but it keeps things
* consistent.
*/
{
return pfree(p);
} /* expat_xfree() */
/* memory handling suite */
const XML_Memory_Handling_Suite xml_memsuite = {
expat_xalloc,
expat_rexalloc,
expat_xfree
};
void expat_ElementStart(void *data, const char *el, const char **attrs)
{
int i;
int num_attributes;
mapping_t *attributes;
svalue_t attr_key, *attr_value;
num_attributes = XML_GetSpecifiedAttributeCount(current_object->xml_parser) / 2;
attributes = allocate_mapping(num_attributes, 1);
for(i = 0; attrs[i]; i += 2)
{
/* name -> value */
put_c_string(&attr_key, attrs[i]);
attr_value = get_map_lvalue(attributes, &attr_key);
put_c_string(attr_value, attrs[i+1]);
free_svalue(&attr_key);
}
/* call lpcish onElementStart with element name and params */
push_c_string(inter_sp, el);
push_mapping(inter_sp, attributes);
secure_apply(new_mstring("xml_onStartTag"), current_object, 2);
}
void expat_ElementEnd(void *data, const char *el)
{
/* call lpcish onElementEnd */
push_c_string(inter_sp, el);
secure_apply(new_mstring("xml_onEndTag"), current_object, 1);
}
void expat_ElementText(void *data, const char *txt, int txtlen)
{
/* txt is not 0-terminated! */
string_t *mtxt;
memsafe(mtxt = new_n_mstring(txt, txtlen), txtlen, "string");
/* call lpcish onText */
push_string(inter_sp, mtxt);
secure_apply(new_mstring("xml_onText"), current_object, 1);
}
svalue_t *
f_expat_parse(svalue_t *sp)
/*
* int expat_parse(string document)
* parses the string document
* returns 1 when finished successfully, 0 if there was a parse error
*/
{
int ret;
int err;
if (current_object->xml_parser == NULL)
{
errorf("%s expat_parse called without initialization.\n", time_stamp());
/* NOTREACHED */
}
current_object->xml_error = MY_FALSE;
/* we parse en block */
err = XML_Parse(current_object->xml_parser, get_txt(sp->u.str), mstrsize(sp->u.str), 0);
if (!err)
{
/* user should fetch the error with expat_lastError() */
current_object->xml_error = MY_TRUE;
ret = 0;
}
else
{
ret = 1;
}
/* free the document string */
free_svalue(sp);
put_number(sp, ret);
return sp;
}
/*
* void expat_init([string namespace separator [, string encoding]])
* initializes the objects XML parser.
* only the first character of the namespace separator string is used.
*
* calling expat_init a second time will reset the parser.
*/
svalue_t *
v_expat_init(svalue_t *sp, int num_arg)
{
char *separator = NULL; /* namespace separator */
char *encoding = NULL;
if (num_arg > 1)
{
separator = get_txt(sp->u.str);
free_svalue(sp--);
}
if (num_arg > 0)
{
encoding = get_txt(sp->u.str);
free_svalue(sp--);
}
if (1) {
current_object->xml_parser = XML_ParserCreate_MM(encoding, &xml_memsuite, separator);
}
else
{
printf("parser reset\n");
XML_ParserReset(current_object->xml_parser, encoding);
}
XML_SetCharacterDataHandler(current_object->xml_parser,
expat_ElementText);
XML_SetElementHandler(current_object->xml_parser,
expat_ElementStart, expat_ElementEnd);
return sp;
}
svalue_t *
f_expat_last_error(svalue_t *sp)
{
if (current_object->xml_error == MY_FALSE)
{
push_number(sp, 0);
}
else
{
vector_t *ret;
int errorcode;
ret = allocate_array(5);
errorcode = XML_GetErrorCode(current_object->xml_parser);
put_c_string(&ret->item[0], XML_ErrorString(errorcode));
put_number(&ret->item[1], errorcode);
put_number(&ret->item[2], XML_GetErrorLineNumber(current_object->xml_parser));
put_number(&ret->item[3], XML_GetErrorColumnNumber(current_object->xml_parser));
put_number(&ret->item[4], XML_GetErrorByteIndex(current_object->xml_parser));
sp++;
put_array(sp, ret);
}
return sp;
}
svalue_t *
f_expat_position(svalue_t *sp) {
if (current_object->xml_parser == NULL)
push_number(sp, -1);
else
push_number(sp, XML_GetCurrentByteIndex(current_object->xml_parser));
return sp;
}
svalue_t *
f_expat_eventlen(svalue_t *sp) {
if (current_object->xml_parser == NULL)
push_number(sp, -1);
else
push_number(sp, XML_GetCurrentByteCount(current_object->xml_parser));
return sp;
}
#endif /* USE_EXPAT */