From 5f23957d8aa0e55be3e658863e758dd954a28c92 Mon Sep 17 00:00:00 2001 From: Andrew Sidwell Date: Wed, 25 Jun 2008 08:54:18 +0000 Subject: Add the "in table body" insertion mode. svn path=/trunk/hubbub/; revision=4442 --- src/treebuilder/Makefile | 2 +- src/treebuilder/in_table_body.c | 170 ++++++++++++++++++++++++++++++++++++++++ src/treebuilder/modes.h | 2 + 3 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 src/treebuilder/in_table_body.c (limited to 'src/treebuilder') diff --git a/src/treebuilder/Makefile b/src/treebuilder/Makefile index 14af5b0..383a4bc 100644 --- a/src/treebuilder/Makefile +++ b/src/treebuilder/Makefile @@ -35,7 +35,7 @@ d := $(DIR) SRCS_$(d) := treebuilder.c \ initial.c before_html.c before_head.c in_head.c \ in_head_noscript.c after_head.c in_body.c \ - in_caption.c in_column_group.c \ + in_caption.c in_column_group.c in_table_body.c \ generic_rcdata.c script_collect.c # Append to sources for component diff --git a/src/treebuilder/in_table_body.c b/src/treebuilder/in_table_body.c new file mode 100644 index 0000000..ef91f55 --- /dev/null +++ b/src/treebuilder/in_table_body.c @@ -0,0 +1,170 @@ +/* + * This file is part of Hubbub. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2008 Andrew Sidwell + */ + +#include +#include + +#include "treebuilder/modes.h" +#include "treebuilder/internal.h" +#include "treebuilder/treebuilder.h" +#include "utils/utils.h" + + +/** + * Clear the stack back to a table body context. + * + * \param treebuilder The treebuilder instance + */ +static void table_clear_stack(hubbub_treebuilder *treebuilder) +{ + element_type cur_node = treebuilder->context.element_stack[ + treebuilder->context.current_node].type; + + while (cur_node != TBODY && cur_node != TFOOT && + cur_node != THEAD && cur_node != HTML) { + element_type type; + void *node; + + if (!element_stack_pop(treebuilder, &type, &node)) { + /** \todo errors */ + } + + cur_node = treebuilder->context.element_stack[ + treebuilder->context.current_node].type; + } + + return; +} + + +/** + * Handle the case common to some start tag and the table end tag cases. + * + * \param treebuilder The treebuilder instance + */ +static bool table_sub_start_or_table_end(hubbub_treebuilder *treebuilder) +{ + if (element_in_scope(treebuilder, TBODY, true) || + element_in_scope(treebuilder, THEAD, true) || + element_in_scope(treebuilder, TFOOT, true)) { + element_type otype; + void *node; + + table_clear_stack(treebuilder); + + /* "Act as if an end tag with the same name as the current + * node had been seen" -- this behaviour should be identical + * to handling for (tbody/tfoot/thead) end tags in this mode */ + if (!element_stack_pop(treebuilder, &otype, &node)) { + /** \todo errors */ + } + + treebuilder->context.mode = IN_TABLE; + + return true; + } else { + /** \todo parse error */ + } + + return false; +} + + +/** + * Handle tokens in "in column group" insertion mode + * + * Up to date with the spec as of 25 June 2008 + * + * \param treebuilder The treebuilder instance + * \param token The token to process + * \return True to reprocess the token, false otherwise + */ +bool handle_in_column_group(hubbub_treebuilder *treebuilder, + const hubbub_token *token) +{ + bool reprocess = false; + + switch (token->type) { + case HUBBUB_TOKEN_START_TAG: + { + element_type type = element_type_from_name(treebuilder, + &token->data.tag.name); + + if (type == TR) { + table_clear_stack(treebuilder); + insert_element(treebuilder, &token->data.tag); + treebuilder->context.mode = IN_ROW; + } else if (type == TH || TD) { + hubbub_tag tag; + + /** \todo parse error */ + + /* Manufacture tr tag */ + tag.name.type = HUBBUB_STRING_PTR; + tag.name.data.ptr = (const uint8_t *) "tr"; + tag.name.len = SLEN("tr"); + + tag.n_attributes = 0; + tag.attributes = NULL; + + insert_element(treebuilder, &tag); + treebuilder->context.mode = IN_ROW; + + reprocess = true; + } else if (type == CAPTION || type == COL || + type == COLGROUP || type == TBODY || + type == TFOOT || type == THEAD) { + table_sub_start_or_table_end(treebuilder); + } else { + reprocess = true; + } + } + break; + case HUBBUB_TOKEN_END_TAG: + { + element_type type = element_type_from_name(treebuilder, + &token->data.tag.name); + + if (type == TBODY || type == TFOOT || type == THEAD) { + if (!element_in_scope(treebuilder, type, true)) { + /** \todo parse error */ + /* Ignore the token */ + } else { + element_type otype; + void *node; + + table_clear_stack(treebuilder); + if (!element_stack_pop(treebuilder, &otype, + &node)) { + /** \todo errors */ + } + + treebuilder->context.mode = IN_TABLE; + } + } else if (type == TABLE) { + table_sub_start_or_table_end(treebuilder); + } else if (type == BODY || type == CAPTION || type == COL || + type == COLGROUP || type == HTML || + type == TD || type == TH || type == TR) { + /** \todo parse error */ + /* Ignore the token */ + } else { + reprocess = process_in_table(treebuilder, token); + } + } + break; + case HUBBUB_TOKEN_CHARACTER: + case HUBBUB_TOKEN_COMMENT: + case HUBBUB_TOKEN_DOCTYPE: + case HUBBUB_TOKEN_EOF: + reprocess = process_in_table(treebuilder, token); + break; + } + + return reprocess; +} + diff --git a/src/treebuilder/modes.h b/src/treebuilder/modes.h index 8f204aa..ebd2ab6 100644 --- a/src/treebuilder/modes.h +++ b/src/treebuilder/modes.h @@ -66,6 +66,8 @@ bool handle_script_collect_characters(hubbub_treebuilder *treebuilder, bool process_in_head(hubbub_treebuilder *treebuilder, const hubbub_token *token); +bool process_in_table(hubbub_treebuilder *treebuilder, + const hubbub_token *token); bool process_tag_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); -- cgit v1.2.3