diff --git a/src/document/dom/renderer.c b/src/document/dom/renderer.c index f3c0699e..977c775e 100644 --- a/src/document/dom/renderer.c +++ b/src/document/dom/renderer.c @@ -621,7 +621,8 @@ static void render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, void *data) { struct dom_renderer *renderer = stack->current->data; - struct sgml_parser_state *pstate = data; + struct dom_stack_state *state = get_dom_stack_top(stack); + struct sgml_parser_state *pstate = get_dom_stack_state_data(stack->contexts, state); struct scanner_token *token = &pstate->end_token; unsigned char *string = token->string; int length = token->length; @@ -730,6 +731,7 @@ render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void } static struct dom_stack_context_info dom_source_renderer_context_info = { + /* Object size: */ 0, /* Push: */ { /* */ NULL, diff --git a/src/document/dom/select.c b/src/document/dom/select.c index 1240f2e9..7922735a 100644 --- a/src/document/dom/select.c +++ b/src/document/dom/select.c @@ -742,7 +742,7 @@ dom_select_pop_element(struct dom_stack *stack, struct dom_node *node, void *dat struct dom_select_node *selector = (void *) state->node; struct dom_select_state *select_state; - select_state = get_dom_stack_state_data(stack, state); + select_state = get_dom_stack_state_data(stack->current, state); if (select_state->node == node) { pop_dom_state(stack, state); WDBG("Remove element."); @@ -788,6 +788,7 @@ dom_select_push_text(struct dom_stack *stack, struct dom_node *node, void *data) } static struct dom_stack_context_info dom_select_context_info = { + /* Object size: */ 0, /* Push: */ { /* */ NULL, @@ -823,6 +824,7 @@ static struct dom_stack_context_info dom_select_context_info = { }; static struct dom_stack_context_info dom_select_data_context_info = { + /* Object size: */ sizeof(struct dom_select_state), /* Push: */ { /* */ NULL, @@ -862,7 +864,6 @@ select_dom_nodes(struct dom_select *select, struct dom_node *root) { struct dom_select_data select_data; struct dom_stack stack; - size_t obj_size = sizeof(struct dom_select_state); memset(&select_data, 0, sizeof(select_data)); @@ -872,7 +873,7 @@ select_dom_nodes(struct dom_select *select, struct dom_node *root) add_dom_stack_context(&stack, &select_data, &dom_select_context_info); - init_dom_stack(&select_data.stack, obj_size, 1); + init_dom_stack(&select_data.stack, 0, 1); add_dom_stack_context(&stack, &select_data, &dom_select_data_context_info); diff --git a/src/document/dom/stack.c b/src/document/dom/stack.c index e5743e90..853eacab 100644 --- a/src/document/dom/stack.c +++ b/src/document/dom/stack.c @@ -37,17 +37,17 @@ realloc_dom_stack_context(struct dom_stack_context **contexts, size_t size) } static inline unsigned char * -realloc_dom_stack_state_objects(struct dom_stack *stack) +realloc_dom_stack_state_objects(struct dom_stack_context *context, size_t depth) { #ifdef DEBUG_MEMLEAK - return mem_align_alloc__(__FILE__, __LINE__, (void **) &stack->state_objects, - stack->depth, stack->depth + 1, - stack->object_size, + return mem_align_alloc__(__FILE__, __LINE__, (void **) &context->state_objects, + depth, depth + 1, + context->info->object_size, DOM_STACK_STATE_GRANULARITY); #else - return mem_align_alloc__((void **) &stack->state_objects, - stack->depth, stack->depth + 1, - stack->object_size, + return mem_align_alloc__((void **) &context->state_objects, + depth, depth + 1, + context->info->object_size, DOM_STACK_STATE_GRANULARITY); #endif } @@ -59,18 +59,22 @@ init_dom_stack(struct dom_stack *stack, size_t object_size, int keep_nodes) memset(stack, 0, sizeof(*stack)); - stack->object_size = object_size; stack->keep_nodes = !!keep_nodes; } void done_dom_stack(struct dom_stack *stack) { + int i; + assert(stack); + for (i = 0; i < stack->contexts_size; i++) { + mem_free_if(stack->contexts[i].state_objects); + } + mem_free_if(stack->contexts); mem_free_if(stack->states); - mem_free_if(stack->state_objects); memset(stack, 0, sizeof(*stack)); } @@ -98,13 +102,11 @@ static void call_dom_stack_callbacks(struct dom_stack *stack, struct dom_stack_state *state, enum dom_stack_action action) { - /* FIME: Variable stack data, so the parse/selector/renderer/etc. can - * really work in parallel. */ - void *state_data = get_dom_stack_state_data(stack, state); int i; for (i = 0; i < stack->contexts_size; i++) { struct dom_stack_context *context = &stack->contexts[i]; + void *state_data = get_dom_stack_state_data(context, state); dom_stack_callback_T callback; if (action == DOM_STACK_PUSH) @@ -124,6 +126,7 @@ struct dom_node * push_dom_node(struct dom_stack *stack, struct dom_node *node) { struct dom_stack_state *state; + int i; assert(stack && node); assert(0 < node->type && node->type < DOM_NODES); @@ -140,18 +143,17 @@ push_dom_node(struct dom_stack *stack, struct dom_node *node) state += stack->depth; - if (stack->object_size) { - unsigned char *state_objects; + for (i = 0; i < stack->contexts_size; i++) { + struct dom_stack_context *context = &stack->contexts[i]; - state_objects = realloc_dom_stack_state_objects(stack); - if (!state_objects) { + if (context->info->object_size + && !realloc_dom_stack_state_objects(context, stack->depth)) { done_dom_node(node); return NULL; } - - state->depth = stack->depth; } + state->depth = stack->depth; state->node = node; /* Grow the state array to the new depth so the state accessors work @@ -166,6 +168,7 @@ static int do_pop_dom_node(struct dom_stack *stack, struct dom_stack_state *parent) { struct dom_stack_state *state; + int i; assert(stack && !dom_stack_is_empty(stack)); @@ -181,10 +184,14 @@ do_pop_dom_node(struct dom_stack *stack, struct dom_stack_state *parent) stack->depth--; assert(stack->depth >= 0); - if (stack->object_size) { - void *state_data = get_dom_stack_state_data(stack, state); + for (i = 0; i < stack->contexts_size; i++) { + struct dom_stack_context *context = &stack->contexts[i]; - memset(state_data, 0, stack->object_size); + if (context->info->object_size) { + void *state_data = get_dom_stack_state_data(context, state); + + memset(state_data, 0, context->info->object_size); + } } memset(state, 0, sizeof(*state)); diff --git a/src/document/dom/stack.h b/src/document/dom/stack.h index 2118394a..85318c5c 100644 --- a/src/document/dom/stack.h +++ b/src/document/dom/stack.h @@ -11,6 +11,7 @@ struct dom_stack; typedef void (*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void *); struct dom_stack_context_info { + size_t object_size; dom_stack_callback_T push[DOM_NODES]; dom_stack_callback_T pop[DOM_NODES]; }; @@ -19,6 +20,12 @@ struct dom_stack_context { /* Data specific to the parser and renderer. */ void *data; + /* This is one big array of context specific objects. */ + /* For the SGML parser this holds DTD-oriented info about the node + * (recorded in struct sgml_node_info). E.g. whether an element node + * is optional. */ + unsigned char *state_objects; + /* Info about node callbacks and such. */ struct dom_stack_context_info *info; }; @@ -54,13 +61,6 @@ struct dom_stack { /* Keep nodes when popping them or call done_dom_node() on them. */ unsigned int keep_nodes:1; - /* This is one big array of parser specific objects. */ - /* The objects hold parser specific data. For the SGML parser this - * holds DTD-oriented info about the node (recorded in struct - * sgml_node_info). E.g. whether an element node is optional. */ - unsigned char *state_objects; - size_t object_size; - /* Callbacks which should be called for the pushed and popped nodes. */ struct dom_stack_context *contexts; size_t contexts_size; @@ -81,8 +81,8 @@ get_dom_stack_state(struct dom_stack *stack, int top_offset) #define get_dom_stack_parent(stack) get_dom_stack_state(stack, 1) #define get_dom_stack_top(stack) get_dom_stack_state(stack, 0) -#define get_dom_stack_state_data(stack, state) \ - ((void *) &(stack)->state_objects[(state)->depth * (stack)->object_size]) +#define get_dom_stack_state_data(context, state) \ + ((void *) &(context)->state_objects[(state)->depth * (context)->info->object_size]) /* The state iterators do not include the bottom state */ diff --git a/src/document/sgml/parser.c b/src/document/sgml/parser.c index 41435708..3116d997 100644 --- a/src/document/sgml/parser.c +++ b/src/document/sgml/parser.c @@ -28,7 +28,7 @@ #define get_sgml_parser(stack) ((stack)->contexts->data) #define get_sgml_parser_state(stack, state) \ - get_dom_stack_state_data(stack, state) + get_dom_stack_state_data(stack->contexts, state) /* Functions for adding new nodes to the DOM tree */ @@ -313,6 +313,7 @@ parse_sgml_document(struct dom_stack *stack, struct scanner *scanner) static struct dom_stack_context_info sgml_parser_context_info = { + /* Object size: */ sizeof(struct sgml_parser_state), /* Push: */ { /* */ NULL, @@ -351,7 +352,6 @@ struct sgml_parser * init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype, struct uri *uri) { - size_t obj_size = sizeof(struct sgml_parser_state); struct sgml_parser *parser; parser = mem_calloc(1, sizeof(*parser)); @@ -361,7 +361,7 @@ init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype, parser->uri = get_uri_reference(uri); parser->info = get_sgml_info(doctype); - init_dom_stack(&parser->stack, obj_size, + init_dom_stack(&parser->stack, 0, type != SGML_PARSER_STREAM); /* FIXME: Some sgml backend specific callbacks? Handle HTML script tags, * and feed document.write() data back to the parser. */