mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Rename DOM navigator -> stack
This is really a much more appropriate word since it never ended up being more than just a stack. The rename also changes the symbol names to use the much shorter "stack".
This commit is contained in:
parent
a0fb29bcd5
commit
bccfbf8647
@ -1,6 +1,6 @@
|
||||
top_builddir=../../..
|
||||
include $(top_builddir)/Makefile.config
|
||||
|
||||
OBJS = navigator.o node.o renderer.o
|
||||
OBJS = node.o renderer.o stack.o
|
||||
|
||||
include $(top_srcdir)/Makefile.lib
|
||||
|
@ -1,258 +0,0 @@
|
||||
/* The DOM tree navigation interface */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include "document/dom/navigator.h"
|
||||
#include "document/dom/node.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
|
||||
|
||||
/* Navigator states */
|
||||
|
||||
#define DOM_NAVIGATOR_STATE_GRANULARITY 0x7
|
||||
#define DOM_NAVIGATOR_CALLBACKS_SIZE (sizeof(dom_navigator_callback_T) * DOM_NODES)
|
||||
|
||||
static inline struct dom_navigator_state *
|
||||
realloc_dom_navigator_states(struct dom_navigator_state **states, size_t size)
|
||||
{
|
||||
return mem_align_alloc(states, size, size + 1,
|
||||
struct dom_navigator_state,
|
||||
DOM_NAVIGATOR_STATE_GRANULARITY);
|
||||
}
|
||||
|
||||
static inline unsigned char *
|
||||
realloc_dom_navigator_state_objects(struct dom_navigator *navigator)
|
||||
{
|
||||
#ifdef DEBUG_MEMLEAK
|
||||
return mem_align_alloc__(__FILE__, __LINE__, (void **) &navigator->state_objects,
|
||||
navigator->depth, navigator->depth + 1,
|
||||
navigator->object_size,
|
||||
DOM_NAVIGATOR_STATE_GRANULARITY);
|
||||
#else
|
||||
return mem_align_alloc__((void **) &navigator->state_objects,
|
||||
navigator->depth, navigator->depth + 1,
|
||||
navigator->object_size,
|
||||
DOM_NAVIGATOR_STATE_GRANULARITY);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
init_dom_navigator(struct dom_navigator *navigator, void *data,
|
||||
dom_navigator_callback_T callbacks[DOM_NODES],
|
||||
size_t object_size)
|
||||
{
|
||||
assert(navigator);
|
||||
|
||||
memset(navigator, 0, sizeof(*navigator));
|
||||
|
||||
navigator->data = data;
|
||||
navigator->object_size = object_size;
|
||||
|
||||
if (callbacks)
|
||||
memcpy(navigator->callbacks, callbacks, DOM_NAVIGATOR_CALLBACKS_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
done_dom_navigator(struct dom_navigator *navigator)
|
||||
{
|
||||
assert(navigator);
|
||||
|
||||
mem_free_if(navigator->states);
|
||||
mem_free_if(navigator->state_objects);
|
||||
|
||||
memset(navigator, 0, sizeof(*navigator));
|
||||
}
|
||||
|
||||
struct dom_node *
|
||||
push_dom_node(struct dom_navigator *navigator, struct dom_node *node)
|
||||
{
|
||||
dom_navigator_callback_T callback;
|
||||
struct dom_navigator_state *state;
|
||||
|
||||
assert(navigator && node);
|
||||
assert(0 < node->type && node->type < DOM_NODES);
|
||||
|
||||
if (navigator->depth > DOM_NAVIGATOR_MAX_DEPTH) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = realloc_dom_navigator_states(&navigator->states, navigator->depth);
|
||||
if (!state) {
|
||||
done_dom_node(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state += navigator->depth;
|
||||
|
||||
if (navigator->object_size) {
|
||||
unsigned char *state_objects;
|
||||
size_t offset = navigator->depth * navigator->object_size;
|
||||
|
||||
state_objects = realloc_dom_navigator_state_objects(navigator);
|
||||
if (!state_objects) {
|
||||
done_dom_node(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->data = (void *) &state_objects[offset];
|
||||
}
|
||||
|
||||
state->node = node;
|
||||
|
||||
/* Grow the state array to the new depth so the state accessors work
|
||||
* in the callbacks */
|
||||
navigator->depth++;
|
||||
|
||||
callback = navigator->callbacks[node->type];
|
||||
if (callback) {
|
||||
node = callback(navigator, node, state->data);
|
||||
|
||||
/* If the callback returned NULL pop the state immediately */
|
||||
if (!node) {
|
||||
memset(state, 0, sizeof(*state));
|
||||
navigator->depth--;
|
||||
assert(navigator->depth >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static int
|
||||
do_pop_dom_node(struct dom_navigator *navigator, struct dom_navigator_state *parent)
|
||||
{
|
||||
struct dom_navigator_state *state;
|
||||
|
||||
assert(navigator);
|
||||
if (!dom_navigator_has_parents(navigator)) return 0;
|
||||
|
||||
state = get_dom_navigator_top(navigator);
|
||||
if (state->callback) {
|
||||
/* Pass the node we are popping to and _not_ the state->node */
|
||||
state->callback(navigator, parent->node, state->data);
|
||||
}
|
||||
|
||||
navigator->depth--;
|
||||
assert(navigator->depth >= 0);
|
||||
|
||||
if (navigator->object_size && state->data) {
|
||||
size_t offset = navigator->depth * navigator->object_size;
|
||||
|
||||
/* I tried to use item->data here but it caused a memory
|
||||
* corruption bug on fm. This is also less trustworthy in that
|
||||
* the state->data pointer could have been mangled. --jonas */
|
||||
memset(&navigator->state_objects[offset], 0, navigator->object_size);
|
||||
}
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
return state == parent;
|
||||
}
|
||||
|
||||
void
|
||||
pop_dom_node(struct dom_navigator *navigator)
|
||||
{
|
||||
assert(navigator);
|
||||
if (!dom_navigator_has_parents(navigator)) return;
|
||||
|
||||
do_pop_dom_node(navigator, get_dom_navigator_parent(navigator));
|
||||
}
|
||||
|
||||
void
|
||||
pop_dom_nodes(struct dom_navigator *navigator, enum dom_node_type type,
|
||||
unsigned char *string, uint16_t length)
|
||||
{
|
||||
struct dom_navigator_state *state, *parent;
|
||||
unsigned int pos;
|
||||
|
||||
if (!dom_navigator_has_parents(navigator)) return;
|
||||
|
||||
parent = search_dom_navigator(navigator, type, string, length);
|
||||
if (!parent) return;
|
||||
|
||||
foreachback_dom_state (navigator, state, pos) {
|
||||
if (do_pop_dom_node(navigator, parent))
|
||||
break;;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
walk_dom_nodes(struct dom_navigator *navigator, struct dom_node *root)
|
||||
{
|
||||
assert(root && navigator);
|
||||
|
||||
push_dom_node(navigator, root);
|
||||
|
||||
while (dom_navigator_has_parents(navigator)) {
|
||||
struct dom_navigator_state *state = get_dom_navigator_top(navigator);
|
||||
struct dom_node_list *list = state->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, state->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, state->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 != state->list) {
|
||||
state->list = list;
|
||||
state->index = 0;
|
||||
}
|
||||
|
||||
/* If we have next child node */
|
||||
if (is_dom_node_list_member(list, state->index)) {
|
||||
struct dom_node *child = list->entries[state->index++];
|
||||
|
||||
if (push_dom_node(navigator, child))
|
||||
continue;
|
||||
}
|
||||
|
||||
pop_dom_node(navigator);
|
||||
}
|
||||
}
|
@ -16,9 +16,9 @@
|
||||
#include "document/css/stylesheet.h"
|
||||
#include "document/docdata.h"
|
||||
#include "document/document.h"
|
||||
#include "document/dom/navigator.h"
|
||||
#include "document/dom/node.h"
|
||||
#include "document/dom/renderer.h"
|
||||
#include "document/dom/stack.h"
|
||||
#include "document/renderer.h"
|
||||
#include "document/sgml/parser.h"
|
||||
#include "intl/charsets.h"
|
||||
@ -389,9 +389,9 @@ add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length)
|
||||
|
||||
#ifdef DOM_TREE_RENDERER
|
||||
static struct dom_node *
|
||||
render_dom_tree(struct dom_navigator *navigator, struct dom_node *node, void *data)
|
||||
render_dom_tree(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = navigator->data;
|
||||
struct dom_renderer *renderer = stack->data;
|
||||
struct screen_char *template = &renderer->styles[node->type];
|
||||
unsigned char *name, *value;
|
||||
|
||||
@ -409,9 +409,9 @@ render_dom_tree(struct dom_navigator *navigator, struct dom_node *node, void *da
|
||||
}
|
||||
|
||||
static struct dom_node *
|
||||
render_dom_tree_id_leaf(struct dom_navigator *navigator, struct dom_node *node, void *data)
|
||||
render_dom_tree_id_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = navigator->data;
|
||||
struct dom_renderer *renderer = stack->data;
|
||||
struct document *document = renderer->document;
|
||||
struct screen_char *template = &renderer->styles[node->type];
|
||||
unsigned char *name, *value, *id;
|
||||
@ -422,7 +422,7 @@ render_dom_tree_id_leaf(struct dom_navigator *navigator, struct dom_node *node,
|
||||
value = get_dom_node_value(node, document->options.cp);
|
||||
id = get_dom_node_type_name(node->type);
|
||||
|
||||
renderer->canvas_x += navigator->depth;
|
||||
renderer->canvas_x += stack->depth;
|
||||
render_dom_printf(renderer, template, "%-16s: %s -> %s\n", id, name, value);
|
||||
|
||||
mem_free_if(name);
|
||||
@ -432,9 +432,9 @@ render_dom_tree_id_leaf(struct dom_navigator *navigator, struct dom_node *node,
|
||||
}
|
||||
|
||||
static struct dom_node *
|
||||
render_dom_tree_leaf(struct dom_navigator *navigator, struct dom_node *node, void *data)
|
||||
render_dom_tree_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = navigator->data;
|
||||
struct dom_renderer *renderer = stack->data;
|
||||
struct document *document = renderer->document;
|
||||
struct screen_char *template = &renderer->styles[node->type];
|
||||
unsigned char *name, *value;
|
||||
@ -444,7 +444,7 @@ render_dom_tree_leaf(struct dom_navigator *navigator, struct dom_node *node, voi
|
||||
name = get_dom_node_name(node);
|
||||
value = get_dom_node_value(node, document->options.cp);
|
||||
|
||||
renderer->canvas_x += navigator->depth;
|
||||
renderer->canvas_x += stack->depth;
|
||||
render_dom_printf(renderer, template, "%-16s: %s\n", name, value);
|
||||
|
||||
mem_free_if(name);
|
||||
@ -454,9 +454,9 @@ render_dom_tree_leaf(struct dom_navigator *navigator, struct dom_node *node, voi
|
||||
}
|
||||
|
||||
static struct dom_node *
|
||||
render_dom_tree_branch(struct dom_navigator *navigator, struct dom_node *node, void *data)
|
||||
render_dom_tree_branch(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = navigator->data;
|
||||
struct dom_renderer *renderer = stack->data;
|
||||
struct document *document = renderer->document;
|
||||
struct screen_char *template = &renderer->styles[node->type];
|
||||
unsigned char *name, *id;
|
||||
@ -466,7 +466,7 @@ render_dom_tree_branch(struct dom_navigator *navigator, struct dom_node *node, v
|
||||
name = get_dom_node_name(node);
|
||||
id = get_dom_node_type_name(node->type);
|
||||
|
||||
renderer->canvas_x += navigator->depth;
|
||||
renderer->canvas_x += stack->depth;
|
||||
render_dom_printf(renderer, template, "%-16s: %s\n", id, name);
|
||||
|
||||
mem_free_if(name);
|
||||
@ -474,7 +474,7 @@ render_dom_tree_branch(struct dom_navigator *navigator, struct dom_node *node, v
|
||||
return node;
|
||||
}
|
||||
|
||||
static dom_navigator_callback_T dom_tree_renderer_callbacks[DOM_NODES] = {
|
||||
static dom_stack_callback_T dom_tree_renderer_callbacks[DOM_NODES] = {
|
||||
/* */ NULL,
|
||||
/* DOM_NODE_ELEMENT */ render_dom_tree_branch,
|
||||
/* DOM_NODE_ATTRIBUTE */ render_dom_tree_id_leaf,
|
||||
@ -538,9 +538,9 @@ render_dom_node_text(struct dom_renderer *renderer, struct screen_char *template
|
||||
}
|
||||
|
||||
static struct dom_node *
|
||||
render_dom_node_source(struct dom_navigator *navigator, struct dom_node *node, void *data)
|
||||
render_dom_node_source(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = navigator->data;
|
||||
struct dom_renderer *renderer = stack->data;
|
||||
|
||||
assert(node && renderer && renderer->document);
|
||||
|
||||
@ -552,9 +552,9 @@ render_dom_node_source(struct dom_navigator *navigator, struct dom_node *node, v
|
||||
}
|
||||
|
||||
static struct dom_node *
|
||||
render_dom_proc_instr_source(struct dom_navigator *navigator, struct dom_node *node, void *data)
|
||||
render_dom_proc_instr_source(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = navigator->data;
|
||||
struct dom_renderer *renderer = stack->data;
|
||||
unsigned char *value;
|
||||
int valuelen;
|
||||
|
||||
@ -579,9 +579,9 @@ render_dom_proc_instr_source(struct dom_navigator *navigator, struct dom_node *n
|
||||
}
|
||||
|
||||
static struct dom_node *
|
||||
render_dom_element_source(struct dom_navigator *navigator, struct dom_node *node, void *data)
|
||||
render_dom_element_source(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = navigator->data;
|
||||
struct dom_renderer *renderer = stack->data;
|
||||
|
||||
assert(node && renderer && renderer->document);
|
||||
|
||||
@ -591,10 +591,10 @@ render_dom_element_source(struct dom_navigator *navigator, struct dom_node *node
|
||||
}
|
||||
|
||||
static struct dom_node *
|
||||
render_dom_attribute_source(struct dom_navigator *navigator, struct dom_node *node, void *data)
|
||||
render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_navigator_state *state = get_dom_navigator_parent(navigator);
|
||||
struct dom_renderer *renderer = navigator->data;
|
||||
struct dom_stack_state *state = get_dom_stack_parent(stack);
|
||||
struct dom_renderer *renderer = stack->data;
|
||||
struct screen_char *template = &renderer->styles[node->type];
|
||||
struct dom_node *attribute = NULL;
|
||||
int i;
|
||||
@ -672,7 +672,7 @@ render_dom_attribute_source(struct dom_navigator *navigator, struct dom_node *no
|
||||
return node;
|
||||
}
|
||||
|
||||
static dom_navigator_callback_T dom_source_renderer_callbacks[DOM_NODES] = {
|
||||
static dom_stack_callback_T dom_source_renderer_callbacks[DOM_NODES] = {
|
||||
/* */ NULL,
|
||||
/* DOM_NODE_ELEMENT */ render_dom_element_source,
|
||||
/* DOM_NODE_ATTRIBUTE */ render_dom_attribute_source,
|
||||
@ -698,8 +698,8 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
||||
struct dom_node *root = parse_sgml(cached, document, buffer);
|
||||
struct dom_renderer renderer;
|
||||
struct conv_table *convert_table;
|
||||
dom_navigator_callback_T *callbacks = dom_source_renderer_callbacks;
|
||||
struct dom_navigator navigator;
|
||||
dom_stack_callback_T *callbacks = dom_source_renderer_callbacks;
|
||||
struct dom_stack stack;
|
||||
|
||||
assert(document->options.plain);
|
||||
if (!root) return;
|
||||
@ -711,11 +711,11 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
||||
document->options.hard_assume);
|
||||
|
||||
init_dom_renderer(&renderer, document, buffer, root, convert_table);
|
||||
init_dom_navigator(&navigator, &renderer, callbacks, 0);
|
||||
init_dom_stack(&stack, &renderer, callbacks, 0);
|
||||
|
||||
document->bgcolor = document->options.default_bg;
|
||||
|
||||
walk_dom_nodes(&navigator, root);
|
||||
walk_dom_nodes(&stack, root);
|
||||
/* If there are no non-element nodes after the last element node make
|
||||
* sure that we flush to the end of the cache entry source including
|
||||
* the '>' of the last element tag if it has one. (bug 519) */
|
||||
@ -724,5 +724,5 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
||||
}
|
||||
|
||||
done_dom_node(root);
|
||||
done_dom_navigator(&navigator);
|
||||
done_dom_stack(&stack);
|
||||
}
|
||||
|
258
src/document/dom/stack.c
Normal file
258
src/document/dom/stack.c
Normal file
@ -0,0 +1,258 @@
|
||||
/* The DOM tree navigation interface */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include "document/dom/node.h"
|
||||
#include "document/dom/stack.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
|
||||
|
||||
/* Navigator states */
|
||||
|
||||
#define DOM_STACK_STATE_GRANULARITY 0x7
|
||||
#define DOM_STACK_CALLBACKS_SIZE (sizeof(dom_stack_callback_T) * DOM_NODES)
|
||||
|
||||
static inline struct dom_stack_state *
|
||||
realloc_dom_stack_states(struct dom_stack_state **states, size_t size)
|
||||
{
|
||||
return mem_align_alloc(states, size, size + 1,
|
||||
struct dom_stack_state,
|
||||
DOM_STACK_STATE_GRANULARITY);
|
||||
}
|
||||
|
||||
static inline unsigned char *
|
||||
realloc_dom_stack_state_objects(struct dom_stack *stack)
|
||||
{
|
||||
#ifdef DEBUG_MEMLEAK
|
||||
return mem_align_alloc__(__FILE__, __LINE__, (void **) &stack->state_objects,
|
||||
stack->depth, stack->depth + 1,
|
||||
stack->object_size,
|
||||
DOM_STACK_STATE_GRANULARITY);
|
||||
#else
|
||||
return mem_align_alloc__((void **) &stack->state_objects,
|
||||
stack->depth, stack->depth + 1,
|
||||
stack->object_size,
|
||||
DOM_STACK_STATE_GRANULARITY);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
init_dom_stack(struct dom_stack *stack, void *data,
|
||||
dom_stack_callback_T callbacks[DOM_NODES],
|
||||
size_t object_size)
|
||||
{
|
||||
assert(stack);
|
||||
|
||||
memset(stack, 0, sizeof(*stack));
|
||||
|
||||
stack->data = data;
|
||||
stack->object_size = object_size;
|
||||
|
||||
if (callbacks)
|
||||
memcpy(stack->callbacks, callbacks, DOM_STACK_CALLBACKS_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
done_dom_stack(struct dom_stack *stack)
|
||||
{
|
||||
assert(stack);
|
||||
|
||||
mem_free_if(stack->states);
|
||||
mem_free_if(stack->state_objects);
|
||||
|
||||
memset(stack, 0, sizeof(*stack));
|
||||
}
|
||||
|
||||
struct dom_node *
|
||||
push_dom_node(struct dom_stack *stack, struct dom_node *node)
|
||||
{
|
||||
dom_stack_callback_T callback;
|
||||
struct dom_stack_state *state;
|
||||
|
||||
assert(stack && node);
|
||||
assert(0 < node->type && node->type < DOM_NODES);
|
||||
|
||||
if (stack->depth > DOM_STACK_MAX_DEPTH) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = realloc_dom_stack_states(&stack->states, stack->depth);
|
||||
if (!state) {
|
||||
done_dom_node(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state += stack->depth;
|
||||
|
||||
if (stack->object_size) {
|
||||
unsigned char *state_objects;
|
||||
size_t offset = stack->depth * stack->object_size;
|
||||
|
||||
state_objects = realloc_dom_stack_state_objects(stack);
|
||||
if (!state_objects) {
|
||||
done_dom_node(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->data = (void *) &state_objects[offset];
|
||||
}
|
||||
|
||||
state->node = node;
|
||||
|
||||
/* Grow the state array to the new depth so the state accessors work
|
||||
* in the callbacks */
|
||||
stack->depth++;
|
||||
|
||||
callback = stack->callbacks[node->type];
|
||||
if (callback) {
|
||||
node = callback(stack, node, state->data);
|
||||
|
||||
/* If the callback returned NULL pop the state immediately */
|
||||
if (!node) {
|
||||
memset(state, 0, sizeof(*state));
|
||||
stack->depth--;
|
||||
assert(stack->depth >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static int
|
||||
do_pop_dom_node(struct dom_stack *stack, struct dom_stack_state *parent)
|
||||
{
|
||||
struct dom_stack_state *state;
|
||||
|
||||
assert(stack);
|
||||
if (!dom_stack_has_parents(stack)) return 0;
|
||||
|
||||
state = get_dom_stack_top(stack);
|
||||
if (state->callback) {
|
||||
/* Pass the node we are popping to and _not_ the state->node */
|
||||
state->callback(stack, parent->node, state->data);
|
||||
}
|
||||
|
||||
stack->depth--;
|
||||
assert(stack->depth >= 0);
|
||||
|
||||
if (stack->object_size && state->data) {
|
||||
size_t offset = stack->depth * stack->object_size;
|
||||
|
||||
/* I tried to use item->data here but it caused a memory
|
||||
* corruption bug on fm. This is also less trustworthy in that
|
||||
* the state->data pointer could have been mangled. --jonas */
|
||||
memset(&stack->state_objects[offset], 0, stack->object_size);
|
||||
}
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
return state == parent;
|
||||
}
|
||||
|
||||
void
|
||||
pop_dom_node(struct dom_stack *stack)
|
||||
{
|
||||
assert(stack);
|
||||
if (!dom_stack_has_parents(stack)) return;
|
||||
|
||||
do_pop_dom_node(stack, get_dom_stack_parent(stack));
|
||||
}
|
||||
|
||||
void
|
||||
pop_dom_nodes(struct dom_stack *stack, enum dom_node_type type,
|
||||
unsigned char *string, uint16_t length)
|
||||
{
|
||||
struct dom_stack_state *state, *parent;
|
||||
unsigned int pos;
|
||||
|
||||
if (!dom_stack_has_parents(stack)) return;
|
||||
|
||||
parent = search_dom_stack(stack, type, string, length);
|
||||
if (!parent) return;
|
||||
|
||||
foreachback_dom_state (stack, state, pos) {
|
||||
if (do_pop_dom_node(stack, parent))
|
||||
break;;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
|
||||
{
|
||||
assert(root && stack);
|
||||
|
||||
push_dom_node(stack, root);
|
||||
|
||||
while (dom_stack_has_parents(stack)) {
|
||||
struct dom_stack_state *state = get_dom_stack_top(stack);
|
||||
struct dom_node_list *list = state->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, state->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, state->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 != state->list) {
|
||||
state->list = list;
|
||||
state->index = 0;
|
||||
}
|
||||
|
||||
/* If we have next child node */
|
||||
if (is_dom_node_list_member(list, state->index)) {
|
||||
struct dom_node *child = list->entries[state->index++];
|
||||
|
||||
if (push_dom_node(stack, child))
|
||||
continue;
|
||||
}
|
||||
|
||||
pop_dom_node(stack);
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
|
||||
#ifndef EL__DOCUMENT_DOM_NAVIGATOR_H
|
||||
#define EL__DOCUMENT_DOM_NAVIGATOR_H
|
||||
#ifndef EL__DOCUMENT_DOM_STACK_H
|
||||
#define EL__DOCUMENT_DOM_STACK_H
|
||||
|
||||
#include "document/document.h"
|
||||
#include "document/dom/node.h"
|
||||
#include "util/error.h"
|
||||
#include "util/hash.h"
|
||||
|
||||
struct dom_navigator;
|
||||
struct dom_stack;
|
||||
|
||||
enum dom_exception_code {
|
||||
DOM_ERR_NONE = 0,
|
||||
@ -31,26 +31,26 @@ enum dom_exception_code {
|
||||
};
|
||||
|
||||
typedef struct dom_node *
|
||||
(*dom_navigator_callback_T)(struct dom_navigator *, struct dom_node *, void *);
|
||||
(*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void *);
|
||||
|
||||
#define DOM_NAVIGATOR_MAX_DEPTH 4096
|
||||
#define DOM_STACK_MAX_DEPTH 4096
|
||||
|
||||
struct dom_navigator_state {
|
||||
struct dom_stack_state {
|
||||
struct dom_node *node;
|
||||
|
||||
struct dom_node_list *list;
|
||||
size_t index;
|
||||
|
||||
dom_navigator_callback_T callback;
|
||||
dom_stack_callback_T callback;
|
||||
void *data;
|
||||
};
|
||||
|
||||
/* The DOM navigator is a convenient way to traverse DOM trees. Also it
|
||||
/* The DOM stack is a convenient way to traverse DOM trees. Also it
|
||||
* maintains needed state info and is therefore also a holder of the current
|
||||
* context since the navigator is used to when the DOM tree is manipulated. */
|
||||
struct dom_navigator {
|
||||
* context since the stack is used to when the DOM tree is manipulated. */
|
||||
struct dom_stack {
|
||||
/* The stack of nodes */
|
||||
struct dom_navigator_state *states;
|
||||
struct dom_stack_state *states;
|
||||
size_t depth;
|
||||
|
||||
unsigned char *state_objects;
|
||||
@ -60,23 +60,23 @@ struct dom_navigator {
|
||||
enum dom_exception_code exception;
|
||||
|
||||
/* Parser and document specific stuff */
|
||||
dom_navigator_callback_T callbacks[DOM_NODES];
|
||||
dom_stack_callback_T callbacks[DOM_NODES];
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define dom_navigator_has_parents(nav) \
|
||||
#define dom_stack_has_parents(nav) \
|
||||
((nav)->states && (nav)->depth > 0)
|
||||
|
||||
static inline struct dom_navigator_state *
|
||||
get_dom_navigator_state(struct dom_navigator *navigator, int top_offset)
|
||||
static inline struct dom_stack_state *
|
||||
get_dom_stack_state(struct dom_stack *stack, int top_offset)
|
||||
{
|
||||
assertm(navigator->depth - 1 - top_offset >= 0,
|
||||
assertm(stack->depth - 1 - top_offset >= 0,
|
||||
"Attempting to access invalid state");
|
||||
return &navigator->states[navigator->depth - 1 - top_offset];
|
||||
return &stack->states[stack->depth - 1 - top_offset];
|
||||
}
|
||||
|
||||
#define get_dom_navigator_parent(nav) get_dom_navigator_state(nav, 1)
|
||||
#define get_dom_navigator_top(nav) get_dom_navigator_state(nav, 0)
|
||||
#define get_dom_stack_parent(nav) get_dom_stack_state(nav, 1)
|
||||
#define get_dom_stack_top(nav) get_dom_stack_state(nav, 0)
|
||||
|
||||
/* The state iterators do not include the bottom state */
|
||||
|
||||
@ -88,15 +88,15 @@ get_dom_navigator_state(struct dom_navigator *navigator, int top_offset)
|
||||
for ((pos) = (nav)->depth - 1; (pos) > 0; (pos)--) \
|
||||
if (((item) = &(nav)->states[(pos)]))
|
||||
|
||||
/* Dive through the navigator states in search for the specified match. */
|
||||
static inline struct dom_navigator_state *
|
||||
search_dom_navigator(struct dom_navigator *navigator, enum dom_node_type type,
|
||||
unsigned char *string, uint16_t length)
|
||||
/* Dive through the stack states in search for the specified match. */
|
||||
static inline struct dom_stack_state *
|
||||
search_dom_stack(struct dom_stack *stack, enum dom_node_type type,
|
||||
unsigned char *string, uint16_t length)
|
||||
{
|
||||
struct dom_navigator_state *state;
|
||||
struct dom_stack_state *state;
|
||||
int pos;
|
||||
|
||||
foreachback_dom_state (navigator, state, pos) {
|
||||
foreachback_dom_state (stack, state, pos) {
|
||||
struct dom_node *parent = state->node;
|
||||
|
||||
if (parent->type == type
|
||||
@ -111,24 +111,26 @@ search_dom_navigator(struct dom_navigator *navigator, enum dom_node_type type,
|
||||
|
||||
/* Life cycle functions. */
|
||||
|
||||
/* The @object_size arg tells whether the navigator should allocate objects for each
|
||||
/* The @object_size arg tells whether the stack should allocate objects for each
|
||||
* state to be assigned to the state's @data member. Zero means no state data should
|
||||
* be allocated. */
|
||||
void init_dom_navigator(struct dom_navigator *navigator, void *data, dom_navigator_callback_T callbacks[DOM_NODES], size_t object_size);
|
||||
void done_dom_navigator(struct dom_navigator *navigator);
|
||||
void init_dom_stack(struct dom_stack *stack, void *data,
|
||||
dom_stack_callback_T callbacks[DOM_NODES],
|
||||
size_t object_size);
|
||||
void done_dom_stack(struct dom_stack *stack);
|
||||
|
||||
/* Decends down to the given node making it the current parent */
|
||||
/* If an error occurs the node is free()d and NULL is returned */
|
||||
struct dom_node *push_dom_node(struct dom_navigator *navigator, struct dom_node *node);
|
||||
struct dom_node *push_dom_node(struct dom_stack *stack, struct dom_node *node);
|
||||
|
||||
/* Ascends the navigator to the current parent */
|
||||
void pop_dom_node(struct dom_navigator *navigator);
|
||||
/* Ascends the stack to the current parent */
|
||||
void pop_dom_node(struct dom_stack *stack);
|
||||
|
||||
/* Ascends the navigator looking for specific parent */
|
||||
void pop_dom_nodes(struct dom_navigator *navigator, enum dom_node_type type,
|
||||
/* Ascends the stack looking for specific parent */
|
||||
void pop_dom_nodes(struct dom_stack *stack, enum dom_node_type type,
|
||||
unsigned char *string, uint16_t length);
|
||||
|
||||
/* Visit each node in the tree rooted at @root pre-order */
|
||||
void walk_dom_nodes(struct dom_navigator *navigator, struct dom_node *root);
|
||||
void walk_dom_nodes(struct dom_stack *stack, struct dom_node *root);
|
||||
|
||||
#endif
|
@ -9,8 +9,8 @@
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include "document/dom/navigator.h"
|
||||
#include "document/dom/node.h"
|
||||
#include "document/dom/stack.h"
|
||||
#include "document/sgml/html/html.h"
|
||||
#include "document/sgml/parser.h"
|
||||
#include "document/sgml/scanner.h"
|
||||
@ -38,20 +38,20 @@ static struct sgml_node_info html_elements[HTML_ELEMENTS] = {
|
||||
|
||||
|
||||
static struct dom_node *
|
||||
add_html_element_end_node(struct dom_navigator *navigator, struct dom_node *node, void *data)
|
||||
add_html_element_end_node(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct sgml_parser *parser = navigator->data;
|
||||
struct sgml_parser *parser = stack->data;
|
||||
struct dom_node *parent;
|
||||
struct scanner_token *token;
|
||||
|
||||
assert(navigator && parser && node);
|
||||
assert(dom_navigator_has_parents(navigator));
|
||||
assert(stack && parser && node);
|
||||
assert(dom_stack_has_parents(stack));
|
||||
|
||||
/* Are we the actual node being popped? */
|
||||
if (node != get_dom_navigator_top(navigator)->node)
|
||||
if (node != get_dom_stack_top(stack)->node)
|
||||
return NULL;
|
||||
|
||||
parent = get_dom_navigator_parent(navigator)->node;
|
||||
parent = get_dom_stack_parent(stack)->node;
|
||||
token = get_scanner_token(&parser->scanner);
|
||||
|
||||
assertm(token, "No token found in callback");
|
||||
@ -65,17 +65,17 @@ add_html_element_end_node(struct dom_navigator *navigator, struct dom_node *node
|
||||
/* TODO: We need to handle ascending of <br> and "<p>text1<p>text2" using data
|
||||
* from sgml_node_info. */
|
||||
static struct dom_node *
|
||||
add_html_element_node(struct dom_navigator *navigator, struct dom_node *node, void *data)
|
||||
add_html_element_node(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct sgml_parser *parser = navigator->data;
|
||||
struct sgml_parser *parser = stack->data;
|
||||
|
||||
assert(navigator && node);
|
||||
assert(dom_navigator_has_parents(navigator));
|
||||
assert(stack && node);
|
||||
assert(dom_stack_has_parents(stack));
|
||||
|
||||
/* TODO: Move to SGML parser main loop and disguise these element ends
|
||||
* in some internal processing instruction. */
|
||||
if (parser->flags & SGML_PARSER_ADD_ELEMENT_ENDS)
|
||||
get_dom_navigator_top(navigator)->callback = add_html_element_end_node;
|
||||
get_dom_stack_top(stack)->callback = add_html_element_end_node;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#ifndef EL__DOCUMENT_SGML_HTML_HTML_H
|
||||
#define EL__DOCUMENT_SGML_HTML_HTML_H
|
||||
|
||||
#include "document/dom/navigator.h"
|
||||
#include "document/dom/stack.h"
|
||||
#include "document/sgml/sgml.h"
|
||||
|
||||
extern struct sgml_info sgml_html_info;
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
#include "cache/cache.h"
|
||||
#include "document/document.h"
|
||||
#include "document/dom/navigator.h"
|
||||
#include "document/dom/node.h"
|
||||
#include "document/dom/stack.h"
|
||||
#include "document/html/renderer.h" /* TODO: Move get_convert_table() */
|
||||
#include "document/sgml/html/html.h"
|
||||
#include "document/sgml/parser.h"
|
||||
@ -29,30 +29,30 @@
|
||||
/* Functions for adding new nodes to the DOM tree */
|
||||
|
||||
static inline struct dom_node *
|
||||
add_sgml_document(struct dom_navigator *navigator, struct uri *uri)
|
||||
add_sgml_document(struct dom_stack *stack, struct uri *uri)
|
||||
{
|
||||
unsigned char *string = struri(uri);
|
||||
int length = strlen(string);
|
||||
struct dom_node *node = init_dom_node(DOM_NODE_DOCUMENT, string, length);
|
||||
|
||||
return node ? push_dom_node(navigator, node) : node;
|
||||
return node ? push_dom_node(stack, node) : node;
|
||||
}
|
||||
|
||||
static inline struct dom_node *
|
||||
add_sgml_element(struct dom_navigator *navigator, struct scanner_token *token)
|
||||
add_sgml_element(struct dom_stack *stack, struct scanner_token *token)
|
||||
{
|
||||
struct sgml_parser *parser = navigator->data;
|
||||
struct dom_node *parent = get_dom_navigator_top(navigator)->node;
|
||||
struct dom_navigator_state *state;
|
||||
struct sgml_parser *parser = stack->data;
|
||||
struct dom_node *parent = get_dom_stack_top(stack)->node;
|
||||
struct dom_stack_state *state;
|
||||
struct sgml_parser_state *pstate;
|
||||
struct dom_node *node;
|
||||
|
||||
node = add_dom_element(parent, token->string, token->length);
|
||||
|
||||
if (!node || !push_dom_node(navigator, node))
|
||||
if (!node || !push_dom_node(stack, node))
|
||||
return NULL;
|
||||
|
||||
state = get_dom_navigator_top(navigator);
|
||||
state = get_dom_stack_top(stack);
|
||||
assert(node == state->node && state->data);
|
||||
|
||||
pstate = state->data;
|
||||
@ -64,11 +64,11 @@ add_sgml_element(struct dom_navigator *navigator, struct scanner_token *token)
|
||||
|
||||
|
||||
static inline void
|
||||
add_sgml_attribute(struct dom_navigator *navigator,
|
||||
add_sgml_attribute(struct dom_stack *stack,
|
||||
struct scanner_token *token, struct scanner_token *valtoken)
|
||||
{
|
||||
struct sgml_parser *parser = navigator->data;
|
||||
struct dom_node *parent = get_dom_navigator_top(navigator)->node;
|
||||
struct sgml_parser *parser = stack->data;
|
||||
struct dom_node *parent = get_dom_stack_top(stack)->node;
|
||||
unsigned char *value = valtoken ? valtoken->string : NULL;
|
||||
uint16_t valuelen = valtoken ? valtoken->length : 0;
|
||||
struct sgml_node_info *info;
|
||||
@ -77,7 +77,7 @@ add_sgml_attribute(struct dom_navigator *navigator,
|
||||
node = add_dom_attribute(parent, token->string, token->length,
|
||||
value, valuelen);
|
||||
|
||||
if (!node || !push_dom_node(navigator, node))
|
||||
if (!node || !push_dom_node(stack, node))
|
||||
return;
|
||||
|
||||
info = get_sgml_node_info(parser->info->attributes, node);
|
||||
@ -89,13 +89,13 @@ add_sgml_attribute(struct dom_navigator *navigator,
|
||||
if (valtoken && valtoken->type == SGML_TOKEN_STRING)
|
||||
node->data.attribute.quoted = 1;
|
||||
|
||||
pop_dom_node(navigator);
|
||||
pop_dom_node(stack);
|
||||
}
|
||||
|
||||
static inline struct dom_node *
|
||||
add_sgml_proc_instruction(struct dom_navigator *navigator, struct scanner_token *token)
|
||||
add_sgml_proc_instruction(struct dom_stack *stack, struct scanner_token *token)
|
||||
{
|
||||
struct dom_node *parent = get_dom_navigator_top(navigator)->node;
|
||||
struct dom_node *parent = get_dom_stack_top(stack)->node;
|
||||
struct dom_node *node;
|
||||
/* Split the token in two if we can find a first space separator. */
|
||||
unsigned char *separator = memchr(token->string, ' ', token->length);
|
||||
@ -121,19 +121,19 @@ add_sgml_proc_instruction(struct dom_navigator *navigator, struct scanner_token
|
||||
node->data.proc_instruction.type = DOM_PROC_INSTRUCTION;
|
||||
}
|
||||
|
||||
if (!push_dom_node(navigator, node))
|
||||
if (!push_dom_node(stack, node))
|
||||
return NULL;
|
||||
|
||||
if (token->type != SGML_TOKEN_PROCESS_XML)
|
||||
pop_dom_node(navigator);
|
||||
pop_dom_node(stack);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_sgml_node(struct dom_navigator *navigator, enum dom_node_type type, struct scanner_token *token)
|
||||
add_sgml_node(struct dom_stack *stack, enum dom_node_type type, struct scanner_token *token)
|
||||
{
|
||||
struct dom_node *parent = get_dom_navigator_top(navigator)->node;
|
||||
struct dom_node *parent = get_dom_stack_top(stack)->node;
|
||||
struct dom_node *node = add_dom_node(parent, type, token->string, token->length);
|
||||
|
||||
if (!node) return;
|
||||
@ -141,16 +141,16 @@ add_sgml_node(struct dom_navigator *navigator, enum dom_node_type type, struct s
|
||||
if (token->type == SGML_TOKEN_SPACE)
|
||||
node->data.text.only_space = 1;
|
||||
|
||||
if (push_dom_node(navigator, node))
|
||||
pop_dom_node(navigator);
|
||||
if (push_dom_node(stack, node))
|
||||
pop_dom_node(stack);
|
||||
}
|
||||
|
||||
#define add_sgml_entityref(nav, t) add_sgml_node(nav, DOM_NODE_ENTITY_REFERENCE, t)
|
||||
#define add_sgml_text(nav, t) add_sgml_node(nav, DOM_NODE_TEXT, t)
|
||||
#define add_sgml_comment(nav, t) add_sgml_node(nav, DOM_NODE_COMMENT, t)
|
||||
#define add_sgml_entityref(stack, t) add_sgml_node(stack, DOM_NODE_ENTITY_REFERENCE, t)
|
||||
#define add_sgml_text(stack, t) add_sgml_node(stack, DOM_NODE_TEXT, t)
|
||||
#define add_sgml_comment(stack, t) add_sgml_node(stack, DOM_NODE_COMMENT, t)
|
||||
|
||||
static inline void
|
||||
parse_sgml_attributes(struct dom_navigator *navigator, struct scanner *scanner)
|
||||
parse_sgml_attributes(struct dom_stack *stack, struct scanner *scanner)
|
||||
{
|
||||
struct scanner_token name;
|
||||
|
||||
@ -193,7 +193,7 @@ parse_sgml_attributes(struct dom_navigator *navigator, struct scanner *scanner)
|
||||
token = NULL;
|
||||
}
|
||||
|
||||
add_sgml_attribute(navigator, &name, token);
|
||||
add_sgml_attribute(stack, &name, token);
|
||||
|
||||
/* Skip the value token */
|
||||
if (token)
|
||||
@ -208,7 +208,7 @@ parse_sgml_attributes(struct dom_navigator *navigator, struct scanner *scanner)
|
||||
}
|
||||
|
||||
void
|
||||
parse_sgml_document(struct dom_navigator *navigator, struct scanner *scanner)
|
||||
parse_sgml_document(struct dom_stack *stack, struct scanner *scanner)
|
||||
{
|
||||
while (scanner_has_tokens(scanner)) {
|
||||
struct scanner_token *token = get_scanner_token(scanner);
|
||||
@ -216,7 +216,7 @@ parse_sgml_document(struct dom_navigator *navigator, struct scanner *scanner)
|
||||
switch (token->type) {
|
||||
case SGML_TOKEN_ELEMENT:
|
||||
case SGML_TOKEN_ELEMENT_BEGIN:
|
||||
if (!add_sgml_element(navigator, token)) {
|
||||
if (!add_sgml_element(stack, token)) {
|
||||
if (token->type == SGML_TOKEN_ELEMENT) {
|
||||
skip_scanner_token(scanner);
|
||||
break;
|
||||
@ -227,7 +227,7 @@ parse_sgml_document(struct dom_navigator *navigator, struct scanner *scanner)
|
||||
}
|
||||
|
||||
if (token->type == SGML_TOKEN_ELEMENT_BEGIN) {
|
||||
parse_sgml_attributes(navigator, scanner);
|
||||
parse_sgml_attributes(stack, scanner);
|
||||
} else {
|
||||
skip_scanner_token(scanner);
|
||||
}
|
||||
@ -235,22 +235,22 @@ parse_sgml_document(struct dom_navigator *navigator, struct scanner *scanner)
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_ELEMENT_EMPTY_END:
|
||||
pop_dom_node(navigator);
|
||||
pop_dom_node(stack);
|
||||
skip_scanner_token(scanner);
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_ELEMENT_END:
|
||||
if (!token->length) {
|
||||
pop_dom_node(navigator);
|
||||
pop_dom_node(stack);
|
||||
} else {
|
||||
pop_dom_nodes(navigator, DOM_NODE_ELEMENT,
|
||||
pop_dom_nodes(stack, DOM_NODE_ELEMENT,
|
||||
token->string, token->length);
|
||||
}
|
||||
skip_scanner_token(scanner);
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_NOTATION_COMMENT:
|
||||
add_sgml_comment(navigator, token);
|
||||
add_sgml_comment(stack, token);
|
||||
skip_scanner_token(scanner);
|
||||
break;
|
||||
|
||||
@ -263,29 +263,29 @@ parse_sgml_document(struct dom_navigator *navigator, struct scanner *scanner)
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_PROCESS_XML:
|
||||
if (!add_sgml_proc_instruction(navigator, token)) {
|
||||
if (!add_sgml_proc_instruction(stack, token)) {
|
||||
skip_sgml_tokens(scanner, SGML_TOKEN_TAG_END);
|
||||
break;
|
||||
}
|
||||
|
||||
parse_sgml_attributes(navigator, scanner);
|
||||
pop_dom_node(navigator);
|
||||
parse_sgml_attributes(stack, scanner);
|
||||
pop_dom_node(stack);
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_PROCESS:
|
||||
add_sgml_proc_instruction(navigator, token);
|
||||
add_sgml_proc_instruction(stack, token);
|
||||
skip_scanner_token(scanner);
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_ENTITY:
|
||||
add_sgml_entityref(navigator, token);
|
||||
add_sgml_entityref(stack, token);
|
||||
skip_scanner_token(scanner);
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_SPACE:
|
||||
case SGML_TOKEN_TEXT:
|
||||
default:
|
||||
add_sgml_text(navigator, token);
|
||||
add_sgml_text(stack, token);
|
||||
skip_scanner_token(scanner);
|
||||
}
|
||||
}
|
||||
@ -316,19 +316,19 @@ struct dom_node *
|
||||
parse_sgml(struct cache_entry *cached, struct document *document,
|
||||
struct string *buffer)
|
||||
{
|
||||
struct dom_navigator navigator;
|
||||
struct dom_stack stack;
|
||||
struct sgml_parser parser;
|
||||
size_t obj_size = sizeof(struct sgml_parser_state);
|
||||
|
||||
init_sgml_parser(&parser, document, cached, &sgml_html_info, buffer);
|
||||
init_dom_navigator(&navigator, &parser, parser.info->callbacks, obj_size);
|
||||
init_dom_stack(&stack, &parser, parser.info->callbacks, obj_size);
|
||||
|
||||
parser.root = add_sgml_document(&navigator, document->uri);
|
||||
parser.root = add_sgml_document(&stack, document->uri);
|
||||
if (parser.root) {
|
||||
parse_sgml_document(&navigator, &parser.scanner);
|
||||
parse_sgml_document(&stack, &parser.scanner);
|
||||
}
|
||||
|
||||
done_dom_navigator(&navigator);
|
||||
done_dom_stack(&stack);
|
||||
|
||||
return parser.root;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include "document/dom/navigator.h"
|
||||
#include "document/dom/node.h"
|
||||
#include "document/sgml/sgml.h"
|
||||
#include "util/error.h"
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "document/dom/navigator.h"
|
||||
#include "document/dom/stack.h"
|
||||
|
||||
/* The flags stored in the attribute sgml node info data */
|
||||
/* TODO: Other potential flags (there can be only 16)
|
||||
@ -76,7 +76,7 @@ get_sgml_node_info(struct sgml_node_info list[], struct dom_node *node)
|
||||
struct sgml_info {
|
||||
struct sgml_node_info *attributes;
|
||||
struct sgml_node_info *elements;
|
||||
dom_navigator_callback_T callbacks[DOM_NODES];
|
||||
dom_stack_callback_T callbacks[DOM_NODES];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user