summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Sidwell <andy@entai.co.uk>2008-07-11 17:07:57 +0000
committerAndrew Sidwell <andy@entai.co.uk>2008-07-11 17:07:57 +0000
commita0970535671dc059dab1ca2a02d053486d187ecf (patch)
tree4ddf1374df5c128bcfb5dbf07d4067e530884668
parent243656db3c7d0b00de8024a9bcb8050651b74dd7 (diff)
downloadlibhubbub-a0970535671dc059dab1ca2a02d053486d187ecf.tar.gz
libhubbub-a0970535671dc059dab1ca2a02d053486d187ecf.tar.bz2
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
-rw-r--r--src/treebuilder/in_foreign_content.c111
-rw-r--r--src/treebuilder/internal.h1
-rw-r--r--src/treebuilder/treebuilder.c12
3 files changed, 50 insertions, 74 deletions
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
@@ -1181,18 +1181,6 @@ element_type current_node(hubbub_treebuilder *treebuilder)
}
/**
- * 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.
*
* \param treebuilder Treebuilder instance