Example #1
0
static inline struct dom_node *
add_sgml_element(struct dom_stack *stack, struct dom_scanner_token *token)
{
	struct sgml_parser *parser = get_sgml_parser(stack);
	struct dom_node *parent = get_dom_stack_top(stack)->node;
	struct dom_stack_state *state;
	struct sgml_parser_state *pstate;
	struct dom_node *node;
	struct sgml_node_info *node_info;

	node = add_dom_element(parent, &token->string);
	if (!node) return NULL;

	node_info = get_sgml_node_info(parser->info->elements, node);
	node->data.element.type = node_info->type;

	if (!push_dom_node(stack, node))
		return NULL;

	state = get_dom_stack_top(stack);
	assert(node == state->node);

	pstate = get_sgml_parser_state(stack, state);
	pstate->info = node_info;

	return node;
}
Example #2
0
static inline void
add_sgml_attribute(struct dom_stack *stack,
		   struct dom_scanner_token *token, struct dom_scanner_token *valtoken)
{
	struct sgml_parser *parser = get_sgml_parser(stack);
	struct dom_node *parent = get_dom_stack_top(stack)->node;
	struct dom_string *value = valtoken ? &valtoken->string : NULL;
	struct sgml_node_info *info;
	struct dom_node *node;

	node = add_dom_attribute(parent, &token->string, value);

	info = get_sgml_node_info(parser->info->attributes, node);

	node->data.attribute.type      = info->type;
	node->data.attribute.id	       = !!(info->flags & SGML_ATTRIBUTE_IDENTIFIER);
	node->data.attribute.reference = !!(info->flags & SGML_ATTRIBUTE_REFERENCE);

	if (valtoken && valtoken->type == SGML_TOKEN_STRING)
		node->data.attribute.quoted = 1;

	if (!node || !push_dom_node(stack, node))
		return;

	pop_dom_node(stack);
}
Example #3
0
static inline struct dom_node *
add_sgml_document(struct dom_stack *stack, struct dom_string *string)
{
	struct dom_node *node = init_dom_node(DOM_NODE_DOCUMENT, string);

	return node ? push_dom_node(stack, node) : NULL;
}
Example #4
0
/* Create a new parsing state by pushing a new text node containing the*/
static struct sgml_parsing_state *
init_sgml_parsing_state(struct sgml_parser *parser, struct dom_string *buffer)
{
	struct dom_stack_state *state;
	struct dom_node *node;

	node = init_dom_node(DOM_NODE_TEXT, buffer);
	if (!node || !push_dom_node(&parser->parsing, node))
		return NULL;

	state = get_dom_stack_top(&parser->parsing);

	return get_dom_stack_state_data(parser->parsing.contexts[0], state);
}
Example #5
0
static inline void
add_sgml_node(struct dom_stack *stack, enum dom_node_type type, struct dom_scanner_token *token)
{
	struct dom_node *parent = get_dom_stack_top(stack)->node;
	struct dom_node *node = add_dom_node(parent, type, &token->string);

	if (!node) return;

	if (token->type == SGML_TOKEN_SPACE)
		node->data.text.only_space = 1;

	if (push_dom_node(stack, node))
		pop_dom_node(stack);
}
Example #6
0
static inline struct dom_node *
add_sgml_proc_instruction(struct dom_stack *stack, struct dom_scanner_token *target,
			  struct dom_scanner_token *data)
{
	struct dom_node *parent = get_dom_stack_top(stack)->node;
	struct dom_string *data_str = data ? &data->string : NULL;
	struct dom_node *node;

	node = add_dom_proc_instruction(parent, &target->string, data_str);
	if (!node) return NULL;

	switch (target->type) {
	case SGML_TOKEN_PROCESS_XML:
		node->data.proc_instruction.type = DOM_PROC_INSTRUCTION_XML;
		break;

	case SGML_TOKEN_PROCESS:
	default:
		node->data.proc_instruction.type = DOM_PROC_INSTRUCTION;
	}

	return push_dom_node(stack, node);
}
Example #7
0
File: select.c Project: ezc/elinks
/* Parse a CSS3 selector and add selector nodes to the @select struct. */
static enum dom_code
parse_dom_select(struct dom_select *select, struct dom_stack *stack,
		 struct dom_string *string)
{
	struct dom_scanner scanner;
	struct dom_select_node sel;

	init_dom_scanner(&scanner, &dom_css_scanner_info, string, 0, 0, 1, 0, 0);

	memset(&sel, 0, sizeof(sel));

	while (dom_scanner_has_tokens(&scanner)) {
		struct dom_scanner_token *token = get_dom_scanner_token(&scanner);
		enum dom_code code;
		struct dom_select_node *select_node;

		assert(token);

		if (token->type == '{'
		    || token->type == '}'
		    || token->type == ';'
		    || token->type == ',')
			break;

		/* Examine the selector fragment */

		switch (token->type) {
		case CSS_TOKEN_IDENT:
			sel.node.type = DOM_NODE_ELEMENT;
			copy_dom_string(&sel.node.string, &token->string);
			if (dom_scanner_token_contains(token, "*"))
				sel.match.element |= DOM_SELECT_ELEMENT_UNIVERSAL;
			break;

		case CSS_TOKEN_HASH:
		case CSS_TOKEN_HEX_COLOR:
			/* ID fragment */
			sel.node.type = DOM_NODE_ATTRIBUTE;
			sel.match.attribute |= DOM_SELECT_ATTRIBUTE_ID;
			/* Skip the leading '#'. */
			skip_dom_scanner_token_char(token);
			break;

		case '[':
			sel.node.type = DOM_NODE_ATTRIBUTE;
			code = parse_dom_select_attribute(&sel, &scanner);
			if (code != DOM_CODE_OK)
				return code;
			break;

		case '.':
			token = get_next_dom_scanner_token(&scanner);
			if (!token || token->type != CSS_TOKEN_IDENT)
				return DOM_CODE_SYNTAX_ERR;

			sel.node.type = DOM_NODE_ATTRIBUTE;
			sel.match.attribute |= DOM_SELECT_ATTRIBUTE_SPACE_LIST;
			set_dom_string(&sel.node.string, "class", -1);
			copy_dom_string(&sel.node.data.attribute.value, &token->string);
			break;

		case ':':
			code = parse_dom_select_pseudo(select, &sel, &scanner);
			if (code != DOM_CODE_OK)
				return code;
			break;

		case '>':
			if (get_element_relation(&sel) != DOM_SELECT_RELATION_DESCENDANT)
				return DOM_CODE_SYNTAX_ERR;
			sel.match.element |= DOM_SELECT_RELATION_DIRECT_CHILD;
			break;

		case '+':
			if (get_element_relation(&sel) != DOM_SELECT_RELATION_DESCENDANT)
				return DOM_CODE_SYNTAX_ERR;
			sel.match.element |= DOM_SELECT_RELATION_DIRECT_ADJACENT;
			break;

		case '~':
			if (get_element_relation(&sel) != DOM_SELECT_RELATION_DESCENDANT)
				return DOM_CODE_SYNTAX_ERR;
			sel.match.element |= DOM_SELECT_RELATION_INDIRECT_ADJACENT;
			break;

		default:
			return DOM_CODE_SYNTAX_ERR;
		}

		skip_dom_scanner_token(&scanner);

		if (sel.node.type == DOM_NODE_UNKNOWN)
			continue;

		select_node = mem_calloc(1, sizeof(*select_node));
		copy_struct(select_node, &sel);

		if (!dom_stack_is_empty(stack)) {
			struct dom_node *node = &select_node->node;
			struct dom_node *parent = get_dom_stack_top(stack)->node;
			struct dom_node_list **list = get_dom_node_list(parent, node);
			int sort = (node->type == DOM_NODE_ATTRIBUTE);
			int index;

			assertm(list != NULL, "Adding node to bad parent [%d -> %d]",
				node->type, parent->type);

			index = *list && (*list)->size > 0 && sort
				? get_dom_node_map_index(*list, node) : -1;

			if (!add_to_dom_node_list(list, node, index)) {
				done_dom_node(node);
				return DOM_CODE_ALLOC_ERR;
			}

			node->parent = parent;

		} else {
			assert(!select->selector);
			select->selector = select_node;
		}

		code = push_dom_node(stack, &select_node->node);
		if (code != DOM_CODE_OK)
			return code;

		if (select_node->node.type != DOM_NODE_ELEMENT)
			pop_dom_node(stack);

		memset(&sel, 0, sizeof(sel));
	}

	if (select->selector)
		return DOM_CODE_OK;

	return DOM_CODE_ERR;
}
Example #8
0
/* FIXME: Instead of walking all nodes in the tree only visit those which are
 * of actual interest to the contexts on the stack. */
void
walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
{
	struct dom_stack_context *context;

	assert(root && stack);

	context = add_dom_stack_context(stack, NULL, &dom_stack_walk_context_info);
	if (!context)
		return;

	if (push_dom_node(stack, root) != DOM_CODE_OK)
		return;

	while (!dom_stack_is_empty(stack)) {
		struct dom_stack_state *state = get_dom_stack_top(stack);
		struct dom_stack_walk_state *wstate = get_dom_stack_state_data(context, state);
		struct dom_node_list *list = wstate->list;
		struct dom_node *node = state->node;

		switch (node->type) {
		case DOM_NODE_DOCUMENT:
			if (!list) list = node->data.document.children;
			break;

		case DOM_NODE_ELEMENT:
			if (!list) list = node->data.element.map;

			if (list == node->data.element.children) break;
			if (is_dom_node_list_member(list, wstate->index)
			    && list == node->data.element.map)
				break;

			list = node->data.element.children;
			break;

		case DOM_NODE_PROCESSING_INSTRUCTION:
			if (!list) list = node->data.proc_instruction.map;
			break;

		case DOM_NODE_DOCUMENT_TYPE:
			if (!list) list = node->data.document_type.entities;

			if (list == node->data.document_type.notations) break;
			if (is_dom_node_list_member(list, wstate->index)
			    && list == node->data.document_type.entities)
				break;

			list = node->data.document_type.notations;
			break;

		case DOM_NODE_ATTRIBUTE:
		case DOM_NODE_TEXT:
		case DOM_NODE_CDATA_SECTION:
		case DOM_NODE_COMMENT:
		case DOM_NODE_NOTATION:
		case DOM_NODE_DOCUMENT_FRAGMENT:
		case DOM_NODE_ENTITY_REFERENCE:
		case DOM_NODE_ENTITY:
		default:
			break;
		}

		/* Reset list state if it is a new list */
		if (list != wstate->list) {
			wstate->list  = list;
			wstate->index = 0;
		}

		/* If we have next child node */
		if (is_dom_node_list_member(list, wstate->index)) {
			struct dom_node *child = list->entries[wstate->index++];

			if (push_dom_node(stack, child) == DOM_CODE_OK)
				continue;
		}

		pop_dom_node(stack);
	}

	done_dom_stack_context(stack, context);
}