mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
James LewisMoss's patch.
2001-02-07 James LewisMoss <dres@phoenixdsl.com> * make-gnucash-patch.in: Add a file ending that is ignored. * src/doc/xml/types.dtd: Change currency-type -> commodity-type. Add defs for cmd:space and cmd:id. * src/doc/xml/io-gncxml-version1.dtd: Change currency-type -> commodity-type. * src/doc/xml/account-v2.dtd: Change currency-type -> commodity-type. 2001-02-06 James LewisMoss <dres@phoenixdsl.com> * src/engine/sixtp.c: Use frame creator. Move sixtp_handle_catastrophe to here. Add functions sixtp_context_new, sixtp_context_destroy. And change and move sixtp_parse_file and sixtp_parse_buffer here from io-gncxml-r.c Add concept of a parsing context to hold data. * src/engine/sixtp-stack.h: Add creator. Add headers. * src/engine/sixtp-stack.c: Add creator. * src/engine/sixtp-parsers.h: add needed headers. Add func from sixtp-to-dom-parser.c * src/engine/io-gncxml.h: Fix name. * src/engine/io-gncxml-w.c: Fix name. * src/engine/io-gncxml-r.c: Fix name. Create stack frame creator function and use here. 2001-02-05 James LewisMoss <dres@phoenixdsl.com> * src/engine/sixtp-stack.h: Add glib.h include (needed for GSList) * src/engine/sixtp.c: Add catchall tag for parsing handlers. Use name instead of next_parser_tag since that can now contain a magic value. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3618 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
7d546af657
commit
fa9cff9ce9
43
ChangeLog
43
ChangeLog
@ -1,3 +1,46 @@
|
||||
2001-02-07 James LewisMoss <dres@phoenixdsl.com>
|
||||
|
||||
* make-gnucash-patch.in: Add a file ending that is ignored.
|
||||
|
||||
* src/doc/xml/types.dtd: Change currency-type -> commodity-type.
|
||||
Add defs for cmd:space and cmd:id.
|
||||
|
||||
* src/doc/xml/io-gncxml-version1.dtd: Change currency-type ->
|
||||
commodity-type.
|
||||
|
||||
* src/doc/xml/account-v2.dtd: Change currency-type ->
|
||||
commodity-type.
|
||||
|
||||
2001-02-06 James LewisMoss <dres@phoenixdsl.com>
|
||||
|
||||
* src/engine/sixtp.c: Use frame creator.
|
||||
Move sixtp_handle_catastrophe to here. Add functions
|
||||
sixtp_context_new, sixtp_context_destroy. And change and move
|
||||
sixtp_parse_file and sixtp_parse_buffer here from io-gncxml-r.c
|
||||
Add concept of a parsing context to hold data.
|
||||
|
||||
* src/engine/sixtp-stack.h: Add creator. Add headers.
|
||||
|
||||
* src/engine/sixtp-stack.c: Add creator.
|
||||
|
||||
* src/engine/sixtp-parsers.h: add needed headers.
|
||||
Add func from sixtp-to-dom-parser.c
|
||||
|
||||
* src/engine/io-gncxml.h: Fix name.
|
||||
|
||||
* src/engine/io-gncxml-w.c: Fix name.
|
||||
|
||||
* src/engine/io-gncxml-r.c: Fix name. Create stack frame creator
|
||||
function and use here.
|
||||
|
||||
2001-02-05 James LewisMoss <dres@phoenixdsl.com>
|
||||
|
||||
* src/engine/sixtp-stack.h: Add glib.h include (needed for GSList)
|
||||
|
||||
* src/engine/sixtp.c: Add catchall tag for parsing handlers. Use
|
||||
name instead of next_parser_tag since that can now contain a magic
|
||||
value.
|
||||
|
||||
2001-02-05 Bill Gribble <grib@billgribble.com>
|
||||
|
||||
* src/scm/qif-import/qif-merge-groups.scm: new file. Utilities
|
||||
|
17
configure.in
17
configure.in
@ -52,6 +52,22 @@ then
|
||||
AC_MSG_ERROR([Cannot find glib.])
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS(dlfcn.h dl.h utmp.h locale.h mcheck.h unistd.h)
|
||||
|
||||
DL_LIB=
|
||||
AC_CHECK_FUNCS(dlopen,,[
|
||||
AC_CHECK_LIB(dl, dlopen, DL_LIB="-ldl",[
|
||||
AC_CHECK_LIB(dld, shl_load, DL_LIB="-ldld",[
|
||||
AC_CHECK_FUNCS(dlopen, DL_LIB="",
|
||||
AC_MSG_ERROR(Dynamic linking is not available on this platform. Some apps,
|
||||
like panel, will not run properly.))
|
||||
])])])
|
||||
oLIBS="$LIBS"
|
||||
LIBS="$LIBS $DL_LIB"
|
||||
AC_CHECK_FUNCS(dlerror,,)
|
||||
LIBS="$oLIBS"
|
||||
AC_SUBST(DL_LIB)
|
||||
|
||||
GNOME_INIT
|
||||
|
||||
GNOME_COMPILE_WARNINGS
|
||||
@ -512,6 +528,7 @@ AC_OUTPUT(
|
||||
src/scm/qif-import/Makefile
|
||||
src/scm/report/Makefile
|
||||
src/scm/srfi/Makefile
|
||||
src/test/Makefile
|
||||
dnl # non-makefiles
|
||||
dnl # Please read doc/build-system before adding *anything* here
|
||||
,
|
||||
|
@ -109,7 +109,7 @@ if (not defined($old)) {
|
||||
|
||||
chdir $gnc_home . "/" . $new or die "Can't cd!\n";
|
||||
# Start out with our basic makepatch arguments
|
||||
my @args = ('-verbose', '-diff', 'diff -u', '-exclude-vc');
|
||||
my @args = ('-verbose', '-diff', 'diff -up', '-exclude-vc');
|
||||
|
||||
if (not $::ask_description) {
|
||||
push(@args, '-description', '');
|
||||
@ -221,6 +221,7 @@ __DATA__
|
||||
*.moc
|
||||
*.o
|
||||
*.orig
|
||||
*.ignmgp
|
||||
*.patch
|
||||
*.rej
|
||||
*.tar.gz
|
||||
|
@ -10,7 +10,8 @@ SUBDIRS = \
|
||||
scm \
|
||||
quotes \
|
||||
pixmaps \
|
||||
optional
|
||||
optional \
|
||||
test
|
||||
|
||||
# Engine Makefile.am file.
|
||||
bin_PROGRAMS = gnucash
|
||||
|
@ -12,9 +12,9 @@
|
||||
|
||||
<!ELEMENT act:type (#PCDATA)>
|
||||
|
||||
<!ELEMENT act:currency %currency-type;>
|
||||
<!ELEMENT act:currency %commodity-type;>
|
||||
|
||||
<!ELEMENT act:security %currency-type;>
|
||||
<!ELEMENT act:security %commodity-type;>
|
||||
|
||||
<!ELEMENT act:slots %slot-type;>
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
"( guid, num?, date-posted, date-entered, description?,
|
||||
slots?, split+)">
|
||||
<!ENTITY % combined-restores "%commodity-restore; | %account-restore; | %transaction-restore;">
|
||||
<!ENTITY % currency-type "(space, id)">
|
||||
<!ENTITY % commodity-type "(space, id)">
|
||||
<!ENTITY % commodity-new "ANY">
|
||||
<!ENTITY % account-new "ANY">
|
||||
<!ENTITY % transaction-new "ANY">
|
||||
@ -47,8 +47,8 @@
|
||||
|
||||
<!ELEMENT guid (#PCDATA)>
|
||||
<!ELEMENT type (#PCDATA)>
|
||||
<!ELEMENT security %currency-type;>
|
||||
<!ELEMENT currency %currency-type;>
|
||||
<!ELEMENT security %commodity-type;>
|
||||
<!ELEMENT currency %commodity-type;>
|
||||
<!ELEMENT slots (s+)>
|
||||
|
||||
<!-- used in two contexts as item in slots list and as a date in -->
|
||||
|
@ -2,8 +2,12 @@
|
||||
<!ENTITY % id-type "(guid, new)">
|
||||
<!ENTITY % default-id-type "guid">
|
||||
|
||||
<!ENTITY % currency-type "(cur:space, cur:id)">
|
||||
<!ELEMENT cmd:space (#PCDATA)>
|
||||
<!ELEMENT cmd:id (#PCDATA)>
|
||||
|
||||
<!ENTITY % commodity-type "(cmd:space, cmd:id)">
|
||||
|
||||
<!-- need to replace the etc here -->
|
||||
<!ENTITY % slot-types "(string | integer | double | etc)">
|
||||
|
||||
<!ELEMENT slot (key, value)>
|
||||
|
@ -37,6 +37,7 @@ libgncengine_la_SOURCES = \
|
||||
sixtp-stack.c \
|
||||
sixtp-utils.c \
|
||||
sixtp-xml-write-utils.c \
|
||||
sixtp-to-dom-parser.c \
|
||||
sixtp.c \
|
||||
Account-xml-parser-v1.c \
|
||||
Commodity-xml-parser-v1.c \
|
||||
|
@ -2,7 +2,7 @@
|
||||
* io-gncxml-r.c -- read XML-format gnucash data file
|
||||
*
|
||||
* Initial code by Rob l. Browning 4Q 2000
|
||||
* Tuneups by James Lewis Moss Dec 2000
|
||||
* Tuneups by James LewisMoss Dec 2000
|
||||
* Excessive hacking inas Vepstas January 2001
|
||||
*
|
||||
*/
|
||||
@ -75,249 +75,7 @@
|
||||
|
||||
*/
|
||||
|
||||
static short module = MOD_IO;
|
||||
|
||||
static xmlEntityPtr
|
||||
sixtp_sax_get_entity_handler(void *user_data, const CHAR *name) {
|
||||
return xmlGetPredefinedEntity(name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
sixtp_handle_catastrophe(sixtp_sax_data *sax_data) {
|
||||
/* Something has gone wrong. To handle it, we have to traverse the
|
||||
stack, calling, at each level, the frame failure handler (the
|
||||
handler for the current, unfinished block) and then the sibling
|
||||
handlers. The order is reverse chronological - oldest child
|
||||
results cleaned up last. This holds overall as well, stack
|
||||
frames are cleaned up in their order on the stack which will be
|
||||
youngest to oldest. */
|
||||
|
||||
GSList *lp;
|
||||
GSList **stack = &(sax_data->stack);
|
||||
|
||||
PERR("parse failed at \n");
|
||||
sixtp_print_frame_stack(sax_data->stack, stderr);
|
||||
|
||||
while(*stack) {
|
||||
sixtp_stack_frame *current_frame = (sixtp_stack_frame *) (*stack)->data;
|
||||
|
||||
/* cleanup the current frame */
|
||||
if(current_frame->parser->fail_handler) {
|
||||
GSList *sibling_data;
|
||||
gpointer parent_data;
|
||||
|
||||
if((*stack)->next == NULL) {
|
||||
/* This is the top of the stack... */
|
||||
parent_data = NULL;
|
||||
sibling_data = NULL;
|
||||
} else {
|
||||
sixtp_stack_frame *parent_frame =
|
||||
(sixtp_stack_frame *) (*stack)->next->data;
|
||||
parent_data = parent_frame->data_for_children;
|
||||
sibling_data = parent_frame->data_from_children;
|
||||
}
|
||||
|
||||
current_frame->parser->fail_handler(current_frame->data_for_children,
|
||||
current_frame->data_from_children,
|
||||
sibling_data,
|
||||
parent_data,
|
||||
sax_data->global_data,
|
||||
¤t_frame->frame_data,
|
||||
current_frame->tag);
|
||||
}
|
||||
|
||||
/* now cleanup any children's results */
|
||||
for(lp = current_frame->data_from_children; lp; lp = lp->next) {
|
||||
sixtp_child_result *cresult = (sixtp_child_result *) lp->data;
|
||||
if(cresult->fail_handler) {
|
||||
cresult->fail_handler(cresult);
|
||||
}
|
||||
}
|
||||
|
||||
*stack = sixtp_pop_and_destroy_frame(*stack);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================================== */
|
||||
/* initialize misc structures so that we can call the libxml
|
||||
* parser.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
sixtp_setup_parser (sixtp *sixtp,
|
||||
gpointer data_for_top_level,
|
||||
gpointer global_data,
|
||||
xmlSAXHandler *sax_handler,
|
||||
sixtp_sax_data *sax_data,
|
||||
sixtp_stack_frame *top_frame
|
||||
)
|
||||
{
|
||||
memset(sax_handler, '\0', sizeof(xmlSAXHandler));
|
||||
sax_handler->startElement = sixtp_sax_start_handler;
|
||||
sax_handler->endElement = sixtp_sax_end_handler;
|
||||
sax_handler->characters = sixtp_sax_characters_handler;
|
||||
sax_handler->getEntity = sixtp_sax_get_entity_handler;
|
||||
|
||||
memset(sax_data, '\0', sizeof(sixtp_sax_data));
|
||||
sax_data->parsing_ok = TRUE;
|
||||
sax_data->stack = NULL;
|
||||
sax_data->global_data = global_data;
|
||||
|
||||
top_frame->parser = sixtp;
|
||||
top_frame->tag = NULL;
|
||||
top_frame->data_from_children = NULL;
|
||||
top_frame->data_for_children = NULL;
|
||||
top_frame->frame_data = NULL;
|
||||
|
||||
sax_data->stack = g_slist_prepend(sax_data->stack, (gpointer) top_frame);
|
||||
|
||||
if(sixtp->start_handler) {
|
||||
sax_data->parsing_ok =
|
||||
sixtp->start_handler(NULL,
|
||||
data_for_top_level,
|
||||
sax_data->global_data,
|
||||
&top_frame->data_for_children,
|
||||
&top_frame->frame_data,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
if(!sax_data->parsing_ok) {
|
||||
PERR ("parsing catastrophe");
|
||||
sixtp_handle_catastrophe(sax_data);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/* ========================================================== */
|
||||
/* misc structure celanup after parsing */
|
||||
|
||||
static gboolean
|
||||
sixtp_teardown_parser(sixtp *sixtp,
|
||||
gpointer data_for_top_level,
|
||||
gpointer global_data,
|
||||
gpointer *parse_result,
|
||||
sixtp_sax_data *sax_data,
|
||||
sixtp_stack_frame *top_frame)
|
||||
{
|
||||
if(!sax_data->parsing_ok) {
|
||||
PERR ("couldn't parse, handle catastrophe");
|
||||
sixtp_handle_catastrophe(sax_data);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if(sixtp->end_handler) {
|
||||
sax_data->parsing_ok =
|
||||
sixtp->end_handler(top_frame->data_for_children,
|
||||
top_frame->data_from_children,
|
||||
NULL,
|
||||
data_for_top_level,
|
||||
sax_data->global_data,
|
||||
&top_frame->frame_data,
|
||||
NULL);
|
||||
|
||||
if(!sax_data->parsing_ok) {
|
||||
PERR ("couldn't call end handler, cleanup catastrophe");
|
||||
sixtp_handle_catastrophe(sax_data);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* put the result where the caller can see it */
|
||||
if(top_frame->frame_data) *parse_result = top_frame->frame_data;
|
||||
|
||||
{
|
||||
GSList *lp = NULL;
|
||||
for(lp = sax_data->stack; lp; lp = lp->next)
|
||||
sixtp_stack_frame_destroy((sixtp_stack_frame *) lp->data);
|
||||
}
|
||||
g_slist_free(sax_data->stack);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* ========================================================== */
|
||||
/* parse the contents of a file */
|
||||
|
||||
static gboolean
|
||||
sixtp_parse_file(sixtp *sixtp,
|
||||
const char *filename,
|
||||
gpointer data_for_top_level,
|
||||
gpointer global_data,
|
||||
gpointer *parse_result)
|
||||
{
|
||||
xmlSAXHandler sax_handler;
|
||||
sixtp_sax_data sax_data;
|
||||
sixtp_stack_frame *top_frame = NULL;
|
||||
int rc;
|
||||
|
||||
/* hack alert -- XXX -- where is top_frame released?? */
|
||||
/* looks like a mem leak to me ... */
|
||||
top_frame = g_new0(sixtp_stack_frame, 1);
|
||||
rc = sixtp_setup_parser (sixtp,
|
||||
data_for_top_level,
|
||||
global_data,
|
||||
&sax_handler,
|
||||
&sax_data,
|
||||
top_frame);
|
||||
|
||||
if(!rc) return(FALSE);
|
||||
|
||||
xmlSAXUserParseFile(&sax_handler, &sax_data, filename);
|
||||
|
||||
rc = sixtp_teardown_parser(sixtp,
|
||||
data_for_top_level,
|
||||
global_data,
|
||||
parse_result,
|
||||
&sax_data,
|
||||
top_frame);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* ========================================================== */
|
||||
/* parse the contents of a buffer in memory */
|
||||
|
||||
static gboolean
|
||||
sixtp_parse_buffer(sixtp *sixtp,
|
||||
char *bufp,
|
||||
int bufsz,
|
||||
gpointer data_for_top_level,
|
||||
gpointer global_data,
|
||||
gpointer *parse_result)
|
||||
{
|
||||
xmlSAXHandler sax_handler;
|
||||
sixtp_sax_data sax_data;
|
||||
sixtp_stack_frame *top_frame = NULL;
|
||||
int rc;
|
||||
|
||||
/* hack alert -- XXX -- where is top_frame released?? */
|
||||
/* looks like a mem leak to me ... */
|
||||
top_frame = g_new0(sixtp_stack_frame, 1);
|
||||
rc = sixtp_setup_parser (sixtp,
|
||||
data_for_top_level,
|
||||
global_data,
|
||||
&sax_handler,
|
||||
&sax_data,
|
||||
top_frame);
|
||||
|
||||
if(!rc) return(FALSE);
|
||||
|
||||
xmlSAXUserParseMemory(&sax_handler, &sax_data, bufp, bufsz);
|
||||
|
||||
rc = sixtp_teardown_parser(sixtp,
|
||||
data_for_top_level,
|
||||
global_data,
|
||||
parse_result,
|
||||
&sax_data,
|
||||
top_frame);
|
||||
|
||||
return rc;
|
||||
}
|
||||
/* static short module = MOD_IO; */
|
||||
|
||||
/* ========================================================== */
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
* HISTORY:
|
||||
* Initial code by Rob L. Browning 4Q 2000
|
||||
* Tuneups by James Lewis Moss Dec 2000
|
||||
* Tuneups by James LewisMoss Dec 2000-Feb 2001
|
||||
* Generic I/O hack by Linas Vepstas January 2001
|
||||
*
|
||||
* Copyright (c) 2000,2001 Gnumatic Incorporated
|
||||
|
@ -2,7 +2,7 @@
|
||||
* io-gncxml.h -- api for new XML-based file format
|
||||
*
|
||||
* Initial code by Rob l. Browning 4Q 2000
|
||||
* Tuneups by James Lewis Moss Dec 2000
|
||||
* Tuneups by James LewisMoss Dec 2000
|
||||
*
|
||||
* Copyright (c) 2000,2001 Gnumatic Incorporated
|
||||
*
|
||||
|
@ -2,6 +2,8 @@
|
||||
#ifndef _SIXTP_PARSERS_H_
|
||||
#define _SIXTP_PARSERS_H_
|
||||
|
||||
#include "sixtp.h"
|
||||
|
||||
/* from Transaction-xml-parser-v1.c */
|
||||
sixtp* gnc_transaction_parser_new(void);
|
||||
|
||||
@ -23,6 +25,8 @@ sixtp* query_server_parser_new (void);
|
||||
/* from sixtp-kvp-parser.c */
|
||||
sixtp* kvp_frame_parser_new(void);
|
||||
|
||||
/* from sixtp-to-dom-parser.c */
|
||||
sixtp* sixtp_dom_parser_new(sixtp_end_handler ender);
|
||||
|
||||
|
||||
#endif /* _SIXTP_PARSERS_H_ */
|
||||
|
@ -12,9 +12,29 @@ sixtp_stack_frame_destroy(sixtp_stack_frame *sf) {
|
||||
g_slist_free(sf->data_from_children);
|
||||
sf->data_from_children = NULL;
|
||||
|
||||
/* if(sf->tag) */
|
||||
/* { */
|
||||
/* g_free(sf->tag); */
|
||||
/* } */
|
||||
|
||||
g_free(sf);
|
||||
}
|
||||
|
||||
sixtp_stack_frame*
|
||||
sixtp_stack_frame_new(sixtp* next_parser, char *tag)
|
||||
{
|
||||
sixtp_stack_frame* new_frame;
|
||||
|
||||
new_frame = g_new0(sixtp_stack_frame, 1);
|
||||
new_frame->parser = next_parser;
|
||||
new_frame->tag = tag;
|
||||
new_frame->data_for_children = NULL;
|
||||
new_frame->data_from_children = NULL;
|
||||
new_frame->frame_data = NULL;
|
||||
|
||||
return new_frame;
|
||||
}
|
||||
|
||||
void
|
||||
sixtp_stack_frame_print(sixtp_stack_frame *sf, gint indent, FILE *f) {
|
||||
gchar *is = g_strnfill(indent, ' ');
|
||||
@ -63,3 +83,72 @@ sixtp_print_frame_stack(GSList *stack, FILE *f) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Parser context */
|
||||
sixtp_parser_context*
|
||||
sixtp_context_new(sixtp *initial_parser, gpointer global_data,
|
||||
gpointer top_level_data)
|
||||
{
|
||||
sixtp_parser_context* ret;
|
||||
|
||||
ret = g_new0(sixtp_parser_context, 1);
|
||||
|
||||
ret->handler.startElement = sixtp_sax_start_handler;
|
||||
ret->handler.endElement = sixtp_sax_end_handler;
|
||||
ret->handler.characters = sixtp_sax_characters_handler;
|
||||
ret->handler.getEntity = sixtp_sax_get_entity_handler;
|
||||
|
||||
ret->data.parsing_ok = TRUE;
|
||||
ret->data.stack = NULL;
|
||||
ret->data.global_data = global_data;
|
||||
|
||||
ret->top_frame = sixtp_stack_frame_new(initial_parser, NULL);
|
||||
|
||||
ret->top_frame_data = top_level_data;
|
||||
|
||||
ret->data.stack = g_slist_prepend(ret->data.stack,
|
||||
(gpointer) ret->top_frame);
|
||||
|
||||
if(initial_parser->start_handler)
|
||||
{
|
||||
if(!initial_parser->start_handler(NULL,
|
||||
&ret->top_frame_data,
|
||||
&ret->data.global_data,
|
||||
&ret->top_frame->data_for_children,
|
||||
&ret->top_frame->frame_data,
|
||||
NULL, NULL))
|
||||
{
|
||||
sixtp_handle_catastrophe(&ret->data);
|
||||
sixtp_context_destroy(ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
sixtp_context_run_end_handler(sixtp_parser_context* ctxt)
|
||||
{
|
||||
if(ctxt->top_frame->parser->end_handler)
|
||||
{
|
||||
ctxt->data.parsing_ok =
|
||||
ctxt->top_frame->parser->end_handler(
|
||||
ctxt->top_frame->data_for_children,
|
||||
ctxt->top_frame->data_from_children,
|
||||
NULL,
|
||||
ctxt->top_frame_data,
|
||||
ctxt->data.global_data,
|
||||
&ctxt->top_frame->frame_data,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sixtp_context_destroy(sixtp_parser_context* context)
|
||||
{
|
||||
sixtp_stack_frame_destroy(context->top_frame);
|
||||
g_slist_free(context->data.stack);
|
||||
g_free(context);
|
||||
}
|
||||
|
@ -2,6 +2,10 @@
|
||||
#ifndef _SIXTP_STACK_H_
|
||||
#define _SIXTP_STACK_H_
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "sixtp.h"
|
||||
|
||||
typedef struct sixtp_stack_frame {
|
||||
sixtp *parser;
|
||||
gchar *tag;
|
||||
@ -10,6 +14,15 @@ typedef struct sixtp_stack_frame {
|
||||
gpointer frame_data;
|
||||
} sixtp_stack_frame;
|
||||
|
||||
struct _sixtp_parser_context_struct
|
||||
{
|
||||
xmlSAXHandler handler;
|
||||
sixtp_sax_data data;
|
||||
sixtp_stack_frame *top_frame;
|
||||
gpointer top_frame_data;
|
||||
};
|
||||
typedef struct _sixtp_parser_context_struct sixtp_parser_context;
|
||||
|
||||
void sixtp_stack_frame_destroy(sixtp_stack_frame *sf);
|
||||
|
||||
void sixtp_stack_frame_print(sixtp_stack_frame *sf, gint indent, FILE *f);
|
||||
@ -18,5 +31,12 @@ GSList* sixtp_pop_and_destroy_frame(GSList *frame_stack);
|
||||
|
||||
void sixtp_print_frame_stack(GSList *stack, FILE *f);
|
||||
|
||||
sixtp_stack_frame* sixtp_stack_frame_new(sixtp* next_parser, char *tag);
|
||||
|
||||
sixtp_parser_context* sixtp_context_new(sixtp *initial_parser,
|
||||
gpointer global_data,
|
||||
gpointer top_level_data);
|
||||
void sixtp_context_destroy(sixtp_parser_context* context);
|
||||
void sixtp_context_run_end_handler(sixtp_parser_context* ctxt);
|
||||
|
||||
#endif /* _SIXTP_STACK_H_ */
|
||||
|
@ -193,35 +193,6 @@ sixtp_set_any(sixtp *tochange, int cleanup, ...)
|
||||
return tochange;
|
||||
}
|
||||
|
||||
sixtp*
|
||||
sixtp_new_full(sixtp_start_handler starter,
|
||||
sixtp_before_child_handler cdbeforer,
|
||||
sixtp_after_child_handler chafterer,
|
||||
sixtp_end_handler ender,
|
||||
sixtp_characters_handler charer,
|
||||
sixtp_fail_handler failer,
|
||||
sixtp_result_handler cleanresulter,
|
||||
sixtp_result_handler cleancharer,
|
||||
sixtp_result_handler resultfailer,
|
||||
sixtp_result_handler charsfailer)
|
||||
{
|
||||
sixtp *ret = sixtp_new();
|
||||
g_return_val_if_fail(ret, NULL);
|
||||
|
||||
sixtp_set_start(ret, starter);
|
||||
sixtp_set_before_child(ret, cdbeforer);
|
||||
sixtp_set_after_child(ret, chafterer);
|
||||
sixtp_set_end(ret, ender);
|
||||
sixtp_set_chars(ret, charer);
|
||||
sixtp_set_fail(ret, failer);
|
||||
sixtp_set_cleanup_result(ret, cleanresulter);
|
||||
sixtp_set_cleanup_chars(ret, cleancharer);
|
||||
sixtp_set_result_fail(ret, resultfailer);
|
||||
sixtp_set_chars_fail(ret, charsfailer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sixtp_destroy_child(gpointer key, gpointer value,
|
||||
gpointer user_data);
|
||||
|
||||
@ -371,9 +342,16 @@ sixtp_sax_start_handler(void *user_data,
|
||||
(gpointer) &next_parser);
|
||||
|
||||
if(!lookup_success) {
|
||||
PERR("Tag <%s> not allowed in current context.\n", name);
|
||||
pdata->parsing_ok = FALSE;
|
||||
return;
|
||||
/* magic catch all value */
|
||||
lookup_success = g_hash_table_lookup_extended(
|
||||
current_parser->children, SIXTP_MAGIC_CATCHER,
|
||||
(gpointer) &next_parser_tag, (gpointer) &next_parser);
|
||||
if(!lookup_success)
|
||||
{
|
||||
PERR("Tag <%s> not allowed in current context.\n", name);
|
||||
pdata->parsing_ok = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(current_frame->parser->before_child) {
|
||||
@ -396,24 +374,15 @@ sixtp_sax_start_handler(void *user_data,
|
||||
pdata->global_data,
|
||||
&(current_frame->frame_data),
|
||||
current_frame->tag,
|
||||
next_parser_tag);
|
||||
name);
|
||||
}
|
||||
|
||||
g_return_if_fail(pdata->parsing_ok);
|
||||
|
||||
/* now allocate the new stack frame and shift to it */
|
||||
new_frame = g_new0(sixtp_stack_frame, 1);
|
||||
new_frame->parser = next_parser;
|
||||
new_frame->tag = next_parser_tag;
|
||||
new_frame->data_for_children = NULL;
|
||||
new_frame->data_from_children = NULL;
|
||||
new_frame->frame_data = NULL;
|
||||
new_frame = sixtp_stack_frame_new(next_parser, g_strdup(name));
|
||||
|
||||
/*printf("PUSHING FRAME for <%s> parser.\n", next_parser_tag);
|
||||
sixtp_stack_frame_print(new_frame, 2, stderr); */
|
||||
pdata->stack = g_slist_prepend(pdata->stack, (gpointer) new_frame);
|
||||
/*printf("RESULTANT STACK: ");
|
||||
sixtp_print_frame_stack(pdata->stack, stderr); */
|
||||
|
||||
if(next_parser->start_handler) {
|
||||
pdata->parsing_ok =
|
||||
@ -422,7 +391,7 @@ sixtp_sax_start_handler(void *user_data,
|
||||
pdata->global_data,
|
||||
&new_frame->data_for_children,
|
||||
&new_frame->frame_data,
|
||||
next_parser_tag,
|
||||
name,
|
||||
(gchar**)attrs);
|
||||
}
|
||||
}
|
||||
@ -553,3 +522,135 @@ sixtp_sax_end_handler(void *user_data, const xmlChar *name) {
|
||||
child_result_data);
|
||||
}
|
||||
}
|
||||
|
||||
xmlEntityPtr
|
||||
sixtp_sax_get_entity_handler(void *user_data, const CHAR *name) {
|
||||
return xmlGetPredefinedEntity(name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sixtp_handle_catastrophe(sixtp_sax_data *sax_data) {
|
||||
/* Something has gone wrong. To handle it, we have to traverse the
|
||||
stack, calling, at each level, the frame failure handler (the
|
||||
handler for the current, unfinished block) and then the sibling
|
||||
handlers. The order is reverse chronological - oldest child
|
||||
results cleaned up last. This holds overall as well, stack
|
||||
frames are cleaned up in their order on the stack which will be
|
||||
youngest to oldest. */
|
||||
|
||||
GSList *lp;
|
||||
GSList **stack = &(sax_data->stack);
|
||||
|
||||
PERR("parse failed at \n");
|
||||
sixtp_print_frame_stack(sax_data->stack, stderr);
|
||||
|
||||
while(*stack) {
|
||||
sixtp_stack_frame *current_frame = (sixtp_stack_frame *) (*stack)->data;
|
||||
|
||||
/* cleanup the current frame */
|
||||
if(current_frame->parser->fail_handler) {
|
||||
GSList *sibling_data;
|
||||
gpointer parent_data;
|
||||
|
||||
if((*stack)->next == NULL) {
|
||||
/* This is the top of the stack... */
|
||||
parent_data = NULL;
|
||||
sibling_data = NULL;
|
||||
} else {
|
||||
sixtp_stack_frame *parent_frame =
|
||||
(sixtp_stack_frame *) (*stack)->next->data;
|
||||
parent_data = parent_frame->data_for_children;
|
||||
sibling_data = parent_frame->data_from_children;
|
||||
}
|
||||
|
||||
current_frame->parser->fail_handler(current_frame->data_for_children,
|
||||
current_frame->data_from_children,
|
||||
sibling_data,
|
||||
parent_data,
|
||||
sax_data->global_data,
|
||||
¤t_frame->frame_data,
|
||||
current_frame->tag);
|
||||
}
|
||||
|
||||
/* now cleanup any children's results */
|
||||
for(lp = current_frame->data_from_children; lp; lp = lp->next) {
|
||||
sixtp_child_result *cresult = (sixtp_child_result *) lp->data;
|
||||
if(cresult->fail_handler) {
|
||||
cresult->fail_handler(cresult);
|
||||
}
|
||||
}
|
||||
|
||||
*stack = sixtp_pop_and_destroy_frame(*stack);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
sixtp_parse_file(sixtp *sixtp,
|
||||
const char *filename,
|
||||
gpointer data_for_top_level,
|
||||
gpointer global_data,
|
||||
gpointer *parse_result)
|
||||
{
|
||||
sixtp_parser_context *ctxt;
|
||||
|
||||
if(!(ctxt = sixtp_context_new(sixtp, global_data, data_for_top_level)))
|
||||
{
|
||||
PERR("sixtp_context_new returned null");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
xmlSAXUserParseFile(&ctxt->handler, &ctxt->data, filename);
|
||||
|
||||
sixtp_context_run_end_handler(ctxt);
|
||||
|
||||
if(ctxt->data.parsing_ok)
|
||||
{
|
||||
*parse_result = ctxt->top_frame->frame_data;
|
||||
sixtp_context_destroy(ctxt);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*parse_result = NULL;
|
||||
sixtp_handle_catastrophe(&ctxt->data);
|
||||
sixtp_context_destroy(ctxt);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
sixtp_parse_buffer(sixtp *sixtp,
|
||||
char *bufp,
|
||||
int bufsz,
|
||||
gpointer data_for_top_level,
|
||||
gpointer global_data,
|
||||
gpointer *parse_result)
|
||||
{
|
||||
sixtp_parser_context *ctxt;
|
||||
|
||||
if(!(ctxt = sixtp_context_new(sixtp, global_data, data_for_top_level)))
|
||||
{
|
||||
PERR("sixtp_context_new returned null");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
xmlSAXUserParseMemory(&ctxt->handler, &ctxt->data, bufp, bufsz);
|
||||
|
||||
sixtp_context_run_end_handler(ctxt);
|
||||
|
||||
if(ctxt->data.parsing_ok)
|
||||
{
|
||||
*parse_result = ctxt->top_frame->frame_data;
|
||||
sixtp_context_destroy(ctxt);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*parse_result = NULL;
|
||||
sixtp_handle_catastrophe(&ctxt->data);
|
||||
sixtp_context_destroy(ctxt);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,9 @@ typedef enum {
|
||||
SIXTP_CHARS_FAIL_ID,
|
||||
} sixtp_handler_type;
|
||||
|
||||
/* completely invalid tag for xml */
|
||||
#define SIXTP_MAGIC_CATCHER "&MAGIX&"
|
||||
|
||||
typedef enum {
|
||||
SIXTP_CHILD_RESULT_CHARS,
|
||||
SIXTP_CHILD_RESULT_NODE
|
||||
@ -167,9 +170,18 @@ void sixtp_sax_characters_handler(void *user_data, const xmlChar *text,
|
||||
void sixtp_sax_end_handler(void *user_data, const xmlChar *name);
|
||||
|
||||
sixtp* sixtp_new(void);
|
||||
|
||||
void sixtp_destroy(sixtp *sp);
|
||||
|
||||
void sixtp_handle_catastrophe(sixtp_sax_data *sax_data);
|
||||
xmlEntityPtr sixtp_sax_get_entity_handler(void *user_data, const CHAR *name);
|
||||
|
||||
gboolean sixtp_parse_file(sixtp *sixtp, const char *filename,
|
||||
gpointer data_for_top_level, gpointer global_data,
|
||||
gpointer *parse_result);
|
||||
gboolean sixtp_parse_buffer(sixtp *sixtp, char *bufp, int bufsz,
|
||||
gpointer data_for_top_level, gpointer global_data,
|
||||
gpointer *parse_result);
|
||||
|
||||
void sixtp_set_start(sixtp *parser, sixtp_start_handler start_handler);
|
||||
void sixtp_set_before_child(sixtp *parser, sixtp_before_child_handler handler);
|
||||
void sixtp_set_after_child(sixtp *parser, sixtp_after_child_handler handler);
|
||||
|
Loading…
Reference in New Issue
Block a user