From a0970535671dc059dab1ca2a02d053486d187ecf Mon Sep 17 00:00:00 2001 From: Andrew Sidwell Date: Fri, 11 Jul 2008 17:07:57 +0000 Subject: Significantly refactor the "in foreign content" mode. Still doesn't work, but the logic is clearer and more correct. svn path=/trunk/hubbub/; revision=4608 --- src/treebuilder/in_foreign_content.c | 111 ++++++++++++++++------------------- src/treebuilder/internal.h | 1 - src/treebuilder/treebuilder.c | 12 ---- 3 files changed, 50 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/treebuilder/in_foreign_content.c b/src/treebuilder/in_foreign_content.c index eea7d49..a8343f1 100644 --- a/src/treebuilder/in_foreign_content.c +++ b/src/treebuilder/in_foreign_content.c @@ -17,16 +17,11 @@ static bool element_in_scope_in_non_html_ns(hubbub_treebuilder *treebuilder) { + element_context *stack = treebuilder->context.element_stack; uint32_t node; - if (treebuilder->context.element_stack == NULL) - return false; - - for (node = treebuilder->context.current_node; node > 0; node--) { - element_type node_ns = - treebuilder->context.element_stack[node].ns; - - if (node_ns != HTML) + for (node = treebuilder->context.current_node; node != 0; node--) { + if (stack[node].ns != HUBBUB_NS_HTML) return true; } @@ -34,6 +29,45 @@ static bool element_in_scope_in_non_html_ns(hubbub_treebuilder *treebuilder) } +static void process_as_in_secondary(hubbub_treebuilder *treebuilder, + const hubbub_token *token) +{ + treebuilder->context.mode = treebuilder->context.second_mode; + + hubbub_treebuilder_token_handler(token, treebuilder); + + if (treebuilder->context.mode == IN_FOREIGN_CONTENT && + !element_in_scope_in_non_html_ns(treebuilder)) { + treebuilder->context.mode = + treebuilder->context.second_mode; + } +} + +/** + * Break out of foreign content as a result of certain start tags or EOF. + */ +static void foreign_break_out(hubbub_treebuilder *treebuilder) +{ + element_context *stack = treebuilder->context.element_stack; + + /** \todo parse error */ + + while (stack[treebuilder->context.current_node].ns != + HUBBUB_NS_HTML) { + hubbub_ns ns; + element_type type; + void *node; + + element_stack_pop(treebuilder, &ns, &type, &node); + + treebuilder->tree_handler->unref_node( + treebuilder->tree_handler->ctx, + node); + } + + treebuilder->context.mode = treebuilder->context.second_mode; +} + /** * Handle tokens in "in foreign content" insertion mode @@ -47,10 +81,6 @@ bool handle_in_foreign_content(hubbub_treebuilder *treebuilder, { bool reprocess = false; - element_type cur_node = current_node(treebuilder); - hubbub_ns cur_node_ns = current_node_ns(treebuilder); - - switch (token->type) { case HUBBUB_TOKEN_CHARACTER: append_text(treebuilder, &token->data.character); @@ -65,6 +95,10 @@ bool handle_in_foreign_content(hubbub_treebuilder *treebuilder, break; case HUBBUB_TOKEN_START_TAG: { + hubbub_ns cur_node_ns = treebuilder->context.element_stack[ + treebuilder->context.current_node].ns; + + element_type cur_node = current_node(treebuilder); element_type type = element_type_from_name(treebuilder, &token->data.tag.name); @@ -74,15 +108,7 @@ bool handle_in_foreign_content(hubbub_treebuilder *treebuilder, (cur_node == MI || cur_node == MO || cur_node == MN || cur_node == MS || cur_node == MTEXT))) { - treebuilder->context.mode = - treebuilder->context.second_mode; - hubbub_treebuilder_token_handler(token, treebuilder); - - if (treebuilder->context.mode == IN_FOREIGN_CONTENT && - !element_in_scope_in_non_html_ns(treebuilder)) { - treebuilder->context.mode = - treebuilder->context.second_mode; - } + process_as_in_secondary(treebuilder, token); } else if (type == B || type == BIG || type == BLOCKQUOTE || type == BODY || type == BR || type == CENTER || type == CODE || type == DD || type == DIV || @@ -99,20 +125,7 @@ bool handle_in_foreign_content(hubbub_treebuilder *treebuilder, type == STRIKE || type == SUB || type == SUP || type == TABLE || type == TT || type == U || type == UL || type == VAR) { - /** \todo parse error */ - - while (cur_node_ns != HUBBUB_NS_HTML) { - void *node; - element_stack_pop(treebuilder, &cur_node_ns, - &cur_node, &node); - treebuilder->tree_handler->unref_node( - treebuilder->tree_handler->ctx, - node); - cur_node_ns = current_node_ns(treebuilder); - } - - treebuilder->context.mode = - treebuilder->context.second_mode; + foreign_break_out(treebuilder); } else { hubbub_tag tag = token->data.tag; @@ -131,34 +144,10 @@ bool handle_in_foreign_content(hubbub_treebuilder *treebuilder, } break; case HUBBUB_TOKEN_END_TAG: - treebuilder->context.mode = - treebuilder->context.second_mode; - hubbub_treebuilder_token_handler(token, treebuilder); - - if (treebuilder->context.mode == IN_FOREIGN_CONTENT && - !element_in_scope_in_non_html_ns(treebuilder)) { - treebuilder->context.mode = - treebuilder->context.second_mode; - } - + process_as_in_secondary(treebuilder, token); break; case HUBBUB_TOKEN_EOF: - { - while (cur_node_ns != HUBBUB_NS_HTML) { - void *node; - element_stack_pop(treebuilder, &cur_node_ns, - &cur_node, &node); - treebuilder->tree_handler->unref_node( - treebuilder->tree_handler->ctx, - node); - cur_node_ns = current_node_ns(treebuilder); - } - - treebuilder->context.mode = - treebuilder->context.second_mode; - - reprocess = true; - } + foreign_break_out(treebuilder); break; } diff --git a/src/treebuilder/internal.h b/src/treebuilder/internal.h index b633fff..04ef26b 100644 --- a/src/treebuilder/internal.h +++ b/src/treebuilder/internal.h @@ -157,7 +157,6 @@ bool element_stack_pop_until(hubbub_treebuilder *treebuilder, element_type type); uint32_t current_table(hubbub_treebuilder *treebuilder); element_type current_node(hubbub_treebuilder *treebuilder); -hubbub_ns current_node_ns(hubbub_treebuilder *treebuilder); element_type prev_node(hubbub_treebuilder *treebuilder); bool formatting_list_append(hubbub_treebuilder *treebuilder, diff --git a/src/treebuilder/treebuilder.c b/src/treebuilder/treebuilder.c index 9a9f895..799c914 100644 --- a/src/treebuilder/treebuilder.c +++ b/src/treebuilder/treebuilder.c @@ -1180,18 +1180,6 @@ element_type current_node(hubbub_treebuilder *treebuilder) [treebuilder->context.current_node].type; } -/** - * Peek at the top element of the element stack. - * - * \param treebuilder Treebuilder instance - * \return Element type on the top of the stack - */ -hubbub_ns current_node_ns(hubbub_treebuilder *treebuilder) -{ - return treebuilder->context.element_stack - [treebuilder->context.current_node].ns; -} - /** * Peek at the element below the top of the element stack. * -- cgit v1.2.3