Index: /libyaml/trunk/src/loader.c
===================================================================
--- /libyaml/trunk/src/loader.c	(revision 238)
+++ /libyaml/trunk/src/loader.c	(revision 238)
@@ -0,0 +1,429 @@
+
+#include "yaml_private.h"
+
+/*
+ * API functions.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
+
+/*
+ * Error handling.
+ */
+
+static int
+yaml_parser_set_parser_error(yaml_parser_t *parser,
+        const char *problem, yaml_mark_t problem_mark);
+
+static int
+yaml_parser_set_parser_error_context(yaml_parser_t *parser,
+        const char *context, yaml_mark_t context_mark,
+        const char *problem, yaml_mark_t problem_mark);
+
+
+/*
+ * Alias handling.
+ */
+
+static int
+yaml_parser_register_anchor(yaml_parser_t *parser,
+        int index, yaml_char_t *anchor);
+
+/*
+ * Clean up functions.
+ */
+
+static void
+yaml_parser_delete_aliases(yaml_parser_t *parser);
+
+/*
+ * Composer functions.
+ */
+
+static int
+yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event);
+
+static int
+yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event);
+
+static int
+yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event);
+
+static int
+yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event);
+
+static int
+yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event);
+
+static int
+yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event);
+
+/*
+ * Load the next document of the stream.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
+{
+    yaml_event_t event;
+
+    assert(parser);     /* Non-NULL parser object is expected. */
+    assert(document);   /* Non-NULL document object is expected. */
+
+    memset(document, 0, sizeof(yaml_document_t));
+    if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE))
+        goto error;
+
+    if (!parser->stream_start_produced) {
+        if (!yaml_parser_parse(parser, &event)) goto error;
+        assert(event.type == YAML_STREAM_START_EVENT);
+                        /* STREAM-START is expected. */
+    }
+
+    if (parser->stream_end_produced) {
+        return 1;
+    }
+
+    if (!yaml_parser_parse(parser, &event)) goto error;
+    if (event.type == YAML_STREAM_END_EVENT) {
+        return 1;
+    }
+
+    if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE))
+        goto error;
+
+    parser->document = document;
+
+    if (!yaml_parser_load_document(parser, &event)) goto error;
+
+    yaml_parser_delete_aliases(parser);
+    parser->document = NULL;
+
+    return 1;
+
+error:
+
+    yaml_parser_delete_aliases(parser);
+    yaml_document_delete(document);
+    parser->document = NULL;
+
+    return 0;
+}
+
+/*
+ * Set composer error.
+ */
+
+static int
+yaml_parser_set_composer_error(yaml_parser_t *parser,
+        const char *problem, yaml_mark_t problem_mark)
+{
+    parser->error = YAML_COMPOSER_ERROR;
+    parser->problem = problem;
+    parser->problem_mark = problem_mark;
+
+    return 0;
+}
+
+/*
+ * Set composer error with context.
+ */
+
+static int
+yaml_parser_set_composer_error_context(yaml_parser_t *parser,
+        const char *context, yaml_mark_t context_mark,
+        const char *problem, yaml_mark_t problem_mark)
+{
+    parser->error = YAML_COMPOSER_ERROR;
+    parser->context = context;
+    parser->context_mark = context_mark;
+    parser->problem = problem;
+    parser->problem_mark = problem_mark;
+
+    return 0;
+}
+
+/*
+ * Delete the stack of aliases.
+ */
+
+static void
+yaml_parser_delete_aliases(yaml_parser_t *parser)
+{
+    while (!STACK_EMPTY(parser, parser->aliases)) {
+        yaml_free(POP(parser, parser->aliases).anchor);
+    }
+    STACK_DEL(parser, parser->aliases);
+}
+
+/*
+ * Compose a document object.
+ */
+
+static int
+yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+    yaml_event_t event;
+
+    assert(first_event->type == YAML_DOCUMENT_START_EVENT);
+                        /* DOCUMENT-START is expected. */
+
+    parser->document->version_directive
+        = first_event->data.document_start.version_directive;
+    parser->document->tag_directives.start
+        = first_event->data.document_start.tag_directives.start;
+    parser->document->tag_directives.end
+        = first_event->data.document_start.tag_directives.end;
+    parser->document->start_implicit
+        = first_event->data.document_start.implicit;
+    parser->document->start_mark = first_event->start_mark;
+
+    if (!yaml_parser_parse(parser, &event)) return 0;
+
+    if (!yaml_parser_load_node(parser, &event)) return 0;
+
+    if (!yaml_parser_parse(parser, &event)) return 0;
+    assert(event.type == YAML_DOCUMENT_END_EVENT);
+                        /* DOCUMENT-END is expected. */
+
+    parser->document->end_implicit = event.data.document_end.implicit;
+    parser->document->end_mark = event.end_mark;
+
+    return 1;
+}
+
+/*
+ * Compose a node.
+ */
+
+static int
+yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+    switch (first_event->type) {
+        case YAML_ALIAS_EVENT:
+            return yaml_parser_load_alias(parser, first_event);
+        case YAML_SCALAR_EVENT:
+            return yaml_parser_load_scalar(parser, first_event);
+        case YAML_SEQUENCE_START_EVENT:
+            return yaml_parser_load_sequence(parser, first_event);
+        case YAML_MAPPING_START_EVENT:
+            return yaml_parser_load_mapping(parser, first_event);
+        default:
+            assert(0);  /* Could not happen. */
+            return 0;
+    }
+
+    return 0;
+}
+
+/*
+ * Add an anchor.
+ */
+
+static int
+yaml_parser_register_anchor(yaml_parser_t *parser,
+        int index, yaml_char_t *anchor)
+{
+    yaml_alias_data_t data = { anchor, index,
+        parser->document->nodes.start[index-1].start_mark };
+    yaml_alias_data_t *alias_data;
+
+    if (!anchor) return 1;
+
+    for (alias_data = parser->aliases.start;
+            alias_data != parser->aliases.top; alias_data ++) {
+        if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
+            yaml_free(anchor);
+            return yaml_parser_set_composer_error_context(parser,
+                    "found duplicate anchor; first occurence",
+                    alias_data->mark, "second occurence", data.mark);
+        }
+    }
+
+    if (!PUSH(parser, parser->aliases, data)) {
+        yaml_free(anchor);
+        return 0;
+    }
+
+    return 1;
+}
+
+/*
+ * Compose a node corresponding to an alias.
+ */
+
+static int
+yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+    yaml_char_t *anchor = first_event->data.alias.anchor;
+    yaml_alias_data_t *alias_data;
+
+    for (alias_data = parser->aliases.start;
+            alias_data != parser->aliases.top; alias_data ++) {
+        if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
+            yaml_free(anchor);
+            return alias_data->index;
+        }
+    }
+
+    yaml_free(anchor);
+    return yaml_parser_set_composer_error(parser, "found undefined alias",
+            first_event->start_mark);
+}
+
+/*
+ * Compose a scalar node.
+ */
+
+static int
+yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+    yaml_node_t node;
+    int index;
+    yaml_char_t *tag = first_event->data.scalar.tag;
+
+    if (!tag || strcmp((char *)tag, "!") == 0) {
+        yaml_free(tag);
+        tag = yaml_strdup(YAML_DEFAULT_SCALAR_TAG);
+        if (!tag) goto error;
+    }
+
+    SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
+            first_event->data.scalar.length, first_event->data.scalar.style,
+            first_event->start_mark, first_event->end_mark);
+
+    if (!PUSH(parser, parser->document->nodes, node)) goto error;
+
+    index = parser->document->nodes.top - parser->document->nodes.start;
+
+    if (!yaml_parser_register_anchor(parser, index,
+                first_event->data.scalar.anchor)) return 0;
+
+    return index;
+
+error:
+    yaml_free(tag);
+    yaml_free(first_event->data.scalar.anchor);
+    yaml_free(first_event->data.scalar.value);
+    return 0;
+}
+
+/*
+ * Compose a sequence node.
+ */
+
+static int
+yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+    yaml_event_t event;
+    yaml_node_t node;
+    struct {
+        yaml_node_item_t *start;
+        yaml_node_item_t *end;
+        yaml_node_item_t *top;
+    } items = { NULL, NULL, NULL };
+    int index, item_index;
+    yaml_char_t *tag = first_event->data.sequence_start.tag;
+
+    if (!tag || strcmp((char *)tag, "!") == 0) {
+        yaml_free(tag);
+        tag = yaml_strdup(YAML_DEFAULT_SEQUENCE_TAG);
+        if (!tag) goto error;
+    }
+
+    if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;
+
+    SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
+            first_event->data.sequence_start.style,
+            first_event->start_mark, first_event->end_mark);
+
+    if (!PUSH(parser, parser->document->nodes, node)) goto error;
+
+    index = parser->document->nodes.top - parser->document->nodes.start;
+
+    if (!yaml_parser_register_anchor(parser, index,
+                first_event->data.sequence_start.anchor)) return 0;
+
+    if (!yaml_parser_parse(parser, &event)) return 0;
+
+    while (event.type != YAML_SEQUENCE_END_EVENT) {
+        item_index = yaml_parser_load_node(parser, &event);
+        if (!item_index) return 0;
+        if (!PUSH(parser,
+                    parser->document->nodes.start[index-1].data.sequence.items,
+                    item_index)) return 0;
+        if (!yaml_parser_parse(parser, &event)) return 0;
+    }
+
+    parser->document->nodes.start[index-1].end_mark = event.end_mark;
+
+    return index;
+
+error:
+    yaml_free(tag);
+    yaml_free(first_event->data.sequence_start.anchor);
+    return 0;
+}
+
+/*
+ * Compose a mapping node.
+ */
+
+static int
+yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+    yaml_event_t event;
+    yaml_node_t node;
+    struct {
+        yaml_node_pair_t *start;
+        yaml_node_pair_t *end;
+        yaml_node_pair_t *top;
+    } pairs = { NULL, NULL, NULL };
+    int index;
+    yaml_node_pair_t pair;
+    yaml_char_t *tag = first_event->data.mapping_start.tag;
+
+    if (!tag || strcmp((char *)tag, "!") == 0) {
+        yaml_free(tag);
+        tag = yaml_strdup(YAML_DEFAULT_MAPPING_TAG);
+        if (!tag) goto error;
+    }
+
+    if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;
+
+    MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
+            first_event->data.mapping_start.style,
+            first_event->start_mark, first_event->end_mark);
+
+    if (!PUSH(parser, parser->document->nodes, node)) goto error;
+
+    index = parser->document->nodes.top - parser->document->nodes.start;
+
+    if (!yaml_parser_register_anchor(parser, index,
+                first_event->data.mapping_start.anchor)) return 0;
+
+    if (!yaml_parser_parse(parser, &event)) return 0;
+
+    while (event.type != YAML_MAPPING_END_EVENT) {
+        pair.key = yaml_parser_load_node(parser, &event);
+        if (!pair.key) return 0;
+        if (!yaml_parser_parse(parser, &event)) return 0;
+        pair.value = yaml_parser_load_node(parser, &event);
+        if (!pair.value) return 0;
+        if (!PUSH(parser,
+                    parser->document->nodes.start[index-1].data.mapping.pairs,
+                    pair)) return 0;
+        if (!yaml_parser_parse(parser, &event)) return 0;
+    }
+
+    parser->document->nodes.start[index-1].end_mark = event.end_mark;
+
+    return index;
+
+error:
+    yaml_free(tag);
+    yaml_free(first_event->data.mapping_start.anchor);
+    return 0;
+}
+
Index: /libyaml/trunk/src/Makefile.am
===================================================================
--- /libyaml/trunk/src/Makefile.am	(revision 219)
+++ /libyaml/trunk/src/Makefile.am	(revision 238)
@@ -1,4 +1,4 @@
 AM_CPPFLAGS = -I$(top_srcdir)/include
 lib_LTLIBRARIES = libyaml.la
-libyaml_la_SOURCES = yaml_private.h api.c reader.c scanner.c parser.c writer.c emitter.c
+libyaml_la_SOURCES = yaml_private.h api.c reader.c scanner.c parser.c loader.c writer.c emitter.c dumper.c
 libyaml_la_LDFLAGS = -release $(YAML_LT_RELEASE) -version-info $(YAML_LT_CURRENT):$(YAML_LT_REVISION):$(YAML_LT_AGE)
Index: /libyaml/trunk/src/api.c
===================================================================
--- /libyaml/trunk/src/api.c	(revision 237)
+++ /libyaml/trunk/src/api.c	(revision 238)
@@ -400,4 +400,5 @@
     }
     STACK_DEL(emitter, emitter->tag_directives);
+    yaml_free(emitter->anchors);
 
     memset(emitter, 0, sizeof(yaml_emitter_t));
@@ -1020,21 +1021,185 @@
 }
 
-#if 0
-
-/*
- * Create a SCALAR node.
- */
-
-YAML_DECLARE(int)
-yaml_scalar_node_initialize(yaml_node_t *node,
+/*
+ * Create a document object.
+ */
+
+YAML_DECLARE(int)
+yaml_document_initialize(yaml_document_t *document,
+        yaml_version_directive_t *version_directive,
+        yaml_tag_directive_t *tag_directives_start,
+        yaml_tag_directive_t *tag_directives_end,
+        int start_implicit, int end_implicit)
+{
+    struct {
+        yaml_error_type_t error;
+    } context;
+    struct {
+        yaml_node_t *start;
+        yaml_node_t *end;
+        yaml_node_t *top;
+    } nodes = { NULL, NULL, NULL };
+    yaml_version_directive_t *version_directive_copy = NULL;
+    struct {
+        yaml_tag_directive_t *start;
+        yaml_tag_directive_t *end;
+        yaml_tag_directive_t *top;
+    } tag_directives_copy = { NULL, NULL, NULL };
+    yaml_tag_directive_t value = { NULL, NULL };
+    yaml_mark_t mark = { 0, 0, 0 };
+
+    assert(document);       /* Non-NULL document object is expected. */
+    assert((tag_directives_start && tag_directives_end) ||
+            (tag_directives_start == tag_directives_end));
+                            /* Valid tag directives are expected. */
+
+    if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error;
+
+    if (version_directive) {
+        version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
+        if (!version_directive_copy) goto error;
+        version_directive_copy->major = version_directive->major;
+        version_directive_copy->minor = version_directive->minor;
+    }
+
+    if (tag_directives_start != tag_directives_end) {
+        yaml_tag_directive_t *tag_directive;
+        if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+            goto error;
+        for (tag_directive = tag_directives_start;
+                tag_directive != tag_directives_end; tag_directive ++) {
+            assert(tag_directive->handle);
+            assert(tag_directive->prefix);
+            if (!yaml_check_utf8(tag_directive->handle,
+                        strlen((char *)tag_directive->handle)))
+                goto error;
+            if (!yaml_check_utf8(tag_directive->prefix,
+                        strlen((char *)tag_directive->prefix)))
+                goto error;
+            value.handle = yaml_strdup(tag_directive->handle);
+            value.prefix = yaml_strdup(tag_directive->prefix);
+            if (!value.handle || !value.prefix) goto error;
+            if (!PUSH(&context, tag_directives_copy, value))
+                goto error;
+            value.handle = NULL;
+            value.prefix = NULL;
+        }
+    }
+
+    DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
+            tag_directives_copy.start, tag_directives_copy.top,
+            start_implicit, end_implicit, mark, mark);
+
+    return 1;
+
+error:
+    STACK_DEL(&context, nodes);
+    yaml_free(version_directive_copy);
+    while (!STACK_EMPTY(&context, tag_directives_copy)) {
+        yaml_tag_directive_t value = POP(&context, tag_directives_copy);
+        yaml_free(value.handle);
+        yaml_free(value.prefix);
+    }
+    STACK_DEL(&context, tag_directives_copy);
+    yaml_free(value.handle);
+    yaml_free(value.prefix);
+
+    return 0;
+}
+
+/*
+ * Destroy a document object.
+ */
+
+YAML_DECLARE(void)
+yaml_document_delete(yaml_document_t *document)
+{
+    struct {
+        yaml_error_type_t error;
+    } context;
+    yaml_tag_directive_t *tag_directive;
+
+    assert(document);   /* Non-NULL document object is expected. */
+
+    while (!STACK_EMPTY(&context, document->nodes)) {
+        yaml_node_t node = POP(&context, document->nodes);
+        yaml_free(node.tag);
+        switch (node.type) {
+            case YAML_SCALAR_NODE:
+                yaml_free(node.data.scalar.value);
+                break;
+            case YAML_SEQUENCE_NODE:
+                STACK_DEL(&context, node.data.sequence.items);
+                break;
+            case YAML_MAPPING_NODE:
+                STACK_DEL(&context, node.data.mapping.pairs);
+                break;
+            default:
+                assert(0);  /* Should not happen. */
+        }
+    }
+    STACK_DEL(&context, document->nodes);
+
+    yaml_free(document->version_directive);
+    for (tag_directive = document->tag_directives.start;
+            tag_directive != document->tag_directives.end;
+            tag_directive++) {
+        yaml_free(tag_directive->handle);
+        yaml_free(tag_directive->prefix);
+    }
+    yaml_free(document->tag_directives.start);
+
+    memset(document, 0, sizeof(yaml_document_t));
+}
+
+/**
+ * Get a document node.
+ */
+
+YAML_DECLARE(yaml_node_t *)
+yaml_document_get_node(yaml_document_t *document, int node)
+{
+    assert(document);   /* Non-NULL document object is expected. */
+
+    if (node > 0 && document->nodes.start + node <= document->nodes.top) {
+        return document->nodes.start + node - 1;
+    }
+    return NULL;
+}
+
+/**
+ * Get the root object.
+ */
+
+YAML_DECLARE(yaml_node_t *)
+yaml_document_get_root_node(yaml_document_t *document)
+{
+    assert(document);   /* Non-NULL document object is expected. */
+
+    if (document->nodes.top != document->nodes.start) {
+        return document->nodes.start;
+    }
+    return NULL;
+}
+
+/*
+ * Add a scalar node to a document.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_scalar(yaml_document_t *document,
         yaml_char_t *tag, yaml_char_t *value, int length,
         yaml_scalar_style_t style)
 {
+    struct {
+        yaml_error_type_t error;
+    } context;
     yaml_mark_t mark = { 0, 0, 0 };
     yaml_char_t *tag_copy = NULL;
     yaml_char_t *value_copy = NULL;
-
-    assert(node);       /* Non-NULL node object is expected. */
-    assert(value);      /* Non-NULL anchor is expected. */
+    yaml_node_t node;
+
+    assert(document);   /* Non-NULL document object is expected. */
+    assert(value);      /* Non-NULL value is expected. */
 
     if (!tag) {
@@ -1056,7 +1221,8 @@
     value_copy[length] = '\0';
 
-    SCALAR_NODE_INIT(*node, tag_copy, value_copy, length, style, mark, mark);
-
-    return 1;
+    SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark);
+    if (!PUSH(&context, document->nodes, node)) goto error;
+
+    return document->nodes.top - document->nodes.start;
 
 error:
@@ -1068,9 +1234,9 @@
 
 /*
- * Create a SEQUENCE node.
- */
-
-YAML_DECLARE(int)
-yaml_sequence_node_initialize(yaml_node_t *node,
+ * Add a sequence node to a document.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_sequence(yaml_document_t *document,
         yaml_char_t *tag, yaml_sequence_style_t style)
 {
@@ -1085,6 +1251,7 @@
         yaml_node_item_t *top;
     } items = { NULL, NULL, NULL };
-
-    assert(node);   /* Non-NULL node object is expected. */
+    yaml_node_t node;
+
+    assert(document);   /* Non-NULL document object is expected. */
 
     if (!tag) {
@@ -1092,20 +1259,19 @@
     }
 
-    if (tag) {
-        if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
-        tag_copy = yaml_strdup(tag);
-        if (!tag_copy) goto error;
-    }
-
-    if (!STACK_INIT(context, items, INITIAL_STACK_SIZE)) goto error;
-
-    SEQUENCE_NODE_INIT(*node, tag_copy, items.start, item.end, style,
-            mark, mark);
-
-    return 1;
+    if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
+    tag_copy = yaml_strdup(tag);
+    if (!tag_copy) goto error;
+
+    if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error;
+
+    SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
+            style, mark, mark);
+    if (!PUSH(&context, document->nodes, node)) goto error;
+
+    return document->nodes.top - document->nodes.start;
 
 error:
+    STACK_DEL(&context, items);
     yaml_free(tag_copy);
-    STACK_DEL(context, items);
 
     return 0;
@@ -1113,9 +1279,9 @@
 
 /*
- * Create a MAPPING node.
- */
-
-YAML_DECLARE(int)
-yaml_mapping_node_initialize(yaml_node_t *node,
+ * Add a mapping node to a document.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_mapping(yaml_document_t *document,
         yaml_char_t *tag, yaml_mapping_style_t style)
 {
@@ -1130,6 +1296,7 @@
         yaml_node_pair_t *top;
     } pairs = { NULL, NULL, NULL };
-
-    assert(node);   /* Non-NULL node object is expected. */
+    yaml_node_t node;
+
+    assert(document);   /* Non-NULL document object is expected. */
 
     if (!tag) {
@@ -1137,20 +1304,19 @@
     }
 
-    if (tag) {
-        if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
-        tag_copy = yaml_strdup(tag);
-        if (!tag_copy) goto error;
-    }
-
-    if (!STACK_INIT(context, pairs, INITIAL_STACK_SIZE)) goto error;
-
-    MAPPING_NODE_INIT(*node, tag_copy, pairs.start, pairs.end, style,
-            mark, mark);
-
-    return 1;
+    if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
+    tag_copy = yaml_strdup(tag);
+    if (!tag_copy) goto error;
+
+    if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error;
+
+    MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
+            style, mark, mark);
+    if (!PUSH(&context, document->nodes, node)) goto error;
+
+    return document->nodes.top - document->nodes.start;
 
 error:
+    STACK_DEL(&context, pairs);
     yaml_free(tag_copy);
-    STACK_DEL(context, pairs);
 
     return 0;
@@ -1158,45 +1324,60 @@
 
 /*
- * Delete a node and its subnodes.
- */
-
-YAML_DECLARE(void)
-yaml_node_delete(yaml_node_t *node)
+ * Append an item to a sequence node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_append_sequence_item(yaml_document_t *document,
+        int sequence, int item)
 {
     struct {
         yaml_error_type_t error;
     } context;
+
+    assert(document);       /* Non-NULL document is required. */
+    assert(sequence > 0
+            && document->nodes.start + sequence <= document->nodes.top);
+                            /* Valid sequence id is required. */
+    assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE);
+                            /* A sequence node is required. */
+    assert(item > 0 && document->nodes.start + item <= document->nodes.top);
+                            /* Valid item id is required. */
+
+    if (!PUSH(&context,
+                document->nodes.start[sequence-1].data.sequence.items, item))
+        return 0;
+
+    return 1;
+}
+
+/*
+ * Append a pair of a key and a value to a mapping node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_append_mapping_pair(yaml_document_t *document,
+        int mapping, int key, int value)
+{
     struct {
-        yaml_node_item_t *start;
-        yaml_node_item_t *end;
-        yaml_node_item_t *head;
-        yaml_node_item_t *tail;
-    } queue = { NULL, NULL, NULL, NULL };
-
-    assert(node);   /* Non-NULL node object is expected. */
-
-    if (node->type == YAML_SCALAR_NODE) {
-        yaml_free(node->data.scalar.tag);
-        yaml_free(node->data.scalar.value);
-        memset(node, 0, sizeof(yaml_node_t));
-        return;
-    }
-
-    if (!QUEUE_INIT(context, queue, INITIAL_QUEUE_SIZE)) goto error;
-    if (!ENQUEUE(context, queue, node)) goto error;
-
-    while (!QUEUE_EMPTY(context, queue)) {
-        yaml_node_t node = DEQUEUE(context, queue);
-        if (node.type == YAML_SCALAR_NODE) {
-            if (!node->reference)
-        }
-        if (node->type == YAML_SEQUENCE_NODE) {
-            while (!STACK_EMPTY(context, node->data.sequence.items)) {
-                yaml_node_t *item = 
-            }
-        }
-    }
-}
-
-#endif
-
+        yaml_error_type_t error;
+    } context;
+    yaml_node_pair_t pair = { key, value };
+
+    assert(document);       /* Non-NULL document is required. */
+    assert(mapping > 0
+            && document->nodes.start + mapping <= document->nodes.top);
+                            /* Valid mapping id is required. */
+    assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE);
+                            /* A mapping node is required. */
+    assert(key > 0 && document->nodes.start + key <= document->nodes.top);
+                            /* Valid key id is required. */
+    assert(value > 0 && document->nodes.start + value <= document->nodes.top);
+                            /* Valid value id is required. */
+
+    if (!PUSH(&context,
+                document->nodes.start[mapping-1].data.mapping.pairs, pair))
+        return 0;
+
+    return 1;
+}
+
Index: /libyaml/trunk/src/emitter.c
===================================================================
--- /libyaml/trunk/src/emitter.c	(revision 216)
+++ /libyaml/trunk/src/emitter.c	(revision 238)
@@ -1161,4 +1161,11 @@
 {
     yaml_scalar_style_t style = event->data.scalar.style;
+    int no_tag = (!emitter->tag_data.handle && !emitter->tag_data.suffix);
+
+    if (no_tag && !event->data.scalar.plain_implicit
+            && !event->data.scalar.quoted_implicit) {
+        return yaml_emitter_set_emitter_error(emitter,
+                "neither tag nor implicit flags are specified");
+    }
 
     if (style == YAML_ANY_SCALAR_STYLE)
@@ -1179,6 +1186,5 @@
                 && (emitter->flow_level || emitter->simple_key_context))
             style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
-        if (!event->data.scalar.plain_implicit
-                && !emitter->tag_data.handle && !emitter->tag_data.suffix)
+        if (no_tag && !event->data.scalar.plain_implicit)
             style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
     }
@@ -1197,17 +1203,9 @@
     }
 
-    if (!emitter->tag_data.handle && !emitter->tag_data.suffix)
-    {
-        if (!event->data.scalar.plain_implicit
-                && !event->data.scalar.quoted_implicit) {
-            return yaml_emitter_set_emitter_error(emitter,
-                    "neither tag nor implicit flags are specified");
-        }
-
-        if (event->data.scalar.plain_implicit
-                && style != YAML_PLAIN_SCALAR_STYLE) {
-            emitter->tag_data.handle = (yaml_char_t *)"!";
-            emitter->tag_data.handle_length = 1;
-        }
+    if (no_tag && !event->data.scalar.quoted_implicit
+            && style != YAML_PLAIN_SCALAR_STYLE)
+    {
+        emitter->tag_data.handle = (yaml_char_t *)"!";
+        emitter->tag_data.handle_length = 1;
     }
 
Index: /libyaml/trunk/src/dumper.c
===================================================================
--- /libyaml/trunk/src/dumper.c	(revision 238)
+++ /libyaml/trunk/src/dumper.c	(revision 238)
@@ -0,0 +1,394 @@
+
+#include "yaml_private.h"
+
+/*
+ * API functions.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_open(yaml_emitter_t *emitter);
+
+YAML_DECLARE(int)
+yaml_emitter_close(yaml_emitter_t *emitter);
+
+YAML_DECLARE(int)
+yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
+
+/*
+ * Clean up functions.
+ */
+
+static void
+yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter);
+
+/*
+ * Anchor functions.
+ */
+
+static void
+yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index);
+
+static yaml_char_t *
+yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id);
+
+
+/*
+ * Serialize functions.
+ */
+
+static int
+yaml_emitter_dump_node(yaml_emitter_t *emitter, int index);
+
+static int
+yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor);
+
+static int
+yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
+        yaml_char_t *anchor);
+
+static int
+yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
+        yaml_char_t *anchor);
+
+static int
+yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
+        yaml_char_t *anchor);
+
+/*
+ * Issue a STREAM-START event.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_open(yaml_emitter_t *emitter)
+{
+    yaml_event_t event;
+    yaml_mark_t mark = { 0, 0, 0 };
+
+    assert(emitter);            /* Non-NULL emitter object is required. */
+    assert(!emitter->opened);   /* Emitter should not be opened yet. */
+
+    STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark);
+
+    if (!yaml_emitter_emit(emitter, &event)) {
+        return 0;
+    }
+
+    emitter->opened = 1;
+
+    return 1;
+}
+
+/*
+ * Issue a STREAM-END event.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_close(yaml_emitter_t *emitter)
+{
+    yaml_event_t event;
+    yaml_mark_t mark = { 0, 0, 0 };
+
+    assert(emitter);            /* Non-NULL emitter object is required. */
+    assert(emitter->opened);    /* Emitter should be opened. */
+
+    if (emitter->closed) return 1;
+
+    STREAM_END_EVENT_INIT(event, mark, mark);
+
+    if (!yaml_emitter_emit(emitter, &event)) {
+        return 0;
+    }
+
+    emitter->closed = 1;
+
+    return 1;
+}
+
+/*
+ * Dump a YAML document.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document)
+{
+    yaml_event_t event;
+    yaml_mark_t mark = { 0, 0, 0 };
+
+    assert(emitter);            /* Non-NULL emitter object is required. */
+    assert(document);           /* Non-NULL emitter object is expected. */
+
+    emitter->document = document;
+
+    if (!emitter->opened) {
+        if (!yaml_emitter_open(emitter)) goto error;
+    }
+
+    if (STACK_EMPTY(emitter, document->nodes)) {
+        if (!yaml_emitter_close(emitter)) goto error;
+        yaml_emitter_delete_document_and_anchors(emitter);
+        return 1;
+    }
+
+    assert(emitter->opened);    /* Emitter should be opened. */
+
+    emitter->anchors = yaml_malloc(sizeof(*(emitter->anchors))
+            * (document->nodes.top - document->nodes.start));
+    if (!emitter->anchors) goto error;
+    memset(emitter->anchors, 0, sizeof(*(emitter->anchors))
+            * (document->nodes.top - document->nodes.start));
+
+    DOCUMENT_START_EVENT_INIT(event, document->version_directive,
+            document->tag_directives.start, document->tag_directives.end,
+            document->start_implicit, mark, mark);
+    if (!yaml_emitter_emit(emitter, &event)) goto error;
+
+    yaml_emitter_anchor_node(emitter, 1);
+    if (!yaml_emitter_dump_node(emitter, 1)) goto error;
+
+    DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark);
+    if (!yaml_emitter_emit(emitter, &event)) goto error;
+
+    yaml_emitter_delete_document_and_anchors(emitter);
+
+    return 1;
+
+error:
+
+    yaml_emitter_delete_document_and_anchors(emitter);
+
+    return 0;
+}
+
+/*
+ * Clean up the emitter object after a document is dumped.
+ */
+
+static void
+yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter)
+{
+    int index;
+
+    if (!emitter->anchors) {
+        yaml_document_delete(emitter->document);
+        emitter->document = NULL;
+        return;
+    }
+
+    for (index = 0; emitter->document->nodes.start + index
+            < emitter->document->nodes.top; index ++) {
+        yaml_node_t node = emitter->document->nodes.start[index];
+        if (!emitter->anchors[index].serialized) {
+            yaml_free(node.tag);
+            if (node.type == YAML_SCALAR_NODE) {
+                yaml_free(node.data.scalar.value);
+            }
+        }
+        if (node.type == YAML_SEQUENCE_NODE) {
+            STACK_DEL(emitter, node.data.sequence.items);
+        }
+        if (node.type == YAML_MAPPING_NODE) {
+            STACK_DEL(emitter, node.data.mapping.pairs);
+        }
+    }
+
+    STACK_DEL(emitter, emitter->document->nodes);
+    yaml_free(emitter->anchors);
+
+    emitter->anchors = NULL;
+    emitter->last_anchor_id = 0;
+    emitter->document = NULL;
+}
+
+/*
+ * Check the references of a node and assign the anchor id if needed.
+ */
+
+static void
+yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index)
+{
+    yaml_node_t *node = emitter->document->nodes.start + index - 1;
+    yaml_node_item_t *item;
+    yaml_node_pair_t *pair;
+
+    emitter->anchors[index-1].references ++;
+
+    if (emitter->anchors[index-1].references == 1) {
+        switch (node->type) {
+            case YAML_SEQUENCE_NODE:
+                for (item = node->data.sequence.items.start;
+                        item < node->data.sequence.items.top; item ++) {
+                    yaml_emitter_anchor_node(emitter, *item);
+                }
+                break;
+            case YAML_MAPPING_NODE:
+                for (pair = node->data.mapping.pairs.start;
+                        pair < node->data.mapping.pairs.top; pair ++) {
+                    yaml_emitter_anchor_node(emitter, pair->key);
+                    yaml_emitter_anchor_node(emitter, pair->value);
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    else if (emitter->anchors[index-1].references == 2) {
+        emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id);
+    }
+}
+
+/*
+ * Generate a textual representation for an anchor.
+ */
+
+#define ANCHOR_TEMPLATE         "id%03d"
+#define ANCHOR_TEMPLATE_LENGTH  16
+
+static yaml_char_t *
+yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id)
+{
+    yaml_char_t *anchor = yaml_malloc(ANCHOR_TEMPLATE_LENGTH);
+
+    if (!anchor) return NULL;
+
+    sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id);
+
+    return anchor;
+}
+
+/*
+ * Serialize a node.
+ */
+
+static int
+yaml_emitter_dump_node(yaml_emitter_t *emitter, int index)
+{
+    yaml_node_t *node = emitter->document->nodes.start + index - 1;
+    int anchor_id = emitter->anchors[index-1].anchor;
+    yaml_char_t *anchor = NULL;
+
+    if (anchor_id) {
+        anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
+        if (!anchor) return 0;
+    }
+
+    if (emitter->anchors[index-1].serialized) {
+        return yaml_emitter_dump_alias(emitter, anchor);
+    }
+
+    emitter->anchors[index-1].serialized = 1;
+
+    switch (node->type) {
+        case YAML_SCALAR_NODE:
+            return yaml_emitter_dump_scalar(emitter, node, anchor);
+        case YAML_SEQUENCE_NODE:
+            return yaml_emitter_dump_sequence(emitter, node, anchor);
+        case YAML_MAPPING_NODE:
+            return yaml_emitter_dump_mapping(emitter, node, anchor);
+        default:
+            assert(0);      /* Could not happen. */
+            break;
+    }
+
+    return 0;       /* Could not happen. */
+}
+
+/*
+ * Serialize an alias.
+ */
+
+static int
+yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor)
+{
+    yaml_event_t event;
+    yaml_mark_t mark  = { 0, 0, 0 };
+
+    ALIAS_EVENT_INIT(event, anchor, mark, mark);
+
+    return yaml_emitter_emit(emitter, &event);
+}
+
+/*
+ * Serialize a scalar.
+ */
+
+static int
+yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
+        yaml_char_t *anchor)
+{
+    yaml_event_t event;
+    yaml_mark_t mark  = { 0, 0, 0 };
+
+    int plain_implicit = (strcmp((char *)node->tag,
+                YAML_DEFAULT_SCALAR_TAG) == 0);
+    int quoted_implicit = (strcmp((char *)node->tag,
+                YAML_DEFAULT_SCALAR_TAG) == 0);
+
+    SCALAR_EVENT_INIT(event, anchor, node->tag, node->data.scalar.value,
+            node->data.scalar.length, plain_implicit, quoted_implicit,
+            node->data.scalar.style, mark, mark);
+
+    return yaml_emitter_emit(emitter, &event);
+}
+
+/*
+ * Serialize a sequence.
+ */
+
+static int
+yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
+        yaml_char_t *anchor)
+{
+    yaml_event_t event;
+    yaml_mark_t mark  = { 0, 0, 0 };
+
+    int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0);
+
+    yaml_node_item_t *item;
+
+    SEQUENCE_START_EVENT_INIT(event, anchor, node->tag, implicit,
+            node->data.sequence.style, mark, mark);
+    if (!yaml_emitter_emit(emitter, &event)) return 0;
+
+    for (item = node->data.sequence.items.start;
+            item < node->data.sequence.items.top; item ++) {
+        if (!yaml_emitter_dump_node(emitter, *item)) return 0;
+    }
+
+    SEQUENCE_END_EVENT_INIT(event, mark, mark);
+    if (!yaml_emitter_emit(emitter, &event)) return 0;
+
+    return 1;
+}
+
+/*
+ * Serialize a mapping.
+ */
+
+static int
+yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
+        yaml_char_t *anchor)
+{
+    yaml_event_t event;
+    yaml_mark_t mark  = { 0, 0, 0 };
+
+    int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0);
+
+    yaml_node_pair_t *pair;
+
+    MAPPING_START_EVENT_INIT(event, anchor, node->tag, implicit,
+            node->data.mapping.style, mark, mark);
+    if (!yaml_emitter_emit(emitter, &event)) return 0;
+
+    for (pair = node->data.mapping.pairs.start;
+            pair < node->data.mapping.pairs.top; pair ++) {
+        if (!yaml_emitter_dump_node(emitter, pair->key)) return 0;
+        if (!yaml_emitter_dump_node(emitter, pair->value)) return 0;
+    }
+
+    MAPPING_END_EVENT_INIT(event, mark, mark);
+    if (!yaml_emitter_emit(emitter, &event)) return 0;
+
+    return 1;
+}
+
Index: /libyaml/trunk/src/yaml_private.h
===================================================================
--- /libyaml/trunk/src/yaml_private.h	(revision 237)
+++ /libyaml/trunk/src/yaml_private.h	(revision 238)
@@ -581,10 +581,29 @@
 
 /*
+ * Document initializer.
+ */
+
+#define DOCUMENT_INIT(document,document_nodes_start,document_nodes_end,         \
+        document_version_directive,document_tag_directives_start,               \
+        document_tag_directives_end,document_start_implicit,                    \
+        document_end_implicit,start_mark,end_mark)                              \
+    (memset(&(document), 0, sizeof(yaml_document_t)),                           \
+     (document).nodes.start = (document_nodes_start),                           \
+     (document).nodes.end = (document_nodes_end),                               \
+     (document).nodes.top = (document_nodes_start),                             \
+     (document).version_directive = (document_version_directive),               \
+     (document).tag_directives.start = (document_tag_directives_start),         \
+     (document).tag_directives.end = (document_tag_directives_end),             \
+     (document).start_implicit = (document_start_implicit),                     \
+     (document).end_implicit = (document_end_implicit))
+
+/*
  * Node initializers.
  */
 
-#define NODE_INIT(node,node_type,node_start_mark,node_end_mark)                 \
+#define NODE_INIT(node,node_type,node_tag,node_start_mark,node_end_mark)        \
     (memset(&(node), 0, sizeof(yaml_node_t)),                                   \
      (node).type = (node_type),                                                 \
+     (node).tag = (node_tag),                                                   \
      (node).start_mark = (node_start_mark),                                     \
      (node).end_mark = (node_end_mark))
@@ -592,6 +611,5 @@
 #define SCALAR_NODE_INIT(node,node_tag,node_value,node_length,                  \
         node_style,start_mark,end_mark)                                         \
-    (EVENT_INIT((node),YAML_SCALAR_NODE,(start_mark),(end_mark)),               \
-     (node).data.scalar.tag = (node_tag),                                       \
+    (NODE_INIT((node),YAML_SCALAR_NODE,(node_tag),(start_mark),(end_mark)),     \
      (node).data.scalar.value = (node_value),                                   \
      (node).data.scalar.length = (node_length),                                 \
@@ -600,6 +618,5 @@
 #define SEQUENCE_NODE_INIT(node,node_tag,node_items_start,node_items_end,       \
         node_style,start_mark,end_mark)                                         \
-    (NODE_INIT((node),YAML_SEQUENCE_NODE,(start_mark),(end_mark)),             \
-     (node).data.sequence.tag = (node_tag),                                     \
+    (NODE_INIT((node),YAML_SEQUENCE_NODE,(node_tag),(start_mark),(end_mark)),   \
      (node).data.sequence.items.start = (node_items_start),                     \
      (node).data.sequence.items.end = (node_items_end),                         \
@@ -609,6 +626,5 @@
 #define MAPPING_NODE_INIT(node,node_tag,node_pairs_start,node_pairs_end,        \
         node_style,start_mark,end_mark)                                         \
-    (NODE_INIT((node),YAML_MAPPING_NODE,(start_mark),(end_mark)),               \
-     (node).data.mapping.tag = (node_tag),                                      \
+    (NODE_INIT((node),YAML_MAPPING_NODE,(node_tag),(start_mark),(end_mark)),    \
      (node).data.mapping.pairs.start = (node_pairs_start),                      \
      (node).data.mapping.pairs.end = (node_pairs_end),                          \
Index: /libyaml/trunk/tests/run-emitter.c
===================================================================
--- /libyaml/trunk/tests/run-emitter.c	(revision 217)
+++ /libyaml/trunk/tests/run-emitter.c	(revision 238)
@@ -257,5 +257,5 @@
         int k;
         memset(buffer, 0, BUFFER_SIZE);
-        memset(events, 0, MAX_EVENTS);
+        memset(events, 0, MAX_EVENTS*sizeof(yaml_event_t));
 
         printf("[%d] Parsing, emitting, and parsing again '%s': ", number, argv[number]);
Index: /libyaml/trunk/tests/run-dumper.c
===================================================================
--- /libyaml/trunk/tests/run-dumper.c	(revision 238)
+++ /libyaml/trunk/tests/run-dumper.c	(revision 238)
@@ -0,0 +1,305 @@
+#include <yaml.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#define BUFFER_SIZE 65536
+#define MAX_DOCUMENTS  16
+
+int copy_document(yaml_document_t *document_to, yaml_document_t *document_from)
+{
+    yaml_node_t *node;
+    yaml_node_item_t *item;
+    yaml_node_pair_t *pair;
+
+    if (!yaml_document_initialize(document_to, document_from->version_directive,
+                document_from->tag_directives.start,
+                document_from->tag_directives.end,
+                document_from->start_implicit, document_from->end_implicit))
+        return 0;
+
+    for (node = document_from->nodes.start;
+            node < document_from->nodes.top; node ++) {
+        switch (node->type) {
+            case YAML_SCALAR_NODE:
+                if (!yaml_document_add_scalar(document_to, node->tag,
+                            node->data.scalar.value, node->data.scalar.length,
+                            node->data.scalar.style)) goto error;
+                break;
+            case YAML_SEQUENCE_NODE:
+                if (!yaml_document_add_sequence(document_to, node->tag,
+                            node->data.sequence.style)) goto error;
+                break;
+            case YAML_MAPPING_NODE:
+                if (!yaml_document_add_mapping(document_to, node->tag,
+                            node->data.mapping.style)) goto error;
+                break;
+            default:
+                assert(0);
+                break;
+        }
+    }
+
+    for (node = document_from->nodes.start;
+            node < document_from->nodes.top; node ++) {
+        switch (node->type) {
+            case YAML_SEQUENCE_NODE:
+                for (item = node->data.sequence.items.start;
+                        item < node->data.sequence.items.top; item ++) {
+                    if (!yaml_document_append_sequence_item(document_to,
+                                node - document_from->nodes.start + 1,
+                                *item)) goto error;
+                }
+                break;
+            case YAML_MAPPING_NODE:
+                for (pair = node->data.mapping.pairs.start;
+                        pair < node->data.mapping.pairs.top; pair ++) {
+                    if (!yaml_document_append_mapping_pair(document_to,
+                                node - document_from->nodes.start + 1,
+                                pair->key, pair->value)) goto error;
+                }
+                break;
+            default:
+                break;
+        }
+    }
+    return 1;
+
+error:
+    yaml_document_delete(document_to);
+    return 0;
+}
+
+int compare_nodes(yaml_document_t *document1, int index1,
+        yaml_document_t *document2, int index2)
+{
+    yaml_node_t *node1 = yaml_document_get_node(document1, index1);
+    yaml_node_t *node2 = yaml_document_get_node(document2, index2);
+    int k;
+
+    assert(node1);
+    assert(node2);
+
+    if (node1->type != node2->type)
+        return 0;
+
+    if (strcmp((char *)node1->tag, (char *)node2->tag) != 0) return 0;
+
+    switch (node1->type) {
+        case YAML_SCALAR_NODE:
+            if (node1->data.scalar.length != node2->data.scalar.length)
+                return 0;
+            if (strncmp((char *)node1->data.scalar.value, (char *)node2->data.scalar.value,
+                        node1->data.scalar.length) != 0) return 0;
+            break;
+        case YAML_SEQUENCE_NODE:
+            if ((node1->data.sequence.items.top - node1->data.sequence.items.start) !=
+                    (node2->data.sequence.items.top - node2->data.sequence.items.start))
+                return 0;
+            for (k = 0; k < (node1->data.sequence.items.top - node1->data.sequence.items.start); k ++) {
+                if (!compare_nodes(document1, node1->data.sequence.items.start[k],
+                            document2, node2->data.sequence.items.start[k])) return 0;
+            }
+            break;
+        case YAML_MAPPING_NODE:
+            if ((node1->data.mapping.pairs.top - node1->data.mapping.pairs.start) !=
+                    (node2->data.mapping.pairs.top - node2->data.mapping.pairs.start))
+                return 0;
+            for (k = 0; k < (node1->data.mapping.pairs.top - node1->data.mapping.pairs.start); k ++) {
+                if (!compare_nodes(document1, node1->data.mapping.pairs.start[k].key,
+                            document2, node2->data.mapping.pairs.start[k].key)) return 0;
+                if (!compare_nodes(document1, node1->data.mapping.pairs.start[k].value,
+                            document2, node2->data.mapping.pairs.start[k].value)) return 0;
+            }
+            break;
+
+    }
+    return 1;
+}
+
+int compare_documents(yaml_document_t *document1, yaml_document_t *document2)
+{
+    int k;
+
+    if ((document1->version_directive && !document2->version_directive)
+            || (!document1->version_directive && document2->version_directive)
+            || (document1->version_directive && document2->version_directive
+                && (document1->version_directive->major != document2->version_directive->major
+                    || document1->version_directive->minor != document2->version_directive->minor)))
+        return 0;
+
+    if ((document1->tag_directives.end - document1->tag_directives.start) !=
+            (document2->tag_directives.end - document2->tag_directives.start))
+        return 0;
+    for (k = 0; k < (document1->tag_directives.end - document1->tag_directives.start); k ++) {
+        if ((strcmp((char *)document1->tag_directives.start[k].handle,
+                        (char *)document2->tag_directives.start[k].handle) != 0)
+                || (strcmp((char *)document1->tag_directives.start[k].prefix,
+                    (char *)document2->tag_directives.start[k].prefix) != 0))
+            return 0;
+    }
+
+    if ((document1->nodes.top - document1->nodes.start) !=
+            (document2->nodes.top - document2->nodes.start))
+        return 0;
+
+    if (document1->nodes.top != document1->nodes.start) {
+        if (!compare_nodes(document1, 1, document2, 1))
+            return 0;
+    }
+
+    return 1;
+}
+
+int print_output(char *name, unsigned char *buffer, size_t size, int count)
+{
+    FILE *file;
+    char data[BUFFER_SIZE];
+    size_t data_size = 1;
+    size_t total_size = 0;
+    if (count >= 0) {
+        printf("FAILED (at the document #%d)\nSOURCE:\n", count+1);
+    }
+    file = fopen(name, "rb");
+    assert(file);
+    while (data_size > 0) {
+        data_size = fread(data, 1, BUFFER_SIZE, file);
+        assert(!ferror(file));
+        if (!data_size) break;
+        assert(fwrite(data, 1, data_size, stdout) == data_size);
+        total_size += data_size;
+        if (feof(file)) break;
+    }
+    fclose(file);
+    printf("#### (length: %d)\n", total_size);
+    printf("OUTPUT:\n%s#### (length: %d)\n", buffer, size);
+    return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+    int number;
+    int canonical = 0;
+    int unicode = 0;
+
+    number = 1;
+    while (number < argc) {
+        if (strcmp(argv[number], "-c") == 0) {
+            canonical = 1;
+        }
+        else if (strcmp(argv[number], "-u") == 0) {
+            unicode = 1;
+        }
+        else if (argv[number][0] == '-') {
+            printf("Unknown option: '%s'\n", argv[number]);
+            return 0;
+        }
+        if (argv[number][0] == '-') {
+            if (number < argc-1) {
+                memmove(argv+number, argv+number+1, (argc-number-1)*sizeof(char *));
+            }
+            argc --;
+        }
+        else {
+            number ++;
+        }
+    }
+
+    if (argc < 2) {
+        printf("Usage: %s [-c] [-u] file1.yaml ...\n", argv[0]);
+        return 0;
+    }
+
+    for (number = 1; number < argc; number ++)
+    {
+        FILE *file;
+        yaml_parser_t parser;
+        yaml_emitter_t emitter;
+
+        yaml_document_t document;
+        unsigned char buffer[BUFFER_SIZE];
+        size_t written = 0;
+        yaml_document_t documents[MAX_DOCUMENTS];
+        size_t document_number = 0;
+        int done = 0;
+        int count = 0;
+        int error = 0;
+        int k;
+        memset(buffer, 0, BUFFER_SIZE);
+        memset(documents, 0, MAX_DOCUMENTS*sizeof(yaml_document_t));
+
+        printf("[%d] Loading, dumping, and loading again '%s': ", number, argv[number]);
+        fflush(stdout);
+
+        file = fopen(argv[number], "rb");
+        assert(file);
+
+        assert(yaml_parser_initialize(&parser));
+        yaml_parser_set_input_file(&parser, file);
+        assert(yaml_emitter_initialize(&emitter));
+        if (canonical) {
+            yaml_emitter_set_canonical(&emitter, 1);
+        }
+        if (unicode) {
+            yaml_emitter_set_unicode(&emitter, 1);
+        }
+        yaml_emitter_set_output_string(&emitter, buffer, BUFFER_SIZE, &written);
+        yaml_emitter_open(&emitter);
+
+        while (!done)
+        {
+            if (!yaml_parser_load(&parser, &document)) {
+                error = 1;
+                break;
+            }
+
+            done = (!yaml_document_get_root_node(&document));
+            if (!done) {
+                assert(document_number < MAX_DOCUMENTS);
+                assert(copy_document(&(documents[document_number++]), &document));
+                assert(yaml_emitter_dump(&emitter, &document) || 
+                        (yaml_emitter_flush(&emitter) && print_output(argv[number], buffer, written, count)));
+                count ++;
+            }
+            else {
+                yaml_document_delete(&document);
+            }
+        }
+
+        yaml_parser_delete(&parser);
+        assert(!fclose(file));
+        yaml_emitter_close(&emitter);
+        yaml_emitter_delete(&emitter);
+
+        if (!error)
+        {
+            count = done = 0;
+            assert(yaml_parser_initialize(&parser));
+            yaml_parser_set_input_string(&parser, buffer, written);
+
+            while (!done)
+            {
+                assert(yaml_parser_load(&parser, &document) || print_output(argv[number], buffer, written, count));
+                done = (!yaml_document_get_root_node(&document));
+                if (!done) {
+                    assert(compare_documents(documents+count, &document) || print_output(argv[number], buffer, written, count));
+                    count ++;
+                }
+                yaml_document_delete(&document);
+            }
+            yaml_parser_delete(&parser);
+        }
+
+        for (k = 0; k < document_number; k ++) {
+            yaml_document_delete(documents+k);
+        }
+
+        printf("PASSED (length: %d)\n", written);
+        print_output(argv[number], buffer, written, -1);
+    }
+
+    return 0;
+}
Index: /libyaml/trunk/tests/example-reformatter-alt.c
===================================================================
--- /libyaml/trunk/tests/example-reformatter-alt.c	(revision 238)
+++ /libyaml/trunk/tests/example-reformatter-alt.c	(revision 238)
@@ -0,0 +1,217 @@
+
+#include <yaml.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+main(int argc, char *argv[])
+{
+    int help = 0;
+    int canonical = 0;
+    int unicode = 0;
+    int k;
+    int done = 0;
+
+    yaml_parser_t parser;
+    yaml_emitter_t emitter;
+    yaml_document_t document;
+
+    /* Clear the objects. */
+
+    memset(&parser, 0, sizeof(parser));
+    memset(&emitter, 0, sizeof(emitter));
+    memset(&document, 0, sizeof(document));
+
+    /* Analyze command line options. */
+
+    for (k = 1; k < argc; k ++)
+    {
+        if (strcmp(argv[k], "-h") == 0
+                || strcmp(argv[k], "--help") == 0) {
+            help = 1;
+        }
+
+        else if (strcmp(argv[k], "-c") == 0
+                || strcmp(argv[k], "--canonical") == 0) {
+            canonical = 1;
+        }
+
+        else if (strcmp(argv[k], "-u") == 0
+                || strcmp(argv[k], "--unicode") == 0) {
+            unicode = 1;
+        }
+
+        else {
+            fprintf(stderr, "Unrecognized option: %s\n"
+                    "Try `%s --help` for more information.\n",
+                    argv[k], argv[0]);
+            return 1;
+        }
+    }
+
+    /* Display the help string. */
+
+    if (help)
+    {
+        printf("%s [--canonical] [--unicode] <input >output\n"
+                "or\n%s -h | --help\nReformat a YAML stream\n\nOptions:\n"
+                "-h, --help\t\tdisplay this help and exit\n"
+                "-c, --canonical\t\toutput in the canonical YAML format\n"
+                "-u, --unicode\t\toutput unescaped non-ASCII characters\n",
+                argv[0], argv[0]);
+        return 0;
+    }
+
+    /* Initialize the parser and emitter objects. */
+
+    if (!yaml_parser_initialize(&parser))
+        goto parser_error;
+
+    if (!yaml_emitter_initialize(&emitter))
+        goto emitter_error;
+
+    /* Set the parser parameters. */
+
+    yaml_parser_set_input_file(&parser, stdin);
+
+    /* Set the emitter parameters. */
+
+    yaml_emitter_set_output_file(&emitter, stdout);
+
+    yaml_emitter_set_canonical(&emitter, canonical);
+    yaml_emitter_set_unicode(&emitter, unicode);
+
+    /* The main loop. */
+
+    while (!done)
+    {
+        /* Get the next event. */
+
+        if (!yaml_parser_load(&parser, &document))
+            goto parser_error;
+
+        /* Check if this is the stream end. */
+
+        if (!yaml_document_get_root_node(&document)) {
+            done = 1;
+        }
+
+        /* Emit the event. */
+
+        if (!yaml_emitter_dump(&emitter, &document))
+            goto emitter_error;
+    }
+
+    yaml_parser_delete(&parser);
+    yaml_emitter_delete(&emitter);
+
+    return 0;
+
+parser_error:
+
+    /* Display a parser error message. */
+
+    switch (parser.error)
+    {
+        case YAML_MEMORY_ERROR:
+            fprintf(stderr, "Memory error: Not enough memory for parsing\n");
+            break;
+
+        case YAML_READER_ERROR:
+            if (parser.problem_value != -1) {
+                fprintf(stderr, "Reader error: %s: #%X at %d\n", parser.problem,
+                        parser.problem_value, parser.problem_offset);
+            }
+            else {
+                fprintf(stderr, "Reader error: %s at %d\n", parser.problem,
+                        parser.problem_offset);
+            }
+            break;
+
+        case YAML_SCANNER_ERROR:
+            if (parser.context) {
+                fprintf(stderr, "Scanner error: %s at line %d, column %d\n"
+                        "%s at line %d, column %d\n", parser.context,
+                        parser.context_mark.line+1, parser.context_mark.column+1,
+                        parser.problem, parser.problem_mark.line+1,
+                        parser.problem_mark.column+1);
+            }
+            else {
+                fprintf(stderr, "Scanner error: %s at line %d, column %d\n",
+                        parser.problem, parser.problem_mark.line+1,
+                        parser.problem_mark.column+1);
+            }
+            break;
+
+        case YAML_PARSER_ERROR:
+            if (parser.context) {
+                fprintf(stderr, "Parser error: %s at line %d, column %d\n"
+                        "%s at line %d, column %d\n", parser.context,
+                        parser.context_mark.line+1, parser.context_mark.column+1,
+                        parser.problem, parser.problem_mark.line+1,
+                        parser.problem_mark.column+1);
+            }
+            else {
+                fprintf(stderr, "Parser error: %s at line %d, column %d\n",
+                        parser.problem, parser.problem_mark.line+1,
+                        parser.problem_mark.column+1);
+            }
+            break;
+
+        case YAML_COMPOSER_ERROR:
+            if (parser.context) {
+                fprintf(stderr, "Composer error: %s at line %d, column %d\n"
+                        "%s at line %d, column %d\n", parser.context,
+                        parser.context_mark.line+1, parser.context_mark.column+1,
+                        parser.problem, parser.problem_mark.line+1,
+                        parser.problem_mark.column+1);
+            }
+            else {
+                fprintf(stderr, "Composer error: %s at line %d, column %d\n",
+                        parser.problem, parser.problem_mark.line+1,
+                        parser.problem_mark.column+1);
+            }
+            break;
+
+        default:
+            /* Couldn't happen. */
+            fprintf(stderr, "Internal error\n");
+            break;
+    }
+
+    yaml_parser_delete(&parser);
+    yaml_emitter_delete(&emitter);
+
+    return 1;
+
+emitter_error:
+
+    /* Display an emitter error message. */
+
+    switch (emitter.error)
+    {
+        case YAML_MEMORY_ERROR:
+            fprintf(stderr, "Memory error: Not enough memory for emitting\n");
+            break;
+
+        case YAML_WRITER_ERROR:
+            fprintf(stderr, "Writer error: %s\n", emitter.problem);
+            break;
+
+        case YAML_EMITTER_ERROR:
+            fprintf(stderr, "Emitter error: %s\n", emitter.problem);
+            break;
+
+        default:
+            /* Couldn't happen. */
+            fprintf(stderr, "Internal error\n");
+            break;
+    }
+
+    yaml_parser_delete(&parser);
+    yaml_emitter_delete(&emitter);
+
+    return 1;
+}
+
Index: /libyaml/trunk/tests/example-deconstructor-alt.c
===================================================================
--- /libyaml/trunk/tests/example-deconstructor-alt.c	(revision 238)
+++ /libyaml/trunk/tests/example-deconstructor-alt.c	(revision 238)
@@ -0,0 +1,800 @@
+
+#include <yaml.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+main(int argc, char *argv[])
+{
+    int help = 0;
+    int canonical = 0;
+    int unicode = 0;
+    int k;
+    int done = 0;
+
+    yaml_parser_t parser;
+    yaml_emitter_t emitter;
+    yaml_event_t input_event;
+    yaml_document_t output_document;
+
+    int root;
+
+    /* Clear the objects. */
+
+    memset(&parser, 0, sizeof(parser));
+    memset(&emitter, 0, sizeof(emitter));
+    memset(&input_event, 0, sizeof(input_event));
+    memset(&output_document, 0, sizeof(output_document));
+
+    /* Analyze command line options. */
+
+    for (k = 1; k < argc; k ++)
+    {
+        if (strcmp(argv[k], "-h") == 0
+                || strcmp(argv[k], "--help") == 0) {
+            help = 1;
+        }
+
+        else if (strcmp(argv[k], "-c") == 0
+                || strcmp(argv[k], "--canonical") == 0) {
+            canonical = 1;
+        }
+
+        else if (strcmp(argv[k], "-u") == 0
+                || strcmp(argv[k], "--unicode") == 0) {
+            unicode = 1;
+        }
+
+        else {
+            fprintf(stderr, "Unrecognized option: %s\n"
+                    "Try `%s --help` for more information.\n",
+                    argv[k], argv[0]);
+            return 1;
+        }
+    }
+
+    /* Display the help string. */
+
+    if (help)
+    {
+        printf("%s <input\n"
+                "or\n%s -h | --help\nDeconstruct a YAML stream\n\nOptions:\n"
+                "-h, --help\t\tdisplay this help and exit\n"
+                "-c, --canonical\t\toutput in the canonical YAML format\n"
+                "-u, --unicode\t\toutput unescaped non-ASCII characters\n",
+                argv[0], argv[0]);
+        return 0;
+    }
+
+    /* Initialize the parser and emitter objects. */
+
+    if (!yaml_parser_initialize(&parser)) {
+        fprintf(stderr, "Could not initialize the parser object\n");
+        return 1;
+    }
+
+    if (!yaml_emitter_initialize(&emitter)) {
+        yaml_parser_delete(&parser);
+        fprintf(stderr, "Could not inialize the emitter object\n");
+        return 1;
+    }
+
+    /* Set the parser parameters. */
+
+    yaml_parser_set_input_file(&parser, stdin);
+
+    /* Set the emitter parameters. */
+
+    yaml_emitter_set_output_file(&emitter, stdout);
+
+    yaml_emitter_set_canonical(&emitter, canonical);
+    yaml_emitter_set_unicode(&emitter, unicode);
+
+    /* Create and emit the STREAM-START event. */
+
+    if (!yaml_emitter_open(&emitter))
+        goto emitter_error;
+
+    /* Create a output_document object. */
+
+    if (!yaml_document_initialize(&output_document, NULL, NULL, NULL, 0, 0))
+        goto document_error;
+
+    /* Create the root sequence. */
+
+    root = yaml_document_add_sequence(&output_document, NULL,
+            YAML_BLOCK_SEQUENCE_STYLE);
+    if (!root) goto document_error;
+
+    /* Loop through the input events. */
+
+    while (!done)
+    {
+        int properties, key, value, map, seq;
+
+        /* Get the next event. */
+
+        if (!yaml_parser_parse(&parser, &input_event))
+            goto parser_error;
+
+        /* Check if this is the stream end. */
+
+        if (input_event.type == YAML_STREAM_END_EVENT) {
+            done = 1;
+        }
+
+        /* Create a mapping node and attach it to the root sequence. */
+
+        properties = yaml_document_add_mapping(&output_document, NULL,
+                YAML_BLOCK_MAPPING_STYLE);
+        if (!properties) goto document_error;
+        if (!yaml_document_append_sequence_item(&output_document,
+                    root, properties)) goto document_error;
+
+        /* Analyze the event. */
+
+        switch (input_event.type)
+        {
+            case YAML_STREAM_START_EVENT:
+
+                /* Add 'type': 'STREAM-START'. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "type", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                    "STREAM-START", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                /* Add 'encoding': <encoding>. */
+
+                if (input_event.data.stream_start.encoding)
+                {
+                    yaml_encoding_t encoding
+                        = input_event.data.stream_start.encoding;
+
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "encoding", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    value = yaml_document_add_scalar(&output_document, NULL,
+                            (encoding == YAML_UTF8_ENCODING ? "utf-8" :
+                             encoding == YAML_UTF16LE_ENCODING ? "utf-16-le" :
+                             encoding == YAML_UTF16BE_ENCODING ? "utf-16-be" :
+                             "unknown"), -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, value)) goto document_error;
+                }
+                    
+                break;
+
+            case YAML_STREAM_END_EVENT:
+
+                /* Add 'type': 'STREAM-END'. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "type", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                    "STREAM-END", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                break;
+
+            case YAML_DOCUMENT_START_EVENT:
+
+                /* Add 'type': 'DOCUMENT-START'. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "type", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                    "DOCUMENT-START", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                /* Display the output_document version numbers. */
+
+                if (input_event.data.document_start.version_directive)
+                {
+                    yaml_version_directive_t *version
+                        = input_event.data.document_start.version_directive;
+                    char number[64];
+
+                    /* Add 'version': {}. */
+                    
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "version", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    map = yaml_document_add_mapping(&output_document, NULL,
+                            YAML_FLOW_MAPPING_STYLE);
+                    if (!map) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, map)) goto document_error;
+
+                    /* Add 'major': <number>. */
+
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "major", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    sprintf(number, "%d", version->major);
+                    value = yaml_document_add_scalar(&output_document, YAML_INT_TAG,
+                        number, -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                map, key, value)) goto document_error;
+
+                    /* Add 'minor': <number>. */
+
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "minor", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    sprintf(number, "%d", version->minor);
+                    value = yaml_document_add_scalar(&output_document, YAML_INT_TAG,
+                        number, -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                map, key, value)) goto document_error;
+                }
+
+                /* Display the output_document tag directives. */
+
+                if (input_event.data.document_start.tag_directives.start
+                        != input_event.data.document_start.tag_directives.end)
+                {
+                    yaml_tag_directive_t *tag;
+
+                    /* Add 'tags': []. */
+                    
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "tags", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    seq = yaml_document_add_sequence(&output_document, NULL,
+                            YAML_BLOCK_SEQUENCE_STYLE);
+                    if (!seq) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, seq)) goto document_error;
+
+                    for (tag = input_event.data.document_start.tag_directives.start;
+                            tag != input_event.data.document_start.tag_directives.end;
+                            tag ++)
+                    {
+                        /* Add {}. */
+
+                        map = yaml_document_add_mapping(&output_document, NULL,
+                                YAML_FLOW_MAPPING_STYLE);
+                        if (!map) goto document_error;
+                        if (!yaml_document_append_sequence_item(&output_document,
+                                    seq, map)) goto document_error;
+
+                        /* Add 'handle': <handle>. */
+
+                        key = yaml_document_add_scalar(&output_document, NULL,
+                            "handle", -1, YAML_PLAIN_SCALAR_STYLE);
+                        if (!key) goto document_error;
+                        value = yaml_document_add_scalar(&output_document, NULL,
+                            tag->handle, -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+                        if (!value) goto document_error;
+                        if (!yaml_document_append_mapping_pair(&output_document,
+                                    map, key, value)) goto document_error;
+
+                        /* Add 'prefix': <prefix>. */
+
+                        key = yaml_document_add_scalar(&output_document, NULL,
+                            "prefix", -1, YAML_PLAIN_SCALAR_STYLE);
+                        if (!key) goto document_error;
+                        value = yaml_document_add_scalar(&output_document, NULL,
+                            tag->prefix, -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+                        if (!value) goto document_error;
+                        if (!yaml_document_append_mapping_pair(&output_document,
+                                    map, key, value)) goto document_error;
+                    }
+                }
+
+                /* Add 'implicit': <flag>. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "implicit", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, YAML_BOOL_TAG,
+                        (input_event.data.document_start.implicit ?
+                         "true" : "false"), -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                break;
+
+            case YAML_DOCUMENT_END_EVENT:
+
+                /* Add 'type': 'DOCUMENT-END'. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "type", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                    "DOCUMENT-END", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                /* Add 'implicit': <flag>. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "implicit", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, YAML_BOOL_TAG,
+                        (input_event.data.document_end.implicit ?
+                         "true" : "false"), -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                break;
+
+            case YAML_ALIAS_EVENT:
+
+                /* Add 'type': 'ALIAS'. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "type", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                    "ALIAS", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                /* Add 'anchor': <anchor>. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "anchor", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                        input_event.data.alias.anchor, -1,
+                        YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                break;
+
+            case YAML_SCALAR_EVENT:
+
+                /* Add 'type': 'SCALAR'. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "type", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                    "SCALAR", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                /* Add 'anchor': <anchor>. */
+
+                if (input_event.data.scalar.anchor)
+                {
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "anchor", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    value = yaml_document_add_scalar(&output_document, NULL,
+                            input_event.data.scalar.anchor, -1,
+                            YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, value)) goto document_error;
+                }
+
+                /* Add 'tag': <tag>. */
+
+                if (input_event.data.scalar.tag)
+                {
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "tag", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    value = yaml_document_add_scalar(&output_document, NULL,
+                            input_event.data.scalar.tag, -1,
+                            YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, value)) goto document_error;
+                }
+
+                /* Add 'value': <value>. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "value", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                        input_event.data.scalar.value,
+                        input_event.data.scalar.length,
+                        YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                /* Display if the scalar tag is implicit. */
+
+                /* Add 'implicit': {} */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "version", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                map = yaml_document_add_mapping(&output_document, NULL,
+                        YAML_FLOW_MAPPING_STYLE);
+                if (!map) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, map)) goto document_error;
+
+                /* Add 'plain': <flag>. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "plain", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, YAML_BOOL_TAG,
+                        (input_event.data.scalar.plain_implicit ?
+                         "true" : "false"), -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            map, key, value)) goto document_error;
+
+                /* Add 'quoted': <flag>. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "quoted", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, YAML_BOOL_TAG,
+                        (input_event.data.scalar.quoted_implicit ?
+                         "true" : "false"), -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            map, key, value)) goto document_error;
+
+                /* Display the style information. */
+
+                if (input_event.data.scalar.style)
+                {
+                    yaml_scalar_style_t style = input_event.data.scalar.style;
+
+                    /* Add 'style': <style>. */
+
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "style", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    value = yaml_document_add_scalar(&output_document, NULL,
+                            (style == YAML_PLAIN_SCALAR_STYLE ? "plain" :
+                             style == YAML_SINGLE_QUOTED_SCALAR_STYLE ?
+                                    "single-quoted" :
+                             style == YAML_DOUBLE_QUOTED_SCALAR_STYLE ?
+                                    "double-quoted" :
+                             style == YAML_LITERAL_SCALAR_STYLE ? "literal" :
+                             style == YAML_FOLDED_SCALAR_STYLE ? "folded" :
+                             "unknown"), -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, value)) goto document_error;
+                }
+
+                break;
+
+            case YAML_SEQUENCE_START_EVENT:
+
+                /* Add 'type': 'SEQUENCE-START'. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "type", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                    "SEQUENCE-START", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                /* Add 'anchor': <anchor>. */
+
+                if (input_event.data.sequence_start.anchor)
+                {
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "anchor", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    value = yaml_document_add_scalar(&output_document, NULL,
+                            input_event.data.sequence_start.anchor, -1,
+                            YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, value)) goto document_error;
+                }
+
+                /* Add 'tag': <tag>. */
+
+                if (input_event.data.sequence_start.tag)
+                {
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "tag", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    value = yaml_document_add_scalar(&output_document, NULL,
+                            input_event.data.sequence_start.tag, -1,
+                            YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, value)) goto document_error;
+                }
+
+                /* Add 'implicit': <flag>. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "implicit", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, YAML_BOOL_TAG,
+                        (input_event.data.sequence_start.implicit ?
+                         "true" : "false"), -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                /* Display the style information. */
+
+                if (input_event.data.sequence_start.style)
+                {
+                    yaml_sequence_style_t style
+                        = input_event.data.sequence_start.style;
+
+                    /* Add 'style': <style>. */
+
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "style", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    value = yaml_document_add_scalar(&output_document, NULL,
+                            (style == YAML_BLOCK_SEQUENCE_STYLE ? "block" :
+                             style == YAML_FLOW_SEQUENCE_STYLE ? "flow" :
+                             "unknown"), -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, value)) goto document_error;
+                }
+
+                break;
+
+            case YAML_SEQUENCE_END_EVENT:
+
+                /* Add 'type': 'SEQUENCE-END'. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "type", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                    "SEQUENCE-END", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                break;
+
+            case YAML_MAPPING_START_EVENT:
+
+                /* Add 'type': 'MAPPING-START'. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "type", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                    "MAPPING-START", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                /* Add 'anchor': <anchor>. */
+
+                if (input_event.data.mapping_start.anchor)
+                {
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "anchor", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    value = yaml_document_add_scalar(&output_document, NULL,
+                            input_event.data.mapping_start.anchor, -1,
+                            YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, value)) goto document_error;
+                }
+
+                /* Add 'tag': <tag>. */
+
+                if (input_event.data.mapping_start.tag)
+                {
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "tag", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    value = yaml_document_add_scalar(&output_document, NULL,
+                            input_event.data.mapping_start.tag, -1,
+                            YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, value)) goto document_error;
+                }
+
+                /* Add 'implicit': <flag>. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "implicit", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, YAML_BOOL_TAG,
+                        (input_event.data.mapping_start.implicit ?
+                         "true" : "false"), -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                /* Display the style information. */
+
+                if (input_event.data.sequence_start.style)
+                {
+                    yaml_sequence_style_t style
+                        = input_event.data.mapping_start.style;
+
+                    /* Add 'style': <style>. */
+
+                    key = yaml_document_add_scalar(&output_document, NULL,
+                        "style", -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!key) goto document_error;
+                    value = yaml_document_add_scalar(&output_document, NULL,
+                            (style == YAML_BLOCK_MAPPING_STYLE ? "block" :
+                             style == YAML_FLOW_MAPPING_STYLE ? "flow" :
+                             "unknown"), -1, YAML_PLAIN_SCALAR_STYLE);
+                    if (!value) goto document_error;
+                    if (!yaml_document_append_mapping_pair(&output_document,
+                                properties, key, value)) goto document_error;
+                }
+
+                break;
+
+            case YAML_MAPPING_END_EVENT:
+
+                /* Add 'type': 'MAPPING-END'. */
+
+                key = yaml_document_add_scalar(&output_document, NULL,
+                    "type", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!key) goto document_error;
+                value = yaml_document_add_scalar(&output_document, NULL,
+                    "MAPPING-END", -1, YAML_PLAIN_SCALAR_STYLE);
+                if (!value) goto document_error;
+                if (!yaml_document_append_mapping_pair(&output_document,
+                            properties, key, value)) goto document_error;
+
+                break;
+
+            default:
+                /* It couldn't really happen. */
+                break;
+        }
+
+        /* Delete the event object. */
+
+        yaml_event_delete(&input_event);
+    }
+
+    if (!yaml_emitter_dump(&emitter, &output_document))
+        goto emitter_error;
+    if (!yaml_emitter_close(&emitter))
+        goto emitter_error;
+
+    yaml_parser_delete(&parser);
+    yaml_emitter_delete(&emitter);
+
+    return 0;
+
+parser_error:
+
+    /* Display a parser error message. */
+
+    switch (parser.error)
+    {
+        case YAML_MEMORY_ERROR:
+            fprintf(stderr, "Memory error: Not enough memory for parsing\n");
+            break;
+
+        case YAML_READER_ERROR:
+            if (parser.problem_value != -1) {
+                fprintf(stderr, "Reader error: %s: #%X at %d\n", parser.problem,
+                        parser.problem_value, parser.problem_offset);
+            }
+            else {
+                fprintf(stderr, "Reader error: %s at %d\n", parser.problem,
+                        parser.problem_offset);
+            }
+            break;
+
+        case YAML_SCANNER_ERROR:
+            if (parser.context) {
+                fprintf(stderr, "Scanner error: %s at line %d, column %d\n"
+                        "%s at line %d, column %d\n", parser.context,
+                        parser.context_mark.line+1, parser.context_mark.column+1,
+                        parser.problem, parser.problem_mark.line+1,
+                        parser.problem_mark.column+1);
+            }
+            else {
+                fprintf(stderr, "Scanner error: %s at line %d, column %d\n",
+                        parser.problem, parser.problem_mark.line+1,
+                        parser.problem_mark.column+1);
+            }
+            break;
+
+        case YAML_PARSER_ERROR:
+            if (parser.context) {
+                fprintf(stderr, "Parser error: %s at line %d, column %d\n"
+                        "%s at line %d, column %d\n", parser.context,
+                        parser.context_mark.line+1, parser.context_mark.column+1,
+                        parser.problem, parser.problem_mark.line+1,
+                        parser.problem_mark.column+1);
+            }
+            else {
+                fprintf(stderr, "Parser error: %s at line %d, column %d\n",
+                        parser.problem, parser.problem_mark.line+1,
+                        parser.problem_mark.column+1);
+            }
+            break;
+
+        default:
+            /* Couldn't happen. */
+            fprintf(stderr, "Internal error\n");
+            break;
+    }
+
+    yaml_event_delete(&input_event);
+    yaml_document_delete(&output_document);
+    yaml_parser_delete(&parser);
+    yaml_emitter_delete(&emitter);
+
+    return 1;
+
+emitter_error:
+
+    /* Display an emitter error message. */
+
+    switch (emitter.error)
+    {
+        case YAML_MEMORY_ERROR:
+            fprintf(stderr, "Memory error: Not enough memory for emitting\n");
+            break;
+
+        case YAML_WRITER_ERROR:
+            fprintf(stderr, "Writer error: %s\n", emitter.problem);
+            break;
+
+        case YAML_EMITTER_ERROR:
+            fprintf(stderr, "Emitter error: %s\n", emitter.problem);
+            break;
+
+        default:
+            /* Couldn't happen. */
+            fprintf(stderr, "Internal error\n");
+            break;
+    }
+
+    yaml_event_delete(&input_event);
+    yaml_document_delete(&output_document);
+    yaml_parser_delete(&parser);
+    yaml_emitter_delete(&emitter);
+
+    return 1;
+
+document_error:
+
+    fprintf(stderr, "Memory error: Not enough memory for creating a document\n");
+
+    yaml_event_delete(&input_event);
+    yaml_document_delete(&output_document);
+    yaml_parser_delete(&parser);
+    yaml_emitter_delete(&emitter);
+
+    return 1;
+}
+
Index: /libyaml/trunk/tests/example-deconstructor.c
===================================================================
--- /libyaml/trunk/tests/example-deconstructor.c	(revision 220)
+++ /libyaml/trunk/tests/example-deconstructor.c	(revision 238)
@@ -337,65 +337,65 @@
                             tag ++)
                     {
-                            /* Write '{'. */
-
-                            if (!yaml_mapping_start_event_initialize(&output_event,
-                                        NULL, "tag:yaml.org,2002:map", 1,
-                                        YAML_FLOW_MAPPING_STYLE))
-                                goto event_error;
-                            if (!yaml_emitter_emit(&emitter, &output_event))
-                                goto emitter_error;
-
-                            /* Write 'handle'. */
-
-                            if (!yaml_scalar_event_initialize(&output_event,
-                                        NULL, "tag:yaml.org,2002:str", "handle", -1,
-                                        1, 1, YAML_PLAIN_SCALAR_STYLE))
-                                goto event_error;
-                            if (!yaml_emitter_emit(&emitter, &output_event))
-                                goto emitter_error;
-
-                            /* Write the tag directive handle. */
-
-                            if (!yaml_scalar_event_initialize(&output_event,
-                                        NULL, "tag:yaml.org,2002:str",
-                                        tag->handle, -1,
-                                        0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE))
-                                goto event_error;
-                            if (!yaml_emitter_emit(&emitter, &output_event))
-                                goto emitter_error;
-
-                            /* Write 'prefix'. */
-
-                            if (!yaml_scalar_event_initialize(&output_event,
-                                        NULL, "tag:yaml.org,2002:str", "prefix", -1,
-                                        1, 1, YAML_PLAIN_SCALAR_STYLE))
-                                goto event_error;
-                            if (!yaml_emitter_emit(&emitter, &output_event))
-                                goto emitter_error;
-
-                            /* Write the tag directive prefix. */
-
-                            if (!yaml_scalar_event_initialize(&output_event,
-                                        NULL, "tag:yaml.org,2002:str",
-                                        tag->prefix, -1,
-                                        0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE))
-                                goto event_error;
-                            if (!yaml_emitter_emit(&emitter, &output_event))
-                                goto emitter_error;
-
-                            /* Write '}'. */
-
-                            if (!yaml_mapping_end_event_initialize(&output_event))
-                                goto event_error;
-                            if (!yaml_emitter_emit(&emitter, &output_event))
-                                goto emitter_error;
-                        }
-
-                        /* End a block sequence. */
-
-                        if (!yaml_sequence_end_event_initialize(&output_event))
+                        /* Write '{'. */
+
+                        if (!yaml_mapping_start_event_initialize(&output_event,
+                                    NULL, "tag:yaml.org,2002:map", 1,
+                                    YAML_FLOW_MAPPING_STYLE))
                             goto event_error;
                         if (!yaml_emitter_emit(&emitter, &output_event))
                             goto emitter_error;
+
+                        /* Write 'handle'. */
+
+                        if (!yaml_scalar_event_initialize(&output_event,
+                                    NULL, "tag:yaml.org,2002:str", "handle", -1,
+                                    1, 1, YAML_PLAIN_SCALAR_STYLE))
+                            goto event_error;
+                        if (!yaml_emitter_emit(&emitter, &output_event))
+                            goto emitter_error;
+
+                        /* Write the tag directive handle. */
+
+                        if (!yaml_scalar_event_initialize(&output_event,
+                                    NULL, "tag:yaml.org,2002:str",
+                                    tag->handle, -1,
+                                    0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+                            goto event_error;
+                        if (!yaml_emitter_emit(&emitter, &output_event))
+                            goto emitter_error;
+
+                        /* Write 'prefix'. */
+
+                        if (!yaml_scalar_event_initialize(&output_event,
+                                    NULL, "tag:yaml.org,2002:str", "prefix", -1,
+                                    1, 1, YAML_PLAIN_SCALAR_STYLE))
+                            goto event_error;
+                        if (!yaml_emitter_emit(&emitter, &output_event))
+                            goto emitter_error;
+
+                        /* Write the tag directive prefix. */
+
+                        if (!yaml_scalar_event_initialize(&output_event,
+                                    NULL, "tag:yaml.org,2002:str",
+                                    tag->prefix, -1,
+                                    0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+                            goto event_error;
+                        if (!yaml_emitter_emit(&emitter, &output_event))
+                            goto emitter_error;
+
+                        /* Write '}'. */
+
+                        if (!yaml_mapping_end_event_initialize(&output_event))
+                            goto event_error;
+                        if (!yaml_emitter_emit(&emitter, &output_event))
+                            goto emitter_error;
+                    }
+
+                    /* End a block sequence. */
+
+                    if (!yaml_sequence_end_event_initialize(&output_event))
+                        goto event_error;
+                    if (!yaml_emitter_emit(&emitter, &output_event))
+                        goto emitter_error;
                 }
 
Index: /libyaml/trunk/tests/Makefile.am
===================================================================
--- /libyaml/trunk/tests/Makefile.am	(revision 224)
+++ /libyaml/trunk/tests/Makefile.am	(revision 238)
@@ -4,3 +4,5 @@
 TESTS = test-version test-reader
 check_PROGRAMS = test-version test-reader
-noinst_PROGRAMS = run-scanner run-parser run-emitter example-reformatter example-deconstructor
+noinst_PROGRAMS = run-scanner run-parser run-loader run-emitter run-dumper	\
+				  example-reformatter example-reformatter-alt	\
+				  example-deconstructor example-deconstructor-alt
Index: /libyaml/trunk/tests/run-loader.c
===================================================================
--- /libyaml/trunk/tests/run-loader.c	(revision 238)
+++ /libyaml/trunk/tests/run-loader.c	(revision 238)
@@ -0,0 +1,59 @@
+#include <yaml.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+int
+main(int argc, char *argv[])
+{
+    int number;
+
+    if (argc < 2) {
+        printf("Usage: %s file1.yaml ...\n", argv[0]);
+        return 0;
+    }
+
+    for (number = 1; number < argc; number ++)
+    {
+        FILE *file;
+        yaml_parser_t parser;
+        yaml_document_t document;
+        int done = 0;
+        int count = 0;
+        int error = 0;
+
+        printf("[%d] Loading '%s': ", number, argv[number]);
+        fflush(stdout);
+
+        file = fopen(argv[number], "rb");
+        assert(file);
+
+        assert(yaml_parser_initialize(&parser));
+
+        yaml_parser_set_input_file(&parser, file);
+
+        while (!done)
+        {
+            if (!yaml_parser_load(&parser, &document)) {
+                error = 1;
+                break;
+            }
+
+            done = (!yaml_document_get_root_node(&document));
+
+            yaml_document_delete(&document);
+
+            if (!done) count ++;
+        }
+
+        yaml_parser_delete(&parser);
+
+        assert(!fclose(file));
+
+        printf("%s (%d documents)\n", (error ? "FAILURE" : "SUCCESS"), count);
+    }
+
+    return 0;
+}
+
Index: /libyaml/trunk/configure.ac
===================================================================
--- /libyaml/trunk/configure.ac	(revision 172)
+++ /libyaml/trunk/configure.ac	(revision 238)
@@ -19,5 +19,5 @@
 #           YAML_AGE = 0
 m4_define([YAML_RELEASE], 0)
-m4_define([YAML_CURRENT], 0)
+m4_define([YAML_CURRENT], 1)
 m4_define([YAML_REVISION], 0)
 m4_define([YAML_AGE], 0)
Index: /libyaml/trunk/include/yaml.h
===================================================================
--- /libyaml/trunk/include/yaml.h	(revision 237)
+++ /libyaml/trunk/include/yaml.h	(revision 238)
@@ -60,7 +60,7 @@
  * Get the library version numbers.
  *
- * @param[out]  major   Major version number.
- * @param[out]  minor   Minor version number.
- * @param[out]  patch   Patch version number.
+ * @param[out]      major   Major version number.
+ * @param[out]      minor   Minor version number.
+ * @param[out]      patch   Patch version number.
  */
 
@@ -79,5 +79,5 @@
 
 /** The version directive data. */
-typedef struct {
+typedef struct yaml_version_directive_s {
     /** The major version number. */
     int major;
@@ -87,5 +87,5 @@
 
 /** The tag directive data. */
-typedef struct {
+typedef struct yaml_tag_directive_s {
     /** The tag handle. */
     yaml_char_t *handle;
@@ -95,5 +95,5 @@
 
 /** The stream encoding. */
-typedef enum {
+typedef enum yaml_encoding_e {
     YAML_ANY_ENCODING,
     YAML_UTF8_ENCODING,
@@ -104,5 +104,5 @@
 /** Line break types. */
 
-typedef enum {
+typedef enum yaml_break_e {
     YAML_ANY_BREAK,
     YAML_CR_BREAK,
@@ -112,5 +112,5 @@
 
 /** Many bad things could happen with the parser and emitter. */
-typedef enum {
+typedef enum yaml_error_type_e {
     YAML_NO_ERROR,
 
@@ -120,4 +120,5 @@
     YAML_SCANNER_ERROR,
     YAML_PARSER_ERROR,
+    YAML_COMPOSER_ERROR,
 
     YAML_WRITER_ERROR,
@@ -126,5 +127,5 @@
 
 /** The pointer position. */
-typedef struct {
+typedef struct yaml_mark_s {
     /** The position index. */
     size_t index;
@@ -145,5 +146,5 @@
 
 /** Scalar styles. */
-typedef enum {
+typedef enum yaml_scalar_style_e {
     YAML_ANY_SCALAR_STYLE,
 
@@ -158,5 +159,5 @@
 
 /** Sequence styles. */
-typedef enum {
+typedef enum yaml_sequence_style_e {
     YAML_ANY_SEQUENCE_STYLE,
 
@@ -166,5 +167,5 @@
 
 /** Mapping styles. */
-typedef enum {
+typedef enum yaml_mapping_style_e {
     YAML_ANY_MAPPING_STYLE,
 
@@ -182,5 +183,5 @@
 
 /** Token types. */
-typedef enum {
+typedef enum yaml_token_type_e {
     YAML_NO_TOKEN,
 
@@ -214,5 +215,5 @@
 
 /** The token structure. */
-typedef struct {
+typedef struct yaml_token_s {
 
     /** The token type. */
@@ -300,5 +301,5 @@
 
 /** Event types. */
-typedef enum {
+typedef enum yaml_event_type_e {
     YAML_NO_EVENT,
 
@@ -320,5 +321,5 @@
 
 /** The event structure. */
-typedef struct {
+typedef struct yaml_event_s {
 
     /** The event type. */
@@ -417,6 +418,6 @@
  * Create the STREAM-START event.
  *
- * @param[out]  event       An empty event object.
- * @param[in]   encoding    The stream encoding.
+ * @param[out]      event       An empty event object.
+ * @param[in]       encoding    The stream encoding.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -430,5 +431,5 @@
  * Create the STREAM-END event.
  *
- * @param[out]  event       An empty event object.
+ * @param[out]      event       An empty event object.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -444,9 +445,13 @@
  * ignored by the emitter.
  *
- * @param[out]  event                   An empty event object.
- * @param[in]   version_directive       The %YAML directive value or @c NULL.
- * @param[in]   tag_directives_start    The beginning of the %TAG directives list.
- * @param[in]   tag_directives_end      The end of the %TAG directives list.
- * @param[in]   implicit                If the document start indicator is implicit.
+ * @param[out]      event                   An empty event object.
+ * @param[in]       version_directive       The %YAML directive value or
+ *                                          @c NULL.
+ * @param[in]       tag_directives_start    The beginning of the %TAG
+ *                                          directives list.
+ * @param[in]       tag_directives_end      The end of the %TAG directives
+ *                                          list.
+ * @param[in]       implicit                If the document start indicator is
+ *                                          implicit.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -466,6 +471,6 @@
  * ignored by the emitter.
  *
- * @param[out]  event       An empty event object.
- * @param[in]   implicit    If the document end indicator is implicit.
+ * @param[out]      event       An empty event object.
+ * @param[in]       implicit    If the document end indicator is implicit.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -478,6 +483,6 @@
  * Create an ALIAS event.
  *
- * @param[out]  event       An empty event object.
- * @param[in]   anchor      The anchor value.
+ * @param[out]      event       An empty event object.
+ * @param[in]       anchor      The anchor value.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -495,12 +500,14 @@
  * @a quoted_implicit flags must be set.
  *
- * @param[out]  event           An empty event object.
- * @param[in]   anchor          The scalar anchor or @c NULL.
- * @param[in]   tag             The scalar tag or @c NULL.
- * @param[in]   value           The scalar value.
- * @param[in]   length          The length of the scalar value.
- * @param[in]   plain_implicit  If the tag may be omitted for the plain style.
- * @param[in]   quoted_implicit If the tag may be omitted for any non-plain style.
- * @param[in]   style           The scalar style.
+ * @param[out]      event           An empty event object.
+ * @param[in]       anchor          The scalar anchor or @c NULL.
+ * @param[in]       tag             The scalar tag or @c NULL.
+ * @param[in]       value           The scalar value.
+ * @param[in]       length          The length of the scalar value.
+ * @param[in]       plain_implicit  If the tag may be omitted for the plain
+ *                                  style.
+ * @param[in]       quoted_implicit If the tag may be omitted for any
+ *                                  non-plain style.
+ * @param[in]       style           The scalar style.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -521,9 +528,9 @@
  * Either the @a tag attribute or the @a implicit flag must be set.
  *
- * @param[out]  event       An empty event object.
- * @param[in]   anchor      The sequence anchor or @c NULL.
- * @param[in]   tag         The sequence tag or @c NULL.
- * @param[in]   implicit    If the tag may be omitted.
- * @param[in]   style       The sequence style.
+ * @param[out]      event       An empty event object.
+ * @param[in]       anchor      The sequence anchor or @c NULL.
+ * @param[in]       tag         The sequence tag or @c NULL.
+ * @param[in]       implicit    If the tag may be omitted.
+ * @param[in]       style       The sequence style.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -538,5 +545,5 @@
  * Create a SEQUENCE-END event.
  *
- * @param[out]  event       An empty event object.
+ * @param[out]      event       An empty event object.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -553,9 +560,9 @@
  * Either the @a tag attribute or the @a implicit flag must be set.
  *
- * @param[out]  event       An empty event object.
- * @param[in]   anchor      The mapping anchor or @c NULL.
- * @param[in]   tag         The mapping tag or @c NULL.
- * @param[in]   implicit    If the tag may be omitted.
- * @param[in]   style       The mapping style.
+ * @param[out]      event       An empty event object.
+ * @param[in]       anchor      The mapping anchor or @c NULL.
+ * @param[in]       tag         The mapping tag or @c NULL.
+ * @param[in]       implicit    If the tag may be omitted.
+ * @param[in]       style       The mapping style.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -570,5 +577,5 @@
  * Create a MAPPING-END event.
  *
- * @param[out]  event       An empty event object.
+ * @param[out]      event       An empty event object.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -581,5 +588,5 @@
  * Free any memory allocated for an event object.
  *
- * @param[out]  event   An event object.
+ * @param[in,out]   event   An event object.
  */
 
@@ -604,8 +611,8 @@
 #define YAML_DEFAULT_SCALAR_TAG     YAML_STR_TAG
 #define YAML_DEFAULT_SEQUENCE_TAG   YAML_SEQ_TAG
-#define YAML_DEFAULT_MAPPING_STYLE  YAML_MAP_TAG
+#define YAML_DEFAULT_MAPPING_TAG    YAML_MAP_TAG
 
 /** Node types. */
-typedef enum {
+typedef enum yaml_node_type_e {
     YAML_NO_NODE,
 
@@ -615,21 +622,26 @@
 } yaml_node_type_t;
 
-#if 0
-
-typedef struct _yaml_node_t yaml_node_item_t;
-
-typedef struct {
-    yaml_node_item_t key;
-    yaml_node_item_t value;
+/** The forward definition of a document node structure. */
+typedef struct yaml_node_s yaml_node_t;
+
+/** An element of a sequence node. */
+typedef int yaml_node_item_t;
+
+/** An element of a mapping node. */
+typedef struct yaml_node_pair_s {
+    /** The key of the element. */
+    int key;
+    /** The value of the element. */
+    int value;
 } yaml_node_pair_t;
 
 /** The node structure. */
-typedef struct _yaml_node_t {
+struct yaml_node_s {
 
     /** The node type. */
     yaml_node_type_t type;
 
-    /* The reference counter. */
-    int references;
+    /** The node tag. */
+    yaml_char_t *tag;
 
     /** The node data. */
@@ -638,6 +650,4 @@
         /** The scalar parameters (for @c YAML_SCALAR_NODE). */
         struct {
-            /** The tag. */
-            yaml_char_t *tag;
             /** The scalar value. */
             yaml_char_t *value;
@@ -650,14 +660,12 @@
         /** The sequence parameters (for @c YAML_SEQUENCE_NODE). */
         struct {
-            /** The tag. */
-            yaml_char_t *tag;
             /** The stack of sequence items. */
             struct {
                 /** The beginning of the stack. */
-                struct yaml_node_item_t *start;
+                yaml_node_item_t *start;
                 /** The end of the stack. */
-                struct yaml_node_item_t *end;
+                yaml_node_item_t *end;
                 /** The top of the stack. */
-                struct yaml_node_item_t *top;
+                yaml_node_item_t *top;
             } items;
             /** The sequence style. */
@@ -667,14 +675,12 @@
         /** The mapping parameters (for @c YAML_MAPPING_NODE). */
         struct {
-            /** The tag. */
-            yaml_char_t *tag;
-            /** The stack of mapping pairs. */
+            /** The stack of mapping pairs (key, value). */
             struct {
                 /** The beginning of the stack. */
-                struct yaml_node_pair_t *start;
+                yaml_node_pair_t *start;
                 /** The end of the stack. */
-                struct yaml_node_pair_t *end;
+                yaml_node_pair_t *end;
                 /** The top of the stack. */
-                struct yaml_node_pair_t *top;
+                yaml_node_pair_t *top;
             } pairs;
             /** The mapping style. */
@@ -689,46 +695,167 @@
     yaml_mark_t end_mark;
 
-} yaml_node_t;
-
-/**
- * Create a SCALAR node.
+};
+
+/** The document structure. */
+typedef struct yaml_document_s {
+
+    /** The document nodes. */
+    struct {
+        /** The beginning of the stack. */
+        yaml_node_t *start;
+        /** The end of the stack. */
+        yaml_node_t *end;
+        /** The top of the stack. */
+        yaml_node_t *top;
+    } nodes;
+
+    /** The version directive. */
+    yaml_version_directive_t *version_directive;
+
+    /** The list of tag directives. */
+    struct {
+        /** The beginning of the tag directives list. */
+        yaml_tag_directive_t *start;
+        /** The end of the tag directives list. */
+        yaml_tag_directive_t *end;
+    } tag_directives;
+
+    /** Is the document start indicator implicit? */
+    int start_implicit;
+    /** Is the document end indicator implicit? */
+    int end_implicit;
+
+    /** The beginning of the document. */
+    yaml_mark_t start_mark;
+    /** The end of the document. */
+    yaml_mark_t end_mark;
+
+} yaml_document_t;
+
+/**
+ * Create a YAML document.
+ *
+ * @param[out]      document                An empty document object.
+ * @param[in]       version_directive       The %YAML directive value or
+ *                                          @c NULL.
+ * @param[in]       tag_directives_start    The beginning of the %TAG
+ *                                          directives list.
+ * @param[in]       tag_directives_end      The end of the %TAG directives
+ *                                          list.
+ * @param[in]       start_implicit          If the document start indicator is
+ *                                          implicit.
+ * @param[in]       end_implicit            If the document end indicator is
+ *                                          implicit.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_initialize(yaml_document_t *document,
+        yaml_version_directive_t *version_directive,
+        yaml_tag_directive_t *tag_directives_start,
+        yaml_tag_directive_t *tag_directives_end,
+        int start_implicit, int end_implicit);
+
+/**
+ * Delete a YAML document and all its nodes.
+ *
+ * @param[in,out]   document        A document object.
+ */
+
+YAML_DECLARE(void)
+yaml_document_delete(yaml_document_t *document);
+
+/**
+ * Get a node of a YAML document.
+ *
+ * The pointer returned by this function is valid until any of the functions
+ * modifying the documents are called.
+ *
+ * @param[in]       document        A document object.
+ * @param[in]       node            The node id.
+ *
+ * @returns the node objct or @c NULL if @c node_id is out of range.
+ */
+
+YAML_DECLARE(yaml_node_t *)
+yaml_document_get_node(yaml_document_t *document, int node_id);
+
+/**
+ * Get the root of a YAML document node.
+ *
+ * The root object is the first object added to the document.
+ *
+ * The pointer returned by this function is valid until any of the functions
+ * modifying the documents are called.
+ *
+ * An empty document produced by the parser signifies the end of a YAML
+ * stream.
+ *
+ * @param[in]       document        A document object.
+ *
+ * @returns the node object or @c NULL if the document is empty.
+ */
+
+YAML_DECLARE(yaml_node_t *)
+yaml_document_get_root_node(yaml_document_t *document);
+
+/**
+ * Create a SCALAR node and attach it to the document.
  *
  * The @a style argument may be ignored by the emitter.
  *
- * @param[out]  node            An empty node object.
- * @param[in]   tag             The scalar tag.
- * @param[in]   value           The scalar value.
- * @param[in]   length          The length of the scalar value.
- * @param[in]   style           The scalar style.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_scalar_node_initialize(yaml_node_t *node,
+ * @param[in,out]   document        A document object.
+ * @param[in]       tag             The scalar tag.
+ * @param[in]       value           The scalar value.
+ * @param[in]       length          The length of the scalar value.
+ * @param[in]       style           The scalar style.
+ *
+ * @returns the node id or @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_scalar(yaml_document_t *document,
         yaml_char_t *tag, yaml_char_t *value, int length,
         yaml_scalar_style_t style);
 
 /**
- * Create a SEQUENCE node.
+ * Create a SEQUENCE node and attach it to the document.
  *
  * The @a style argument may be ignored by the emitter.
  *
- * @param[out]  node        An empty node object.
- * @param[in]   tag         The sequence tag.
- * @param[in]   style       The sequence style.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_sequence_node_initialize(yaml_node_t *node,
+ * @param[in,out]   document    A document object.
+ * @param[in]       tag         The sequence tag.
+ * @param[in]       style       The sequence style.
+ *
+ * @returns the node id or @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_sequence(yaml_document_t *document,
         yaml_char_t *tag, yaml_sequence_style_t style);
 
 /**
- * Add an item to a SEQUENCE node
- *
- * @param[out]  node        A sequence node.
- * @param[in]   item        An item node.
+ * Create a MAPPING node and attach it to the document.
+ *
+ * The @a style argument may be ignored by the emitter.
+ *
+ * @param[in,out]   document    A document object.
+ * @param[in]       tag         The sequence tag.
+ * @param[in]       style       The sequence style.
+ *
+ * @returns the node id or @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_mapping(yaml_document_t *document,
+        yaml_char_t *tag, yaml_mapping_style_t style);
+
+/**
+ * Add an item to a SEQUENCE node.
+ *
+ * @param[in,out]   document    A document object.
+ * @param[in]       sequence    The sequence node id.
+ * @param[in]       item        The item node id.
 *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -736,152 +863,21 @@
 
 YAML_DECLARE(int)
-yaml_sequence_node_add_item(yaml_node_t *node, yaml_node_t *item)
-
-/**
- * Create a SCALAR node and add it to a SEQUENCE node.
- *
- * @param[out]  node        A sequence node.
- * @param[in]   tag         The scalar tag.
- * @param[in]   value       The scalar value.
- * @param[in]   length      The length of the scalar value.
- * @param[in]   style       The scalar style.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_sequence_node_add_scalar_item(yaml_node_t *node,
-        yaml_char_t *tag, yaml_char_t *value, int length,
-        yaml_scalar_style_t style);
-
-/**
- * Get the number of subnodes of a SEQUENCE node.
- *
- * @param[in]  node         A sequence node.
- *
- * @returns the number of subnodes.
- */
-
-YAML_DECLARE(size_t)
-yaml_sequence_node_get_length(yaml_node_t *node);
-
-/**
- * Get a subnode of a SEQUENCE node.
- *
- * @param[in]   node        A sequence node.
- * @param[in]   index       The index of a subnode.
- * @param[out]  item        A subnode.
- */
-
-YAML_DECLARE(void)
-yaml_sequence_node_get_item(yaml_node_t *node, size_t index,
-        yaml_node_t *item);
-
-/**
- * Create a MAPPING node.
- *
- * The @a style argument may be ignored by the emitter.
- *
- * @param[out]  node        An empty node object.
- * @param[in]   tag         The mapping tag.
- * @param[in]   style       The mapping style.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_mapping_node_initialize(yaml_node_t *node,
-        yaml_char_t *tag, yaml_mapping_style_t style);
-
-/**
- * Add a key/value pair of nodes to a MAPPING node.
- *
- * @param[out]  node        A mapping node.
- * @param[in]   key         A key node.
- * @param[in]   value       A value node.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_mapping_node_add_pair(yaml_node_t *node,
-        yaml_node_t *key, yaml_node_t *value)
-
-/**
- * Create a scalar key and add the key/value pair to a MAPPING node.
- *
- * @param[out]  node        A mapping node.
- * @param[in]   key_tag     The key node tag.
- * @param[in]   key_value   The key node value.
- * @param[in]   key_length  The length of the key node value.
- * @param[in]   key_style   The key node style.
- * @param[in]   value       A value node.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_sequence_node_add_scalar_key_pair(yaml_node_t *node,
-        yaml_char_t *key_tag, yaml_char_t *key_value, int key_length,
-        yaml_scalar_style_t key_style,
-        yaml_node_t *value);
-
-/**
- * Create a scalar key/value nodes and add the pair to a MAPPING node.
- *
- * @param[out]  node            A mapping node.
- * @param[in]   key_tag         The key node tag.
- * @param[in]   key_value       The key node value.
- * @param[in]   key_length      The length of the key node value.
- * @param[in]   key_style       The key node style.
- * @param[in]   value_tag       The value node tag.
- * @param[in]   value_value     The value node value.
- * @param[in]   value_length    The length of the value node value.
- * @param[in]   value_style     The value node style.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_sequence_node_add_scalar_pair(yaml_node_t *node,
-        yaml_char_t *key_tag, yaml_char_t *key_value, int key_length,
-        yaml_scalar_style_t key_style,
-        yaml_char_t *value_tag, yaml_char_t *value_value, int value_length,
-        yaml_scalar_style_t value_style);
-
-/**
- * Get the number of subnode pairs of a MAPPING node.
- *
- * @param[in]  node         A mapping node.
- *
- * @returns the number of pairs.
- */
-
-YAML_DECLARE(size_t)
-yaml_mapping_node_get_length(yaml_node_t *node);
-
-/**
- * Get a subnode of a SEQUENCE node.
- *
- * @param[in]   node        A sequence node.
- * @param[in]   index       The index of a subnode.
- * @param[out]  key         The key subnode.
- * @param[out]  value       The value subnode.
- */
-
-YAML_DECLARE(void)
-yaml_mapping_node_get_pair(yaml_node_t *node, size_t index,
-        yaml_node_t *key, yaml_node_t *value);
-
-/**
- * Delete a node and its subnodes.
- *
- * @param[out]  node    A node object.
- */
-
-YAML_DECLARE(void)
-yaml_node_delete(yaml_node_t *node);
-
-#endif
+yaml_document_append_sequence_item(yaml_document_t *document,
+        int sequence, int item);
+
+/**
+ * Add a pair of a key and a value to a MAPPING node.
+ *
+ * @param[in,out]   document    A document object.
+ * @param[in]       mapping     The mapping node id.
+ * @param[in]       key         The key node id.
+ * @param[in]       value       The value node id.
+*
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_append_mapping_pair(yaml_document_t *document,
+        int mapping, int key, int value);
 
 /** @} */
@@ -917,5 +913,5 @@
  */
 
-typedef struct {
+typedef struct yaml_simple_key_s {
     /** Is a simple key possible? */
     int possible;
@@ -934,5 +930,5 @@
  * The states of the parser.
  */
-typedef enum {
+typedef enum yaml_parser_state_e {
     YAML_PARSE_STREAM_START_STATE,
     YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE,
@@ -962,4 +958,17 @@
 
 /**
+ * This structure holds aliases data.
+ */
+
+typedef struct yaml_alias_data_s {
+    /** The anchor. */
+    yaml_char_t *anchor;
+    /** The node id. */
+    int index;
+    /** The anchor mark. */
+    yaml_mark_t mark;
+} yaml_alias_data_t;
+
+/**
  * The parser structure.
  *
@@ -968,5 +977,5 @@
  */
 
-typedef struct {
+typedef struct yaml_parser_s {
 
     /**
@@ -1168,4 +1177,26 @@
      */
 
+    /**
+     * @name Dumper stuff
+     * @{
+     */
+
+    /** The alias data. */
+    struct {
+        /** The beginning of the list. */
+        yaml_alias_data_t *start;
+        /** The end of the list. */
+        yaml_alias_data_t *end;
+        /** The top of the list. */
+        yaml_alias_data_t *top;
+    } aliases;
+
+    /** The currently parsed document. */
+    yaml_document_t *document;
+
+    /**
+     * @}
+     */
+
 } yaml_parser_t;
 
@@ -1176,5 +1207,5 @@
  * for destroying the object using the yaml_parser_delete() function.
  *
- * @param[out]  parser  An empty parser object.
+ * @param[out]      parser  An empty parser object.
  *
  * @returns @c 1 if the function succeeded, @c 0 on error.
@@ -1257,5 +1288,6 @@
  *
  * An application must not alternate the calls of yaml_parser_scan() with the
- * calls of yaml_parser_parse(). Doing this will break the parser.
+ * calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break
+ * the parser.
  *
  * @param[in,out]   parser      A parser object.
@@ -1279,6 +1311,7 @@
  * produced event object using the yaml_event_delete() function.
  *
- * An application must not alternate the calls of yaml_parser_scan() with the
- * calls of yaml_parser_parse(). Doing this will break the parser.
+ * An application must not alternate the calls of yaml_parser_parse() with the
+ * calls of yaml_parser_scan() or yaml_parser_load(). Doing this will break the
+ * parser.
  *
  * @param[in,out]   parser      A parser object.
@@ -1290,4 +1323,29 @@
 YAML_DECLARE(int)
 yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
+
+/**
+ * Parse the input stream and produce the next YAML document.
+ *
+ * Call this function subsequently to produce a sequence of documents
+ * constituting the input stream.
+ *
+ * If the produced document has no root node, it means that the document
+ * end has been reached.
+ *
+ * An application is responsible for freeing any data associated with the
+ * produced document object using the yaml_document_delete() function.
+ *
+ * An application must not alternate the calls of yaml_parser_load() with the
+ * calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break
+ * the parser.
+ *
+ * @param[in,out]   parser      A parser object.
+ * @param[out]      document    An empty document object.
+ *
+ * @return @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
 
 /** @} */
@@ -1317,5 +1375,5 @@
 
 /** The emitter states. */
-typedef enum {
+typedef enum yaml_emitter_state_e {
     YAML_EMIT_STREAM_START_STATE,
     YAML_EMIT_FIRST_DOCUMENT_START_STATE,
@@ -1345,5 +1403,5 @@
  */
 
-typedef struct {
+typedef struct yaml_emitter_s {
 
     /**
@@ -1550,4 +1608,34 @@
      */
 
+    /**
+     * @name Dumper stuff
+     * @{
+     */
+
+    /** If the stream was already opened? */
+    int opened;
+    /** If the stream was already closed? */
+    int closed;
+
+    /** The information associated with the document nodes. */
+    struct {
+        /** The number of references. */
+        int references;
+        /** The anchor id. */
+        int anchor;
+        /** If the node has been emitted? */
+        int serialized;
+    } *anchors;
+
+    /** The last assigned anchor id. */
+    int last_anchor_id;
+
+    /** The currently emitted document. */
+    yaml_document_t *document;
+
+    /**
+     * @}
+     */
+
 } yaml_emitter_t;
 
@@ -1698,4 +1786,47 @@
 yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event);
 
+/*
+ * Start a YAML stream.
+ *
+ * This function should be used before yaml_emitter_dump() is called.
+ *
+ * @param[in,out]   emitter     An emitter object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_open(yaml_emitter_t *emitter);
+
+/*
+ * Finish a YAML stream.
+ *
+ * This function should be used after yaml_emitter_dump() is called.
+ *
+ * @param[in,out]   emitter     An emitter object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_close(yaml_emitter_t *emitter);
+
+/*
+ * Emit a YAML document.
+ *
+ * The documen object may be generated using the yaml_parser_load() function
+ * or the yaml_document_initialize() function.  The emitter takes the
+ * responsibility for the document object and destoys its content after
+ * it is emitted. The document object is destroyedeven if the function fails.
+ *
+ * @param[in,out]   emitter     An emitter object.
+ * @param[in,out]   document    A document object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
+
 /**
  * Flush the accumulated characters to the output.
