From fa9cff9ce9d3215452b207d48a00950e734987fd Mon Sep 17 00:00:00 2001 From: Dave Peticolas Date: Thu, 8 Feb 2001 04:08:50 +0000 Subject: [PATCH] James LewisMoss's patch. 2001-02-07 James LewisMoss * 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 * 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 * 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 --- ChangeLog | 43 +++++ configure.in | 17 ++ make-gnucash-patch.in | 3 +- src/Makefile.am | 3 +- src/doc/xml/account-v2.dtd | 4 +- src/doc/xml/io-gncxml-version1.dtd | 6 +- src/doc/xml/types.dtd | 6 +- src/engine/Makefile.am | 1 + src/engine/io-gncxml-r.c | 246 +---------------------------- src/engine/io-gncxml-w.c | 2 +- src/engine/io-gncxml.h | 2 +- src/engine/sixtp-parsers.h | 4 + src/engine/sixtp-stack.c | 89 +++++++++++ src/engine/sixtp-stack.h | 20 +++ src/engine/sixtp.c | 189 ++++++++++++++++------ src/engine/sixtp.h | 16 +- 16 files changed, 351 insertions(+), 300 deletions(-) diff --git a/ChangeLog b/ChangeLog index ec799f06fc..5704cdf88c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +2001-02-07 James LewisMoss + + * 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 + + * 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 + + * 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 * src/scm/qif-import/qif-merge-groups.scm: new file. Utilities diff --git a/configure.in b/configure.in index 4d41e31044..e3364eb4f4 100644 --- a/configure.in +++ b/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 , diff --git a/make-gnucash-patch.in b/make-gnucash-patch.in index 0c5ae9bc58..c984523093 100644 --- a/make-gnucash-patch.in +++ b/make-gnucash-patch.in @@ -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 diff --git a/src/Makefile.am b/src/Makefile.am index 7d9d732143..7492cd1a76 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,8 @@ SUBDIRS = \ scm \ quotes \ pixmaps \ - optional + optional \ + test # Engine Makefile.am file. bin_PROGRAMS = gnucash diff --git a/src/doc/xml/account-v2.dtd b/src/doc/xml/account-v2.dtd index 92ffca2c72..13c7410ae0 100644 --- a/src/doc/xml/account-v2.dtd +++ b/src/doc/xml/account-v2.dtd @@ -12,9 +12,9 @@ - + - + diff --git a/src/doc/xml/io-gncxml-version1.dtd b/src/doc/xml/io-gncxml-version1.dtd index 5aa881c9e6..3452b462f4 100644 --- a/src/doc/xml/io-gncxml-version1.dtd +++ b/src/doc/xml/io-gncxml-version1.dtd @@ -25,7 +25,7 @@ "( guid, num?, date-posted, date-entered, description?, slots?, split+)"> - + @@ -47,8 +47,8 @@ - - + + diff --git a/src/doc/xml/types.dtd b/src/doc/xml/types.dtd index 12463c4bf7..75bfe1fd6b 100644 --- a/src/doc/xml/types.dtd +++ b/src/doc/xml/types.dtd @@ -2,8 +2,12 @@ - + + + + + diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am index edc583ba18..292e12bb20 100644 --- a/src/engine/Makefile.am +++ b/src/engine/Makefile.am @@ -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 \ diff --git a/src/engine/io-gncxml-r.c b/src/engine/io-gncxml-r.c index e67f81843d..83dcb923cb 100644 --- a/src/engine/io-gncxml-r.c +++ b/src/engine/io-gncxml-r.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; */ /* ========================================================== */ diff --git a/src/engine/io-gncxml-w.c b/src/engine/io-gncxml-w.c index 5e1297a13a..1f6ba8582e 100644 --- a/src/engine/io-gncxml-w.c +++ b/src/engine/io-gncxml-w.c @@ -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 diff --git a/src/engine/io-gncxml.h b/src/engine/io-gncxml.h index 2b2901bde3..caddc89177 100644 --- a/src/engine/io-gncxml.h +++ b/src/engine/io-gncxml.h @@ -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 * diff --git a/src/engine/sixtp-parsers.h b/src/engine/sixtp-parsers.h index e7111d8c94..bfcfdacedb 100644 --- a/src/engine/sixtp-parsers.h +++ b/src/engine/sixtp-parsers.h @@ -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_ */ diff --git a/src/engine/sixtp-stack.c b/src/engine/sixtp-stack.c index 2caf84d229..6fb8257be6 100644 --- a/src/engine/sixtp-stack.c +++ b/src/engine/sixtp-stack.c @@ -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); +} diff --git a/src/engine/sixtp-stack.h b/src/engine/sixtp-stack.h index 502cf908e3..cf4a319b71 100644 --- a/src/engine/sixtp-stack.h +++ b/src/engine/sixtp-stack.h @@ -2,6 +2,10 @@ #ifndef _SIXTP_STACK_H_ #define _SIXTP_STACK_H_ +#include + +#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_ */ diff --git a/src/engine/sixtp.c b/src/engine/sixtp.c index 20c787bfd0..c7cc13d785 100644 --- a/src/engine/sixtp.c +++ b/src/engine/sixtp.c @@ -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; + } +} + diff --git a/src/engine/sixtp.h b/src/engine/sixtp.h index ca80363491..b648c16d65 100644 --- a/src/engine/sixtp.h +++ b/src/engine/sixtp.h @@ -132,7 +132,10 @@ 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);