Import unsafe-libyaml

Bug: 277909042
Test: build
Change-Id: I51f314d42db5cdb161e14df5ec5e20fd45876088
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..09e6054
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "9651508612c804480141a6f57839e7af729559f7"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..7507077
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: dtolnay
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..8661567
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,95 @@
+name: CI
+
+on:
+  push:
+  pull_request:
+  workflow_dispatch:
+  schedule: [cron: "40 1 * * *"]
+
+permissions:
+  contents: read
+
+env:
+  RUSTFLAGS: -Dwarnings
+
+jobs:
+  pre_ci:
+    uses: dtolnay/.github/.github/workflows/pre_ci.yml@master
+
+  test:
+    name: Rust ${{matrix.rust}}
+    needs: pre_ci
+    if: needs.pre_ci.outputs.continue
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        rust: [nightly, beta, stable, 1.62.0]
+    timeout-minutes: 45
+    steps:
+      - uses: actions/checkout@v3
+      - uses: dtolnay/rust-toolchain@master
+        with:
+          toolchain: ${{matrix.rust}}
+      - name: Enable type layout randomization
+        run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV
+        if: matrix.rust == 'nightly'
+      - run: cargo test
+
+  msrv:
+    name: Rust 1.56.0
+    needs: pre_ci
+    if: needs.pre_ci.outputs.continue
+    runs-on: ubuntu-latest
+    timeout-minutes: 45
+    steps:
+      - uses: actions/checkout@v3
+      - uses: dtolnay/rust-toolchain@1.56.0
+      - run: cargo check --lib
+
+  clippy:
+    name: Clippy
+    runs-on: ubuntu-latest
+    if: github.event_name != 'pull_request'
+    timeout-minutes: 45
+    steps:
+      - uses: actions/checkout@v3
+      - uses: dtolnay/rust-toolchain@clippy
+      - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic
+
+  miri:
+    name: Miri
+    needs: pre_ci
+    if: needs.pre_ci.outputs.continue
+    runs-on: ubuntu-latest
+    timeout-minutes: 45
+    steps:
+      - uses: actions/checkout@v3
+      - uses: dtolnay/rust-toolchain@miri
+      - run: cargo miri setup
+      - run: cargo miri test
+        env:
+          MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-strict-provenance
+
+  fuzz:
+    name: Fuzz
+    needs: pre_ci
+    if: needs.pre_ci.outputs.continue
+    runs-on: ubuntu-latest
+    timeout-minutes: 45
+    steps:
+      - uses: actions/checkout@v3
+      - uses: dtolnay/rust-toolchain@nightly
+      - uses: dtolnay/install@cargo-fuzz
+      - run: cargo fuzz check
+
+  outdated:
+    name: Outdated
+    runs-on: ubuntu-latest
+    if: github.event_name != 'pull_request'
+    timeout-minutes: 45
+    steps:
+      - uses: actions/checkout@v3
+      - uses: dtolnay/install@cargo-outdated
+      - run: cargo outdated --workspace --exit-code 1
+      - run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b3a0655
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/build.rs
+/rust-toolchain
+target
+Cargo.lock
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..078508e
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,37 @@
+// This file is generated by cargo2android.py --run --force-rlib.
+// Do not modify this file as changes will be overridden on upgrade.
+
+
+
+rust_library_host_rlib {
+    name: "libunsafe_libyaml",
+    crate_name: "unsafe_libyaml",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.2.9",
+    srcs: ["src/lib.rs"],
+    edition: "2021",
+}
+
+rust_binary_host {
+    name: "run_emitter_test_suite",
+    crate_name: "run_emitter_test_suite",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.2.9",
+    srcs: ["src/bin/run-emitter-test-suite.rs"],
+    edition: "2021",
+    rustlibs: [
+        "libunsafe_libyaml",
+    ],
+}
+
+rust_binary_host {
+    name: "run_parser_test_suite",
+    crate_name: "run_parser_test_suite",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.2.9",
+    srcs: ["src/bin/run-parser-test-suite.rs"],
+    edition: "2021",
+    rustlibs: [
+        "libunsafe_libyaml",
+    ],
+}
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..31efefc
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,38 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.56"
+name = "unsafe-libyaml"
+version = "0.2.9"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+description = "libyaml transpiled to rust by c2rust"
+documentation = "https://docs.rs/unsafe-libyaml"
+readme = "README.md"
+keywords = ["yaml"]
+categories = [
+    "encoding",
+    "parser-implementations",
+    "no-std",
+]
+license = "MIT"
+repository = "https://github.com/dtolnay/unsafe-libyaml"
+
+[package.metadata.docs.rs]
+rustdoc-args = ["--generate-link-to-definition"]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[lib]
+doc-scrape-examples = false
+
+[dev-dependencies.pretty_assertions]
+version = "1.0"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..e6186b8
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,24 @@
+[package]
+name = "unsafe-libyaml"
+version = "0.2.9" # remember to update html_root_url
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+categories = ["encoding", "parser-implementations", "no-std"]
+description = "libyaml transpiled to rust by c2rust"
+documentation = "https://docs.rs/unsafe-libyaml"
+edition = "2021"
+keywords = ["yaml"]
+license = "MIT"
+repository = "https://github.com/dtolnay/unsafe-libyaml"
+rust-version = "1.56"
+
+[workspace]
+[dev-dependencies]
+pretty_assertions = "1.0"
+unsafe-libyaml-test-suite = { path = "tests/data" }
+
+[lib]
+doc-scrape-examples = false
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+rustdoc-args = ["--generate-link-to-definition"]
diff --git a/LICENSE b/LICENSE
new file mode 120000
index 0000000..7f9a88e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1 @@
+LICENSE-MIT
\ No newline at end of file
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..31aa793
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..ba4f960
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,19 @@
+name: "unsafe-libyaml"
+description: "libyaml transpiled to rust by c2rust"
+third_party {
+  identifier {
+    type: "crates.io"
+    value: "https://crates.io/crates/unsafe-libyaml"
+  }
+  identifier {
+    type: "Archive"
+    value: "https://static.crates.io/crates/unsafe-libyaml/unsafe-libyaml-0.2.9.crate"
+  }
+  version: "0.2.9"
+  license_type: NOTICE
+  last_upgrade_date {
+    year: 2023
+    month: 8
+    day: 23
+  }
+}
diff --git a/MODULE_LICENSE_MIT b/MODULE_LICENSE_MIT
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_MIT
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..45dc4dd
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1 @@
+include platform/prebuilts/rust:master:/OWNERS
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bfe37a7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,24 @@
+unsafe-libyaml
+==============
+
+[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/unsafe--libyaml-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/unsafe-libyaml)
+[<img alt="crates.io" src="https://img.shields.io/crates/v/unsafe-libyaml.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/unsafe-libyaml)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-unsafe--libyaml-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/unsafe-libyaml)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/unsafe-libyaml/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/unsafe-libyaml/actions?query=branch%3Amaster)
+
+This library is [libyaml] translated from C to unsafe Rust with the assistance
+of [c2rust].
+
+[libyaml]: https://github.com/yaml/libyaml/tree/2c891fc7a770e8ba2fec34fc6b545c672beb37e6
+[c2rust]: https://github.com/immunant/c2rust
+
+```toml
+[dependencies]
+unsafe-libyaml = "0.2"
+```
+
+*Compiler support: requires rustc 1.56+*
+
+## License
+
+<a href="LICENSE-MIT">MIT license</a>, same as libyaml.
diff --git a/src/api.rs b/src/api.rs
new file mode 100644
index 0000000..2e44d66
--- /dev/null
+++ b/src/api.rs
@@ -0,0 +1,1545 @@
+use crate::externs::{free, malloc, memcpy, memmove, memset, realloc, strdup, strlen};
+use crate::success::{Success, FAIL, OK};
+use crate::yaml::{size_t, yaml_char_t};
+use crate::{
+    libc, yaml_break_t, yaml_document_t, yaml_emitter_state_t, yaml_emitter_t, yaml_encoding_t,
+    yaml_event_t, yaml_mapping_style_t, yaml_mark_t, yaml_node_item_t, yaml_node_pair_t,
+    yaml_node_t, yaml_parser_state_t, yaml_parser_t, yaml_read_handler_t, yaml_scalar_style_t,
+    yaml_sequence_style_t, yaml_simple_key_t, yaml_tag_directive_t, yaml_token_t,
+    yaml_version_directive_t, yaml_write_handler_t, PointerExt, YAML_ALIAS_EVENT, YAML_ALIAS_TOKEN,
+    YAML_ANCHOR_TOKEN, YAML_ANY_ENCODING, YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_START_EVENT,
+    YAML_MAPPING_END_EVENT, YAML_MAPPING_NODE, YAML_MAPPING_START_EVENT, YAML_SCALAR_EVENT,
+    YAML_SCALAR_NODE, YAML_SCALAR_TOKEN, YAML_SEQUENCE_END_EVENT, YAML_SEQUENCE_NODE,
+    YAML_SEQUENCE_START_EVENT, YAML_STREAM_END_EVENT, YAML_STREAM_START_EVENT,
+    YAML_TAG_DIRECTIVE_TOKEN, YAML_TAG_TOKEN,
+};
+use core::mem::{size_of, MaybeUninit};
+use core::ptr::{self, addr_of_mut};
+
+const INPUT_RAW_BUFFER_SIZE: usize = 16384;
+const INPUT_BUFFER_SIZE: usize = INPUT_RAW_BUFFER_SIZE * 3;
+const OUTPUT_BUFFER_SIZE: usize = 16384;
+const OUTPUT_RAW_BUFFER_SIZE: usize = OUTPUT_BUFFER_SIZE * 2 + 2;
+
+pub(crate) unsafe fn yaml_malloc(size: size_t) -> *mut libc::c_void {
+    malloc(size)
+}
+
+pub(crate) unsafe fn yaml_realloc(ptr: *mut libc::c_void, size: size_t) -> *mut libc::c_void {
+    if !ptr.is_null() {
+        realloc(ptr, size)
+    } else {
+        malloc(size)
+    }
+}
+
+pub(crate) unsafe fn yaml_free(ptr: *mut libc::c_void) {
+    if !ptr.is_null() {
+        free(ptr);
+    }
+}
+
+pub(crate) unsafe fn yaml_strdup(str: *const yaml_char_t) -> *mut yaml_char_t {
+    if str.is_null() {
+        return ptr::null_mut::<yaml_char_t>();
+    }
+    strdup(str as *mut libc::c_char) as *mut yaml_char_t
+}
+
+pub(crate) unsafe fn yaml_string_extend(
+    start: *mut *mut yaml_char_t,
+    pointer: *mut *mut yaml_char_t,
+    end: *mut *mut yaml_char_t,
+) {
+    let new_start: *mut yaml_char_t = yaml_realloc(
+        *start as *mut libc::c_void,
+        ((*end).c_offset_from(*start) as libc::c_long * 2_i64) as size_t,
+    ) as *mut yaml_char_t;
+    memset(
+        new_start.wrapping_offset((*end).c_offset_from(*start) as libc::c_long as isize)
+            as *mut libc::c_void,
+        0,
+        (*end).c_offset_from(*start) as libc::c_long as libc::c_ulong,
+    );
+    *pointer = new_start.wrapping_offset((*pointer).c_offset_from(*start) as libc::c_long as isize);
+    *end =
+        new_start.wrapping_offset(((*end).c_offset_from(*start) as libc::c_long * 2_i64) as isize);
+    *start = new_start;
+}
+
+pub(crate) unsafe fn yaml_string_join(
+    a_start: *mut *mut yaml_char_t,
+    a_pointer: *mut *mut yaml_char_t,
+    a_end: *mut *mut yaml_char_t,
+    b_start: *mut *mut yaml_char_t,
+    b_pointer: *mut *mut yaml_char_t,
+    _b_end: *mut *mut yaml_char_t,
+) {
+    if *b_start == *b_pointer {
+        return;
+    }
+    while (*a_end).c_offset_from(*a_pointer) as libc::c_long
+        <= (*b_pointer).c_offset_from(*b_start) as libc::c_long
+    {
+        yaml_string_extend(a_start, a_pointer, a_end);
+    }
+    memcpy(
+        *a_pointer as *mut libc::c_void,
+        *b_start as *const libc::c_void,
+        (*b_pointer).c_offset_from(*b_start) as libc::c_long as libc::c_ulong,
+    );
+    *a_pointer =
+        (*a_pointer).wrapping_offset((*b_pointer).c_offset_from(*b_start) as libc::c_long as isize);
+}
+
+pub(crate) unsafe fn yaml_stack_extend(
+    start: *mut *mut libc::c_void,
+    top: *mut *mut libc::c_void,
+    end: *mut *mut libc::c_void,
+) {
+    let new_start: *mut libc::c_void = yaml_realloc(
+        *start,
+        ((*end as *mut libc::c_char).c_offset_from(*start as *mut libc::c_char) as libc::c_long
+            * 2_i64) as size_t,
+    );
+    *top = (new_start as *mut libc::c_char).wrapping_offset(
+        (*top as *mut libc::c_char).c_offset_from(*start as *mut libc::c_char) as libc::c_long
+            as isize,
+    ) as *mut libc::c_void;
+    *end = (new_start as *mut libc::c_char).wrapping_offset(
+        ((*end as *mut libc::c_char).c_offset_from(*start as *mut libc::c_char) as libc::c_long
+            * 2_i64) as isize,
+    ) as *mut libc::c_void;
+    *start = new_start;
+}
+
+pub(crate) unsafe fn yaml_queue_extend(
+    start: *mut *mut libc::c_void,
+    head: *mut *mut libc::c_void,
+    tail: *mut *mut libc::c_void,
+    end: *mut *mut libc::c_void,
+) {
+    if *start == *head && *tail == *end {
+        let new_start: *mut libc::c_void = yaml_realloc(
+            *start,
+            ((*end as *mut libc::c_char).c_offset_from(*start as *mut libc::c_char) as libc::c_long
+                * 2_i64) as size_t,
+        );
+        *head = (new_start as *mut libc::c_char).wrapping_offset(
+            (*head as *mut libc::c_char).c_offset_from(*start as *mut libc::c_char) as libc::c_long
+                as isize,
+        ) as *mut libc::c_void;
+        *tail = (new_start as *mut libc::c_char).wrapping_offset(
+            (*tail as *mut libc::c_char).c_offset_from(*start as *mut libc::c_char) as libc::c_long
+                as isize,
+        ) as *mut libc::c_void;
+        *end = (new_start as *mut libc::c_char).wrapping_offset(
+            ((*end as *mut libc::c_char).c_offset_from(*start as *mut libc::c_char) as libc::c_long
+                * 2_i64) as isize,
+        ) as *mut libc::c_void;
+        *start = new_start;
+    }
+    if *tail == *end {
+        if *head != *tail {
+            memmove(
+                *start,
+                *head,
+                (*tail as *mut libc::c_char).c_offset_from(*head as *mut libc::c_char)
+                    as libc::c_long as libc::c_ulong,
+            );
+        }
+        *tail = (*start as *mut libc::c_char).wrapping_offset(
+            (*tail as *mut libc::c_char).c_offset_from(*head as *mut libc::c_char) as libc::c_long
+                as isize,
+        ) as *mut libc::c_void;
+        *head = *start;
+    }
+}
+
+/// Initialize a parser.
+///
+/// This function creates a new parser object. An application is responsible
+/// for destroying the object using the yaml_parser_delete() function.
+pub unsafe fn yaml_parser_initialize(parser: *mut yaml_parser_t) -> Success {
+    __assert!(!parser.is_null());
+    memset(
+        parser as *mut libc::c_void,
+        0,
+        size_of::<yaml_parser_t>() as libc::c_ulong,
+    );
+    BUFFER_INIT!((*parser).raw_buffer, INPUT_RAW_BUFFER_SIZE);
+    BUFFER_INIT!((*parser).buffer, INPUT_BUFFER_SIZE);
+    QUEUE_INIT!((*parser).tokens, yaml_token_t);
+    STACK_INIT!((*parser).indents, libc::c_int);
+    STACK_INIT!((*parser).simple_keys, yaml_simple_key_t);
+    STACK_INIT!((*parser).states, yaml_parser_state_t);
+    STACK_INIT!((*parser).marks, yaml_mark_t);
+    STACK_INIT!((*parser).tag_directives, yaml_tag_directive_t);
+    OK
+}
+
+/// Destroy a parser.
+pub unsafe fn yaml_parser_delete(parser: *mut yaml_parser_t) {
+    __assert!(!parser.is_null());
+    BUFFER_DEL!((*parser).raw_buffer);
+    BUFFER_DEL!((*parser).buffer);
+    while !QUEUE_EMPTY!((*parser).tokens) {
+        yaml_token_delete(addr_of_mut!(DEQUEUE!((*parser).tokens)));
+    }
+    QUEUE_DEL!((*parser).tokens);
+    STACK_DEL!((*parser).indents);
+    STACK_DEL!((*parser).simple_keys);
+    STACK_DEL!((*parser).states);
+    STACK_DEL!((*parser).marks);
+    while !STACK_EMPTY!((*parser).tag_directives) {
+        let tag_directive = POP!((*parser).tag_directives);
+        yaml_free(tag_directive.handle as *mut libc::c_void);
+        yaml_free(tag_directive.prefix as *mut libc::c_void);
+    }
+    STACK_DEL!((*parser).tag_directives);
+    memset(
+        parser as *mut libc::c_void,
+        0,
+        size_of::<yaml_parser_t>() as libc::c_ulong,
+    );
+}
+
+unsafe fn yaml_string_read_handler(
+    data: *mut libc::c_void,
+    buffer: *mut libc::c_uchar,
+    mut size: size_t,
+    size_read: *mut size_t,
+) -> libc::c_int {
+    let parser: *mut yaml_parser_t = data as *mut yaml_parser_t;
+    if (*parser).input.string.current == (*parser).input.string.end {
+        *size_read = 0_u64;
+        return 1;
+    }
+    if size
+        > (*parser)
+            .input
+            .string
+            .end
+            .c_offset_from((*parser).input.string.current) as libc::c_long as size_t
+    {
+        size = (*parser)
+            .input
+            .string
+            .end
+            .c_offset_from((*parser).input.string.current) as libc::c_long as size_t;
+    }
+    memcpy(
+        buffer as *mut libc::c_void,
+        (*parser).input.string.current as *const libc::c_void,
+        size,
+    );
+    let fresh80 = addr_of_mut!((*parser).input.string.current);
+    *fresh80 = (*fresh80).wrapping_offset(size as isize);
+    *size_read = size;
+    1
+}
+
+/// Set a string input.
+///
+/// Note that the `input` pointer must be valid while the `parser` object
+/// exists. The application is responsible for destroying `input` after
+/// destroying the `parser`.
+pub unsafe fn yaml_parser_set_input_string(
+    parser: *mut yaml_parser_t,
+    input: *const libc::c_uchar,
+    size: size_t,
+) {
+    __assert!(!parser.is_null());
+    __assert!(((*parser).read_handler).is_none());
+    __assert!(!input.is_null());
+    let fresh81 = addr_of_mut!((*parser).read_handler);
+    *fresh81 = Some(
+        yaml_string_read_handler
+            as unsafe fn(*mut libc::c_void, *mut libc::c_uchar, size_t, *mut size_t) -> libc::c_int,
+    );
+    let fresh82 = addr_of_mut!((*parser).read_handler_data);
+    *fresh82 = parser as *mut libc::c_void;
+    let fresh83 = addr_of_mut!((*parser).input.string.start);
+    *fresh83 = input;
+    let fresh84 = addr_of_mut!((*parser).input.string.current);
+    *fresh84 = input;
+    let fresh85 = addr_of_mut!((*parser).input.string.end);
+    *fresh85 = input.wrapping_offset(size as isize);
+}
+
+/// Set a generic input handler.
+pub unsafe fn yaml_parser_set_input(
+    parser: *mut yaml_parser_t,
+    handler: yaml_read_handler_t,
+    data: *mut libc::c_void,
+) {
+    __assert!(!parser.is_null());
+    __assert!(((*parser).read_handler).is_none());
+    let fresh89 = addr_of_mut!((*parser).read_handler);
+    *fresh89 = Some(handler);
+    let fresh90 = addr_of_mut!((*parser).read_handler_data);
+    *fresh90 = data;
+}
+
+/// Set the source encoding.
+pub unsafe fn yaml_parser_set_encoding(parser: *mut yaml_parser_t, encoding: yaml_encoding_t) {
+    __assert!(!parser.is_null());
+    __assert!((*parser).encoding == YAML_ANY_ENCODING);
+    (*parser).encoding = encoding;
+}
+
+/// Initialize an emitter.
+///
+/// This function creates a new emitter object. An application is responsible
+/// for destroying the object using the yaml_emitter_delete() function.
+pub unsafe fn yaml_emitter_initialize(emitter: *mut yaml_emitter_t) -> Success {
+    __assert!(!emitter.is_null());
+    memset(
+        emitter as *mut libc::c_void,
+        0,
+        size_of::<yaml_emitter_t>() as libc::c_ulong,
+    );
+    BUFFER_INIT!((*emitter).buffer, OUTPUT_BUFFER_SIZE);
+    BUFFER_INIT!((*emitter).raw_buffer, OUTPUT_RAW_BUFFER_SIZE);
+    STACK_INIT!((*emitter).states, yaml_emitter_state_t);
+    QUEUE_INIT!((*emitter).events, yaml_event_t);
+    STACK_INIT!((*emitter).indents, libc::c_int);
+    STACK_INIT!((*emitter).tag_directives, yaml_tag_directive_t);
+    OK
+}
+
+/// Destroy an emitter.
+pub unsafe fn yaml_emitter_delete(emitter: *mut yaml_emitter_t) {
+    __assert!(!emitter.is_null());
+    BUFFER_DEL!((*emitter).buffer);
+    BUFFER_DEL!((*emitter).raw_buffer);
+    STACK_DEL!((*emitter).states);
+    while !QUEUE_EMPTY!((*emitter).events) {
+        yaml_event_delete(addr_of_mut!(DEQUEUE!((*emitter).events)));
+    }
+    QUEUE_DEL!((*emitter).events);
+    STACK_DEL!((*emitter).indents);
+    while !STACK_EMPTY!((*emitter).tag_directives) {
+        let tag_directive = POP!((*emitter).tag_directives);
+        yaml_free(tag_directive.handle as *mut libc::c_void);
+        yaml_free(tag_directive.prefix as *mut libc::c_void);
+    }
+    STACK_DEL!((*emitter).tag_directives);
+    yaml_free((*emitter).anchors as *mut libc::c_void);
+    memset(
+        emitter as *mut libc::c_void,
+        0,
+        size_of::<yaml_emitter_t>() as libc::c_ulong,
+    );
+}
+
+unsafe fn yaml_string_write_handler(
+    data: *mut libc::c_void,
+    buffer: *mut libc::c_uchar,
+    size: size_t,
+) -> libc::c_int {
+    let emitter: *mut yaml_emitter_t = data as *mut yaml_emitter_t;
+    if (*emitter)
+        .output
+        .string
+        .size
+        .wrapping_sub(*(*emitter).output.string.size_written)
+        < size
+    {
+        memcpy(
+            (*emitter)
+                .output
+                .string
+                .buffer
+                .wrapping_offset(*(*emitter).output.string.size_written as isize)
+                as *mut libc::c_void,
+            buffer as *const libc::c_void,
+            (*emitter)
+                .output
+                .string
+                .size
+                .wrapping_sub(*(*emitter).output.string.size_written),
+        );
+        *(*emitter).output.string.size_written = (*emitter).output.string.size;
+        return 0;
+    }
+    memcpy(
+        (*emitter)
+            .output
+            .string
+            .buffer
+            .wrapping_offset(*(*emitter).output.string.size_written as isize)
+            as *mut libc::c_void,
+        buffer as *const libc::c_void,
+        size,
+    );
+    let fresh153 = addr_of_mut!((*(*emitter).output.string.size_written));
+    *fresh153 = (*fresh153 as libc::c_ulong).wrapping_add(size) as size_t as size_t;
+    1
+}
+
+/// Set a string output.
+///
+/// The emitter will write the output characters to the `output` buffer of the
+/// size `size`. The emitter will set `size_written` to the number of written
+/// bytes. If the buffer is smaller than required, the emitter produces the
+/// YAML_WRITE_ERROR error.
+pub unsafe fn yaml_emitter_set_output_string(
+    emitter: *mut yaml_emitter_t,
+    output: *mut libc::c_uchar,
+    size: size_t,
+    size_written: *mut size_t,
+) {
+    __assert!(!emitter.is_null());
+    __assert!(((*emitter).write_handler).is_none());
+    __assert!(!output.is_null());
+    let fresh154 = addr_of_mut!((*emitter).write_handler);
+    *fresh154 = Some(
+        yaml_string_write_handler
+            as unsafe fn(*mut libc::c_void, *mut libc::c_uchar, size_t) -> libc::c_int,
+    );
+    let fresh155 = addr_of_mut!((*emitter).write_handler_data);
+    *fresh155 = emitter as *mut libc::c_void;
+    let fresh156 = addr_of_mut!((*emitter).output.string.buffer);
+    *fresh156 = output;
+    (*emitter).output.string.size = size;
+    let fresh157 = addr_of_mut!((*emitter).output.string.size_written);
+    *fresh157 = size_written;
+    *size_written = 0_u64;
+}
+
+/// Set a generic output handler.
+pub unsafe fn yaml_emitter_set_output(
+    emitter: *mut yaml_emitter_t,
+    handler: yaml_write_handler_t,
+    data: *mut libc::c_void,
+) {
+    __assert!(!emitter.is_null());
+    __assert!(((*emitter).write_handler).is_none());
+    let fresh161 = addr_of_mut!((*emitter).write_handler);
+    *fresh161 = Some(handler);
+    let fresh162 = addr_of_mut!((*emitter).write_handler_data);
+    *fresh162 = data;
+}
+
+/// Set the output encoding.
+pub unsafe fn yaml_emitter_set_encoding(emitter: *mut yaml_emitter_t, encoding: yaml_encoding_t) {
+    __assert!(!emitter.is_null());
+    __assert!((*emitter).encoding == YAML_ANY_ENCODING);
+    (*emitter).encoding = encoding;
+}
+
+/// Set if the output should be in the "canonical" format as in the YAML
+/// specification.
+pub unsafe fn yaml_emitter_set_canonical(emitter: *mut yaml_emitter_t, canonical: bool) {
+    __assert!(!emitter.is_null());
+    (*emitter).canonical = canonical;
+}
+
+/// Set the indentation increment.
+pub unsafe fn yaml_emitter_set_indent(emitter: *mut yaml_emitter_t, indent: libc::c_int) {
+    __assert!(!emitter.is_null());
+    (*emitter).best_indent = if 1 < indent && indent < 10 { indent } else { 2 };
+}
+
+/// Set the preferred line width. -1 means unlimited.
+pub unsafe fn yaml_emitter_set_width(emitter: *mut yaml_emitter_t, width: libc::c_int) {
+    __assert!(!emitter.is_null());
+    (*emitter).best_width = if width >= 0 { width } else { -1 };
+}
+
+/// Set if unescaped non-ASCII characters are allowed.
+pub unsafe fn yaml_emitter_set_unicode(emitter: *mut yaml_emitter_t, unicode: bool) {
+    __assert!(!emitter.is_null());
+    (*emitter).unicode = unicode;
+}
+
+/// Set the preferred line break.
+pub unsafe fn yaml_emitter_set_break(emitter: *mut yaml_emitter_t, line_break: yaml_break_t) {
+    __assert!(!emitter.is_null());
+    (*emitter).line_break = line_break;
+}
+
+/// Free any memory allocated for a token object.
+pub unsafe fn yaml_token_delete(token: *mut yaml_token_t) {
+    __assert!(!token.is_null());
+    match (*token).type_ {
+        YAML_TAG_DIRECTIVE_TOKEN => {
+            yaml_free((*token).data.tag_directive.handle as *mut libc::c_void);
+            yaml_free((*token).data.tag_directive.prefix as *mut libc::c_void);
+        }
+        YAML_ALIAS_TOKEN => {
+            yaml_free((*token).data.alias.value as *mut libc::c_void);
+        }
+        YAML_ANCHOR_TOKEN => {
+            yaml_free((*token).data.anchor.value as *mut libc::c_void);
+        }
+        YAML_TAG_TOKEN => {
+            yaml_free((*token).data.tag.handle as *mut libc::c_void);
+            yaml_free((*token).data.tag.suffix as *mut libc::c_void);
+        }
+        YAML_SCALAR_TOKEN => {
+            yaml_free((*token).data.scalar.value as *mut libc::c_void);
+        }
+        _ => {}
+    }
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+}
+
+unsafe fn yaml_check_utf8(start: *const yaml_char_t, length: size_t) -> Success {
+    let end: *const yaml_char_t = start.wrapping_offset(length as isize);
+    let mut pointer: *const yaml_char_t = start;
+    while pointer < end {
+        let mut octet: libc::c_uchar;
+        let mut value: libc::c_uint;
+        let mut k: size_t;
+        octet = *pointer;
+        let width: libc::c_uint = if octet & 0x80 == 0 {
+            1
+        } else if octet & 0xE0 == 0xC0 {
+            2
+        } else if octet & 0xF0 == 0xE0 {
+            3
+        } else if octet & 0xF8 == 0xF0 {
+            4
+        } else {
+            0
+        } as libc::c_uint;
+        value = if octet & 0x80 == 0 {
+            octet & 0x7F
+        } else if octet & 0xE0 == 0xC0 {
+            octet & 0x1F
+        } else if octet & 0xF0 == 0xE0 {
+            octet & 0xF
+        } else if octet & 0xF8 == 0xF0 {
+            octet & 0x7
+        } else {
+            0
+        } as libc::c_uint;
+        if width == 0 {
+            return FAIL;
+        }
+        if pointer.wrapping_offset(width as isize) > end {
+            return FAIL;
+        }
+        k = 1_u64;
+        while k < width as libc::c_ulong {
+            octet = *pointer.wrapping_offset(k as isize);
+            if octet & 0xC0 != 0x80 {
+                return FAIL;
+            }
+            value = (value << 6).wrapping_add((octet & 0x3F) as libc::c_uint);
+            k = k.wrapping_add(1);
+        }
+        if !(width == 1
+            || width == 2 && value >= 0x80
+            || width == 3 && value >= 0x800
+            || width == 4 && value >= 0x10000)
+        {
+            return FAIL;
+        }
+        pointer = pointer.wrapping_offset(width as isize);
+    }
+    OK
+}
+
+/// Create the STREAM-START event.
+pub unsafe fn yaml_stream_start_event_initialize(
+    event: *mut yaml_event_t,
+    encoding: yaml_encoding_t,
+) -> Success {
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    __assert!(!event.is_null());
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_STREAM_START_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    (*event).data.stream_start.encoding = encoding;
+    OK
+}
+
+/// Create the STREAM-END event.
+pub unsafe fn yaml_stream_end_event_initialize(event: *mut yaml_event_t) -> Success {
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    __assert!(!event.is_null());
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_STREAM_END_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    OK
+}
+
+/// Create the DOCUMENT-START event.
+///
+/// The `implicit` argument is considered as a stylistic parameter and may be
+/// ignored by the emitter.
+pub unsafe fn yaml_document_start_event_initialize(
+    event: *mut yaml_event_t,
+    version_directive: *mut yaml_version_directive_t,
+    tag_directives_start: *mut yaml_tag_directive_t,
+    tag_directives_end: *mut yaml_tag_directive_t,
+    implicit: bool,
+) -> Success {
+    let current_block: u64;
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    let mut version_directive_copy: *mut yaml_version_directive_t =
+        ptr::null_mut::<yaml_version_directive_t>();
+    struct TagDirectivesCopy {
+        start: *mut yaml_tag_directive_t,
+        end: *mut yaml_tag_directive_t,
+        top: *mut yaml_tag_directive_t,
+    }
+    let mut tag_directives_copy = TagDirectivesCopy {
+        start: ptr::null_mut::<yaml_tag_directive_t>(),
+        end: ptr::null_mut::<yaml_tag_directive_t>(),
+        top: ptr::null_mut::<yaml_tag_directive_t>(),
+    };
+    let mut value = yaml_tag_directive_t {
+        handle: ptr::null_mut::<yaml_char_t>(),
+        prefix: ptr::null_mut::<yaml_char_t>(),
+    };
+    __assert!(!event.is_null());
+    __assert!(
+        !tag_directives_start.is_null() && !tag_directives_end.is_null()
+            || tag_directives_start == tag_directives_end
+    );
+    if !version_directive.is_null() {
+        version_directive_copy = yaml_malloc(size_of::<yaml_version_directive_t>() as libc::c_ulong)
+            as *mut yaml_version_directive_t;
+        (*version_directive_copy).major = (*version_directive).major;
+        (*version_directive_copy).minor = (*version_directive).minor;
+    }
+    if tag_directives_start != tag_directives_end {
+        let mut tag_directive: *mut yaml_tag_directive_t;
+        STACK_INIT!(tag_directives_copy, yaml_tag_directive_t);
+        tag_directive = tag_directives_start;
+        loop {
+            if !(tag_directive != tag_directives_end) {
+                current_block = 16203760046146113240;
+                break;
+            }
+            __assert!(!((*tag_directive).handle).is_null());
+            __assert!(!((*tag_directive).prefix).is_null());
+            if yaml_check_utf8(
+                (*tag_directive).handle,
+                strlen((*tag_directive).handle as *mut libc::c_char),
+            )
+            .fail
+            {
+                current_block = 14964981520188694172;
+                break;
+            }
+            if yaml_check_utf8(
+                (*tag_directive).prefix,
+                strlen((*tag_directive).prefix as *mut libc::c_char),
+            )
+            .fail
+            {
+                current_block = 14964981520188694172;
+                break;
+            }
+            value.handle = yaml_strdup((*tag_directive).handle);
+            value.prefix = yaml_strdup((*tag_directive).prefix);
+            if value.handle.is_null() || value.prefix.is_null() {
+                current_block = 14964981520188694172;
+                break;
+            }
+            PUSH!(tag_directives_copy, value);
+            value.handle = ptr::null_mut::<yaml_char_t>();
+            value.prefix = ptr::null_mut::<yaml_char_t>();
+            tag_directive = tag_directive.wrapping_offset(1);
+        }
+    } else {
+        current_block = 16203760046146113240;
+    }
+    if current_block != 14964981520188694172 {
+        memset(
+            event as *mut libc::c_void,
+            0,
+            size_of::<yaml_event_t>() as libc::c_ulong,
+        );
+        (*event).type_ = YAML_DOCUMENT_START_EVENT;
+        (*event).start_mark = mark;
+        (*event).end_mark = mark;
+        let fresh164 = addr_of_mut!((*event).data.document_start.version_directive);
+        *fresh164 = version_directive_copy;
+        let fresh165 = addr_of_mut!((*event).data.document_start.tag_directives.start);
+        *fresh165 = tag_directives_copy.start;
+        let fresh166 = addr_of_mut!((*event).data.document_start.tag_directives.end);
+        *fresh166 = tag_directives_copy.top;
+        (*event).data.document_start.implicit = implicit;
+        return OK;
+    }
+    yaml_free(version_directive_copy as *mut libc::c_void);
+    while !STACK_EMPTY!(tag_directives_copy) {
+        let value = POP!(tag_directives_copy);
+        yaml_free(value.handle as *mut libc::c_void);
+        yaml_free(value.prefix as *mut libc::c_void);
+    }
+    STACK_DEL!(tag_directives_copy);
+    yaml_free(value.handle as *mut libc::c_void);
+    yaml_free(value.prefix as *mut libc::c_void);
+    FAIL
+}
+
+/// Create the DOCUMENT-END event.
+///
+/// The `implicit` argument is considered as a stylistic parameter and may be
+/// ignored by the emitter.
+pub unsafe fn yaml_document_end_event_initialize(
+    event: *mut yaml_event_t,
+    implicit: bool,
+) -> Success {
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    __assert!(!event.is_null());
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_DOCUMENT_END_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    (*event).data.document_end.implicit = implicit;
+    OK
+}
+
+/// Create an ALIAS event.
+pub unsafe fn yaml_alias_event_initialize(
+    event: *mut yaml_event_t,
+    anchor: *const yaml_char_t,
+) -> Success {
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    __assert!(!event.is_null());
+    __assert!(!anchor.is_null());
+    if yaml_check_utf8(anchor, strlen(anchor as *mut libc::c_char)).fail {
+        return FAIL;
+    }
+    let anchor_copy: *mut yaml_char_t = yaml_strdup(anchor);
+    if anchor_copy.is_null() {
+        return FAIL;
+    }
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_ALIAS_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    let fresh167 = addr_of_mut!((*event).data.alias.anchor);
+    *fresh167 = anchor_copy;
+    OK
+}
+
+/// Create a SCALAR event.
+///
+/// The `style` argument may be ignored by the emitter.
+///
+/// Either the `tag` attribute or one of the `plain_implicit` and
+/// `quoted_implicit` flags must be set.
+///
+pub unsafe fn yaml_scalar_event_initialize(
+    event: *mut yaml_event_t,
+    anchor: *const yaml_char_t,
+    tag: *const yaml_char_t,
+    value: *const yaml_char_t,
+    mut length: libc::c_int,
+    plain_implicit: bool,
+    quoted_implicit: bool,
+    style: yaml_scalar_style_t,
+) -> Success {
+    let mut current_block: u64;
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    let mut anchor_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut tag_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut value_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    __assert!(!event.is_null());
+    __assert!(!value.is_null());
+    if !anchor.is_null() {
+        if yaml_check_utf8(anchor, strlen(anchor as *mut libc::c_char)).fail {
+            current_block = 16285396129609901221;
+        } else {
+            anchor_copy = yaml_strdup(anchor);
+            if anchor_copy.is_null() {
+                current_block = 16285396129609901221;
+            } else {
+                current_block = 8515828400728868193;
+            }
+        }
+    } else {
+        current_block = 8515828400728868193;
+    }
+    if current_block == 8515828400728868193 {
+        if !tag.is_null() {
+            if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char)).fail {
+                current_block = 16285396129609901221;
+            } else {
+                tag_copy = yaml_strdup(tag);
+                if tag_copy.is_null() {
+                    current_block = 16285396129609901221;
+                } else {
+                    current_block = 12800627514080957624;
+                }
+            }
+        } else {
+            current_block = 12800627514080957624;
+        }
+        if current_block != 16285396129609901221 {
+            if length < 0 {
+                length = strlen(value as *mut libc::c_char) as libc::c_int;
+            }
+            if yaml_check_utf8(value, length as size_t).ok {
+                value_copy = yaml_malloc((length + 1) as size_t) as *mut yaml_char_t;
+                memcpy(
+                    value_copy as *mut libc::c_void,
+                    value as *const libc::c_void,
+                    length as libc::c_ulong,
+                );
+                *value_copy.wrapping_offset(length as isize) = b'\0';
+                memset(
+                    event as *mut libc::c_void,
+                    0,
+                    size_of::<yaml_event_t>() as libc::c_ulong,
+                );
+                (*event).type_ = YAML_SCALAR_EVENT;
+                (*event).start_mark = mark;
+                (*event).end_mark = mark;
+                let fresh168 = addr_of_mut!((*event).data.scalar.anchor);
+                *fresh168 = anchor_copy;
+                let fresh169 = addr_of_mut!((*event).data.scalar.tag);
+                *fresh169 = tag_copy;
+                let fresh170 = addr_of_mut!((*event).data.scalar.value);
+                *fresh170 = value_copy;
+                (*event).data.scalar.length = length as size_t;
+                (*event).data.scalar.plain_implicit = plain_implicit;
+                (*event).data.scalar.quoted_implicit = quoted_implicit;
+                (*event).data.scalar.style = style;
+                return OK;
+            }
+        }
+    }
+    yaml_free(anchor_copy as *mut libc::c_void);
+    yaml_free(tag_copy as *mut libc::c_void);
+    yaml_free(value_copy as *mut libc::c_void);
+    FAIL
+}
+
+/// Create a SEQUENCE-START event.
+///
+/// The `style` argument may be ignored by the emitter.
+///
+/// Either the `tag` attribute or the `implicit` flag must be set.
+pub unsafe fn yaml_sequence_start_event_initialize(
+    event: *mut yaml_event_t,
+    anchor: *const yaml_char_t,
+    tag: *const yaml_char_t,
+    implicit: bool,
+    style: yaml_sequence_style_t,
+) -> Success {
+    let mut current_block: u64;
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    let mut anchor_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut tag_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    __assert!(!event.is_null());
+    if !anchor.is_null() {
+        if yaml_check_utf8(anchor, strlen(anchor as *mut libc::c_char)).fail {
+            current_block = 8817775685815971442;
+        } else {
+            anchor_copy = yaml_strdup(anchor);
+            if anchor_copy.is_null() {
+                current_block = 8817775685815971442;
+            } else {
+                current_block = 11006700562992250127;
+            }
+        }
+    } else {
+        current_block = 11006700562992250127;
+    }
+    match current_block {
+        11006700562992250127 => {
+            if !tag.is_null() {
+                if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char)).fail {
+                    current_block = 8817775685815971442;
+                } else {
+                    tag_copy = yaml_strdup(tag);
+                    if tag_copy.is_null() {
+                        current_block = 8817775685815971442;
+                    } else {
+                        current_block = 7651349459974463963;
+                    }
+                }
+            } else {
+                current_block = 7651349459974463963;
+            }
+            if current_block != 8817775685815971442 {
+                memset(
+                    event as *mut libc::c_void,
+                    0,
+                    size_of::<yaml_event_t>() as libc::c_ulong,
+                );
+                (*event).type_ = YAML_SEQUENCE_START_EVENT;
+                (*event).start_mark = mark;
+                (*event).end_mark = mark;
+                let fresh171 = addr_of_mut!((*event).data.sequence_start.anchor);
+                *fresh171 = anchor_copy;
+                let fresh172 = addr_of_mut!((*event).data.sequence_start.tag);
+                *fresh172 = tag_copy;
+                (*event).data.sequence_start.implicit = implicit;
+                (*event).data.sequence_start.style = style;
+                return OK;
+            }
+        }
+        _ => {}
+    }
+    yaml_free(anchor_copy as *mut libc::c_void);
+    yaml_free(tag_copy as *mut libc::c_void);
+    FAIL
+}
+
+/// Create a SEQUENCE-END event.
+pub unsafe fn yaml_sequence_end_event_initialize(event: *mut yaml_event_t) -> Success {
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    __assert!(!event.is_null());
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_SEQUENCE_END_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    OK
+}
+
+/// Create a MAPPING-START event.
+///
+/// The `style` argument may be ignored by the emitter.
+///
+/// Either the `tag` attribute or the `implicit` flag must be set.
+pub unsafe fn yaml_mapping_start_event_initialize(
+    event: *mut yaml_event_t,
+    anchor: *const yaml_char_t,
+    tag: *const yaml_char_t,
+    implicit: bool,
+    style: yaml_mapping_style_t,
+) -> Success {
+    let mut current_block: u64;
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    let mut anchor_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut tag_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    __assert!(!event.is_null());
+    if !anchor.is_null() {
+        if yaml_check_utf8(anchor, strlen(anchor as *mut libc::c_char)).fail {
+            current_block = 14748279734549812740;
+        } else {
+            anchor_copy = yaml_strdup(anchor);
+            if anchor_copy.is_null() {
+                current_block = 14748279734549812740;
+            } else {
+                current_block = 11006700562992250127;
+            }
+        }
+    } else {
+        current_block = 11006700562992250127;
+    }
+    if current_block == 11006700562992250127 {
+        if !tag.is_null() {
+            if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char)).fail {
+                current_block = 14748279734549812740;
+            } else {
+                tag_copy = yaml_strdup(tag);
+                if tag_copy.is_null() {
+                    current_block = 14748279734549812740;
+                } else {
+                    current_block = 7651349459974463963;
+                }
+            }
+        } else {
+            current_block = 7651349459974463963;
+        }
+        if current_block != 14748279734549812740 {
+            memset(
+                event as *mut libc::c_void,
+                0,
+                size_of::<yaml_event_t>() as libc::c_ulong,
+            );
+            (*event).type_ = YAML_MAPPING_START_EVENT;
+            (*event).start_mark = mark;
+            (*event).end_mark = mark;
+            let fresh173 = addr_of_mut!((*event).data.mapping_start.anchor);
+            *fresh173 = anchor_copy;
+            let fresh174 = addr_of_mut!((*event).data.mapping_start.tag);
+            *fresh174 = tag_copy;
+            (*event).data.mapping_start.implicit = implicit;
+            (*event).data.mapping_start.style = style;
+            return OK;
+        }
+    }
+    yaml_free(anchor_copy as *mut libc::c_void);
+    yaml_free(tag_copy as *mut libc::c_void);
+    FAIL
+}
+
+/// Create a MAPPING-END event.
+pub unsafe fn yaml_mapping_end_event_initialize(event: *mut yaml_event_t) -> Success {
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    __assert!(!event.is_null());
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_MAPPING_END_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    OK
+}
+
+/// Free any memory allocated for an event object.
+pub unsafe fn yaml_event_delete(event: *mut yaml_event_t) {
+    let mut tag_directive: *mut yaml_tag_directive_t;
+    __assert!(!event.is_null());
+    match (*event).type_ {
+        YAML_DOCUMENT_START_EVENT => {
+            yaml_free((*event).data.document_start.version_directive as *mut libc::c_void);
+            tag_directive = (*event).data.document_start.tag_directives.start;
+            while tag_directive != (*event).data.document_start.tag_directives.end {
+                yaml_free((*tag_directive).handle as *mut libc::c_void);
+                yaml_free((*tag_directive).prefix as *mut libc::c_void);
+                tag_directive = tag_directive.wrapping_offset(1);
+            }
+            yaml_free((*event).data.document_start.tag_directives.start as *mut libc::c_void);
+        }
+        YAML_ALIAS_EVENT => {
+            yaml_free((*event).data.alias.anchor as *mut libc::c_void);
+        }
+        YAML_SCALAR_EVENT => {
+            yaml_free((*event).data.scalar.anchor as *mut libc::c_void);
+            yaml_free((*event).data.scalar.tag as *mut libc::c_void);
+            yaml_free((*event).data.scalar.value as *mut libc::c_void);
+        }
+        YAML_SEQUENCE_START_EVENT => {
+            yaml_free((*event).data.sequence_start.anchor as *mut libc::c_void);
+            yaml_free((*event).data.sequence_start.tag as *mut libc::c_void);
+        }
+        YAML_MAPPING_START_EVENT => {
+            yaml_free((*event).data.mapping_start.anchor as *mut libc::c_void);
+            yaml_free((*event).data.mapping_start.tag as *mut libc::c_void);
+        }
+        _ => {}
+    }
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+}
+
+/// Create a YAML document.
+pub unsafe fn yaml_document_initialize(
+    document: *mut yaml_document_t,
+    version_directive: *mut yaml_version_directive_t,
+    tag_directives_start: *mut yaml_tag_directive_t,
+    tag_directives_end: *mut yaml_tag_directive_t,
+    start_implicit: bool,
+    end_implicit: bool,
+) -> Success {
+    let current_block: u64;
+    struct Nodes {
+        start: *mut yaml_node_t,
+        end: *mut yaml_node_t,
+        top: *mut yaml_node_t,
+    }
+    let mut nodes = Nodes {
+        start: ptr::null_mut::<yaml_node_t>(),
+        end: ptr::null_mut::<yaml_node_t>(),
+        top: ptr::null_mut::<yaml_node_t>(),
+    };
+    let mut version_directive_copy: *mut yaml_version_directive_t =
+        ptr::null_mut::<yaml_version_directive_t>();
+    struct TagDirectivesCopy {
+        start: *mut yaml_tag_directive_t,
+        end: *mut yaml_tag_directive_t,
+        top: *mut yaml_tag_directive_t,
+    }
+    let mut tag_directives_copy = TagDirectivesCopy {
+        start: ptr::null_mut::<yaml_tag_directive_t>(),
+        end: ptr::null_mut::<yaml_tag_directive_t>(),
+        top: ptr::null_mut::<yaml_tag_directive_t>(),
+    };
+    let mut value = yaml_tag_directive_t {
+        handle: ptr::null_mut::<yaml_char_t>(),
+        prefix: ptr::null_mut::<yaml_char_t>(),
+    };
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    __assert!(!document.is_null());
+    __assert!(
+        !tag_directives_start.is_null() && !tag_directives_end.is_null()
+            || tag_directives_start == tag_directives_end
+    );
+    STACK_INIT!(nodes, yaml_node_t);
+    if !version_directive.is_null() {
+        version_directive_copy = yaml_malloc(size_of::<yaml_version_directive_t>() as libc::c_ulong)
+            as *mut yaml_version_directive_t;
+        (*version_directive_copy).major = (*version_directive).major;
+        (*version_directive_copy).minor = (*version_directive).minor;
+    }
+    if tag_directives_start != tag_directives_end {
+        let mut tag_directive: *mut yaml_tag_directive_t;
+        STACK_INIT!(tag_directives_copy, yaml_tag_directive_t);
+        tag_directive = tag_directives_start;
+        loop {
+            if !(tag_directive != tag_directives_end) {
+                current_block = 14818589718467733107;
+                break;
+            }
+            __assert!(!((*tag_directive).handle).is_null());
+            __assert!(!((*tag_directive).prefix).is_null());
+            if yaml_check_utf8(
+                (*tag_directive).handle,
+                strlen((*tag_directive).handle as *mut libc::c_char),
+            )
+            .fail
+            {
+                current_block = 8142820162064489797;
+                break;
+            }
+            if yaml_check_utf8(
+                (*tag_directive).prefix,
+                strlen((*tag_directive).prefix as *mut libc::c_char),
+            )
+            .fail
+            {
+                current_block = 8142820162064489797;
+                break;
+            }
+            value.handle = yaml_strdup((*tag_directive).handle);
+            value.prefix = yaml_strdup((*tag_directive).prefix);
+            if value.handle.is_null() || value.prefix.is_null() {
+                current_block = 8142820162064489797;
+                break;
+            }
+            PUSH!(tag_directives_copy, value);
+            value.handle = ptr::null_mut::<yaml_char_t>();
+            value.prefix = ptr::null_mut::<yaml_char_t>();
+            tag_directive = tag_directive.wrapping_offset(1);
+        }
+    } else {
+        current_block = 14818589718467733107;
+    }
+    if current_block != 8142820162064489797 {
+        memset(
+            document as *mut libc::c_void,
+            0,
+            size_of::<yaml_document_t>() as libc::c_ulong,
+        );
+        let fresh176 = addr_of_mut!((*document).nodes.start);
+        *fresh176 = nodes.start;
+        let fresh177 = addr_of_mut!((*document).nodes.end);
+        *fresh177 = nodes.end;
+        let fresh178 = addr_of_mut!((*document).nodes.top);
+        *fresh178 = nodes.start;
+        let fresh179 = addr_of_mut!((*document).version_directive);
+        *fresh179 = version_directive_copy;
+        let fresh180 = addr_of_mut!((*document).tag_directives.start);
+        *fresh180 = tag_directives_copy.start;
+        let fresh181 = addr_of_mut!((*document).tag_directives.end);
+        *fresh181 = tag_directives_copy.top;
+        (*document).start_implicit = start_implicit;
+        (*document).end_implicit = end_implicit;
+        (*document).start_mark = mark;
+        (*document).end_mark = mark;
+        return OK;
+    }
+    STACK_DEL!(nodes);
+    yaml_free(version_directive_copy as *mut libc::c_void);
+    while !STACK_EMPTY!(tag_directives_copy) {
+        let value = POP!(tag_directives_copy);
+        yaml_free(value.handle as *mut libc::c_void);
+        yaml_free(value.prefix as *mut libc::c_void);
+    }
+    STACK_DEL!(tag_directives_copy);
+    yaml_free(value.handle as *mut libc::c_void);
+    yaml_free(value.prefix as *mut libc::c_void);
+    FAIL
+}
+
+/// Delete a YAML document and all its nodes.
+pub unsafe fn yaml_document_delete(document: *mut yaml_document_t) {
+    let mut tag_directive: *mut yaml_tag_directive_t;
+    __assert!(!document.is_null());
+    while !STACK_EMPTY!((*document).nodes) {
+        let mut node = POP!((*document).nodes);
+        yaml_free(node.tag as *mut libc::c_void);
+        match node.type_ {
+            YAML_SCALAR_NODE => {
+                yaml_free(node.data.scalar.value as *mut libc::c_void);
+            }
+            YAML_SEQUENCE_NODE => {
+                STACK_DEL!(node.data.sequence.items);
+            }
+            YAML_MAPPING_NODE => {
+                STACK_DEL!(node.data.mapping.pairs);
+            }
+            _ => {
+                __assert!(false);
+            }
+        }
+    }
+    STACK_DEL!((*document).nodes);
+    yaml_free((*document).version_directive as *mut libc::c_void);
+    tag_directive = (*document).tag_directives.start;
+    while tag_directive != (*document).tag_directives.end {
+        yaml_free((*tag_directive).handle as *mut libc::c_void);
+        yaml_free((*tag_directive).prefix as *mut libc::c_void);
+        tag_directive = tag_directive.wrapping_offset(1);
+    }
+    yaml_free((*document).tag_directives.start as *mut libc::c_void);
+    memset(
+        document as *mut libc::c_void,
+        0,
+        size_of::<yaml_document_t>() as libc::c_ulong,
+    );
+}
+
+/// 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.
+///
+/// Returns the node objct or NULL if `node_id` is out of range.
+pub unsafe fn yaml_document_get_node(
+    document: *mut yaml_document_t,
+    index: libc::c_int,
+) -> *mut yaml_node_t {
+    __assert!(!document.is_null());
+    if index > 0 && (*document).nodes.start.wrapping_offset(index as isize) <= (*document).nodes.top
+    {
+        return (*document)
+            .nodes
+            .start
+            .wrapping_offset(index as isize)
+            .wrapping_offset(-1_isize);
+    }
+    ptr::null_mut::<yaml_node_t>()
+}
+
+/// 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.
+///
+/// Returns the node object or NULL if the document is empty.
+pub unsafe fn yaml_document_get_root_node(document: *mut yaml_document_t) -> *mut yaml_node_t {
+    __assert!(!document.is_null());
+    if (*document).nodes.top != (*document).nodes.start {
+        return (*document).nodes.start;
+    }
+    ptr::null_mut::<yaml_node_t>()
+}
+
+/// Create a SCALAR node and attach it to the document.
+///
+/// The `style` argument may be ignored by the emitter.
+///
+/// Returns the node id or 0 on error.
+#[must_use]
+pub unsafe fn yaml_document_add_scalar(
+    document: *mut yaml_document_t,
+    mut tag: *const yaml_char_t,
+    value: *const yaml_char_t,
+    mut length: libc::c_int,
+    style: yaml_scalar_style_t,
+) -> libc::c_int {
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    let mut tag_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut value_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut node = MaybeUninit::<yaml_node_t>::uninit();
+    let node = node.as_mut_ptr();
+    __assert!(!document.is_null());
+    __assert!(!value.is_null());
+    if tag.is_null() {
+        tag = b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char as *mut yaml_char_t;
+    }
+    if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char)).ok {
+        tag_copy = yaml_strdup(tag);
+        if !tag_copy.is_null() {
+            if length < 0 {
+                length = strlen(value as *mut libc::c_char) as libc::c_int;
+            }
+            if yaml_check_utf8(value, length as size_t).ok {
+                value_copy = yaml_malloc((length + 1) as size_t) as *mut yaml_char_t;
+                memcpy(
+                    value_copy as *mut libc::c_void,
+                    value as *const libc::c_void,
+                    length as libc::c_ulong,
+                );
+                *value_copy.wrapping_offset(length as isize) = b'\0';
+                memset(
+                    node as *mut libc::c_void,
+                    0,
+                    size_of::<yaml_node_t>() as libc::c_ulong,
+                );
+                (*node).type_ = YAML_SCALAR_NODE;
+                (*node).tag = tag_copy;
+                (*node).start_mark = mark;
+                (*node).end_mark = mark;
+                (*node).data.scalar.value = value_copy;
+                (*node).data.scalar.length = length as size_t;
+                (*node).data.scalar.style = style;
+                PUSH!((*document).nodes, *node);
+                return (*document).nodes.top.c_offset_from((*document).nodes.start) as libc::c_int;
+            }
+        }
+    }
+    yaml_free(tag_copy as *mut libc::c_void);
+    yaml_free(value_copy as *mut libc::c_void);
+    0
+}
+
+/// Create a SEQUENCE node and attach it to the document.
+///
+/// The `style` argument may be ignored by the emitter.
+///
+/// Returns the node id or 0 on error.
+#[must_use]
+pub unsafe fn yaml_document_add_sequence(
+    document: *mut yaml_document_t,
+    mut tag: *const yaml_char_t,
+    style: yaml_sequence_style_t,
+) -> libc::c_int {
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    let mut tag_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    struct Items {
+        start: *mut yaml_node_item_t,
+        end: *mut yaml_node_item_t,
+        top: *mut yaml_node_item_t,
+    }
+    let mut items = Items {
+        start: ptr::null_mut::<yaml_node_item_t>(),
+        end: ptr::null_mut::<yaml_node_item_t>(),
+        top: ptr::null_mut::<yaml_node_item_t>(),
+    };
+    let mut node = MaybeUninit::<yaml_node_t>::uninit();
+    let node = node.as_mut_ptr();
+    __assert!(!document.is_null());
+    if tag.is_null() {
+        tag = b"tag:yaml.org,2002:seq\0" as *const u8 as *const libc::c_char as *mut yaml_char_t;
+    }
+    if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char)).ok {
+        tag_copy = yaml_strdup(tag);
+        if !tag_copy.is_null() {
+            STACK_INIT!(items, yaml_node_item_t);
+            memset(
+                node as *mut libc::c_void,
+                0,
+                size_of::<yaml_node_t>() as libc::c_ulong,
+            );
+            (*node).type_ = YAML_SEQUENCE_NODE;
+            (*node).tag = tag_copy;
+            (*node).start_mark = mark;
+            (*node).end_mark = mark;
+            (*node).data.sequence.items.start = items.start;
+            (*node).data.sequence.items.end = items.end;
+            (*node).data.sequence.items.top = items.start;
+            (*node).data.sequence.style = style;
+            PUSH!((*document).nodes, *node);
+            return (*document).nodes.top.c_offset_from((*document).nodes.start) as libc::c_int;
+        }
+    }
+    STACK_DEL!(items);
+    yaml_free(tag_copy as *mut libc::c_void);
+    0
+}
+
+/// Create a MAPPING node and attach it to the document.
+///
+/// The `style` argument may be ignored by the emitter.
+///
+/// Returns the node id or 0 on error.
+#[must_use]
+pub unsafe fn yaml_document_add_mapping(
+    document: *mut yaml_document_t,
+    mut tag: *const yaml_char_t,
+    style: yaml_mapping_style_t,
+) -> libc::c_int {
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    let mut tag_copy: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    struct Pairs {
+        start: *mut yaml_node_pair_t,
+        end: *mut yaml_node_pair_t,
+        top: *mut yaml_node_pair_t,
+    }
+    let mut pairs = Pairs {
+        start: ptr::null_mut::<yaml_node_pair_t>(),
+        end: ptr::null_mut::<yaml_node_pair_t>(),
+        top: ptr::null_mut::<yaml_node_pair_t>(),
+    };
+    let mut node = MaybeUninit::<yaml_node_t>::uninit();
+    let node = node.as_mut_ptr();
+    __assert!(!document.is_null());
+    if tag.is_null() {
+        tag = b"tag:yaml.org,2002:map\0" as *const u8 as *const libc::c_char as *mut yaml_char_t;
+    }
+    if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char)).ok {
+        tag_copy = yaml_strdup(tag);
+        if !tag_copy.is_null() {
+            STACK_INIT!(pairs, yaml_node_pair_t);
+            memset(
+                node as *mut libc::c_void,
+                0,
+                size_of::<yaml_node_t>() as libc::c_ulong,
+            );
+            (*node).type_ = YAML_MAPPING_NODE;
+            (*node).tag = tag_copy;
+            (*node).start_mark = mark;
+            (*node).end_mark = mark;
+            (*node).data.mapping.pairs.start = pairs.start;
+            (*node).data.mapping.pairs.end = pairs.end;
+            (*node).data.mapping.pairs.top = pairs.start;
+            (*node).data.mapping.style = style;
+            PUSH!((*document).nodes, *node);
+            return (*document).nodes.top.c_offset_from((*document).nodes.start) as libc::c_int;
+        }
+    }
+    STACK_DEL!(pairs);
+    yaml_free(tag_copy as *mut libc::c_void);
+    0
+}
+
+/// Add an item to a SEQUENCE node.
+pub unsafe fn yaml_document_append_sequence_item(
+    document: *mut yaml_document_t,
+    sequence: libc::c_int,
+    item: libc::c_int,
+) -> Success {
+    __assert!(!document.is_null());
+    __assert!(
+        sequence > 0
+            && ((*document).nodes.start).wrapping_offset(sequence as isize)
+                <= (*document).nodes.top
+    );
+    __assert!(
+        (*((*document).nodes.start).wrapping_offset((sequence - 1) as isize)).type_
+            == YAML_SEQUENCE_NODE
+    );
+    __assert!(
+        item > 0
+            && ((*document).nodes.start).wrapping_offset(item as isize) <= (*document).nodes.top
+    );
+    PUSH!(
+        (*((*document).nodes.start).wrapping_offset((sequence - 1) as isize))
+            .data
+            .sequence
+            .items,
+        item
+    );
+    OK
+}
+
+/// Add a pair of a key and a value to a MAPPING node.
+pub unsafe fn yaml_document_append_mapping_pair(
+    document: *mut yaml_document_t,
+    mapping: libc::c_int,
+    key: libc::c_int,
+    value: libc::c_int,
+) -> Success {
+    __assert!(!document.is_null());
+    __assert!(
+        mapping > 0
+            && ((*document).nodes.start).wrapping_offset(mapping as isize) <= (*document).nodes.top
+    );
+    __assert!(
+        (*((*document).nodes.start).wrapping_offset((mapping - 1) as isize)).type_
+            == YAML_MAPPING_NODE
+    );
+    __assert!(
+        key > 0 && ((*document).nodes.start).wrapping_offset(key as isize) <= (*document).nodes.top
+    );
+    __assert!(
+        value > 0
+            && ((*document).nodes.start).wrapping_offset(value as isize) <= (*document).nodes.top
+    );
+    let pair = yaml_node_pair_t { key, value };
+    PUSH!(
+        (*((*document).nodes.start).wrapping_offset((mapping - 1) as isize))
+            .data
+            .mapping
+            .pairs,
+        pair
+    );
+    OK
+}
diff --git a/src/bin/cstr/mod.rs b/src/bin/cstr/mod.rs
new file mode 100644
index 0000000..7054c46
--- /dev/null
+++ b/src/bin/cstr/mod.rs
@@ -0,0 +1,47 @@
+use std::fmt::{self, Display, Write as _};
+use std::slice;
+use std::str;
+
+#[allow(non_camel_case_types)]
+type c_char = i8;
+
+pub struct CStr {
+    ptr: *const u8,
+}
+
+impl CStr {
+    pub unsafe fn from_ptr(ptr: *const c_char) -> Self {
+        CStr { ptr: ptr.cast() }
+    }
+}
+
+impl Display for CStr {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        let len = unsafe { strlen(self.ptr) };
+        let mut bytes = unsafe { slice::from_raw_parts(self.ptr, len) };
+        loop {
+            match str::from_utf8(bytes) {
+                Ok(valid) => return formatter.write_str(valid),
+                Err(utf8_error) => {
+                    let valid_up_to = utf8_error.valid_up_to();
+                    let valid = unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) };
+                    formatter.write_str(valid)?;
+                    formatter.write_char(char::REPLACEMENT_CHARACTER)?;
+                    if let Some(error_len) = utf8_error.error_len() {
+                        bytes = &bytes[valid_up_to + error_len..];
+                    } else {
+                        return Ok(());
+                    }
+                }
+            }
+        }
+    }
+}
+
+unsafe fn strlen(s: *const u8) -> usize {
+    let mut end = s;
+    while *end != 0 {
+        end = end.add(1);
+    }
+    end.offset_from(s) as usize
+}
diff --git a/src/bin/run-emitter-test-suite.rs b/src/bin/run-emitter-test-suite.rs
new file mode 100644
index 0000000..0c51b9c
--- /dev/null
+++ b/src/bin/run-emitter-test-suite.rs
@@ -0,0 +1,307 @@
+#![warn(clippy::pedantic)]
+#![allow(
+    clippy::cast_lossless,
+    clippy::cast_possible_truncation,
+    clippy::cast_possible_wrap,
+    clippy::cast_sign_loss,
+    clippy::items_after_statements,
+    clippy::let_underscore_untyped,
+    clippy::missing_errors_doc,
+    clippy::missing_safety_doc,
+    clippy::ptr_as_ptr,
+    clippy::single_match_else,
+    clippy::too_many_lines,
+    clippy::unreadable_literal
+)]
+
+mod cstr;
+
+use self::cstr::CStr;
+use std::env;
+use std::error::Error;
+use std::ffi::c_void;
+use std::fs::File;
+use std::io::{self, Read, Write};
+use std::mem::MaybeUninit;
+use std::process::{self, ExitCode};
+use std::ptr::{self, addr_of_mut};
+use std::slice;
+use unsafe_libyaml::{
+    yaml_alias_event_initialize, yaml_document_end_event_initialize,
+    yaml_document_start_event_initialize, yaml_emitter_delete, yaml_emitter_emit,
+    yaml_emitter_initialize, yaml_emitter_set_canonical, yaml_emitter_set_output,
+    yaml_emitter_set_unicode, yaml_emitter_t, yaml_event_t, yaml_mapping_end_event_initialize,
+    yaml_mapping_start_event_initialize, yaml_scalar_event_initialize, yaml_scalar_style_t,
+    yaml_sequence_end_event_initialize, yaml_sequence_start_event_initialize,
+    yaml_stream_end_event_initialize, yaml_stream_start_event_initialize, yaml_tag_directive_t,
+    yaml_version_directive_t, YAML_ANY_SCALAR_STYLE, YAML_BLOCK_MAPPING_STYLE,
+    YAML_BLOCK_SEQUENCE_STYLE, YAML_DOUBLE_QUOTED_SCALAR_STYLE, YAML_EMITTER_ERROR,
+    YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE, YAML_MEMORY_ERROR,
+    YAML_PLAIN_SCALAR_STYLE, YAML_SINGLE_QUOTED_SCALAR_STYLE, YAML_UTF8_ENCODING,
+    YAML_WRITER_ERROR,
+};
+
+pub(crate) unsafe fn unsafe_main(
+    stdin: &mut dyn Read,
+    mut stdout: &mut dyn Write,
+) -> Result<(), Box<dyn Error>> {
+    let mut emitter = MaybeUninit::<yaml_emitter_t>::uninit();
+    let emitter = emitter.as_mut_ptr();
+    if yaml_emitter_initialize(emitter).fail {
+        return Err("Could not initalize the emitter object".into());
+    }
+
+    unsafe fn write_to_stdio(data: *mut c_void, buffer: *mut u8, size: u64) -> i32 {
+        let stdout: *mut &mut dyn Write = data.cast();
+        let bytes = slice::from_raw_parts(buffer.cast(), size as usize);
+        match (*stdout).write(bytes) {
+            Ok(n) => n as i32,
+            Err(_) => 0,
+        }
+    }
+
+    yaml_emitter_set_output(emitter, write_to_stdio, addr_of_mut!(stdout).cast());
+    yaml_emitter_set_canonical(emitter, false);
+    yaml_emitter_set_unicode(emitter, false);
+
+    let mut buf = ReadBuf::new();
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    let result = loop {
+        let line = match buf.get_line(stdin) {
+            Some(line) => line,
+            None => break Ok(()),
+        };
+
+        let mut anchor = [0u8; 256];
+        let mut tag = [0u8; 256];
+        let result = if line.starts_with(b"+STR") {
+            yaml_stream_start_event_initialize(event, YAML_UTF8_ENCODING)
+        } else if line.starts_with(b"-STR") {
+            yaml_stream_end_event_initialize(event)
+        } else if line.starts_with(b"+DOC") {
+            let implicit = !line[4..].starts_with(b" ---");
+            yaml_document_start_event_initialize(
+                event,
+                ptr::null_mut::<yaml_version_directive_t>(),
+                ptr::null_mut::<yaml_tag_directive_t>(),
+                ptr::null_mut::<yaml_tag_directive_t>(),
+                implicit,
+            )
+        } else if line.starts_with(b"-DOC") {
+            let implicit = !line[4..].starts_with(b" ...");
+            yaml_document_end_event_initialize(event, implicit)
+        } else if line.starts_with(b"+MAP") {
+            yaml_mapping_start_event_initialize(
+                event,
+                get_anchor(b'&', line, anchor.as_mut_ptr()),
+                get_tag(line, tag.as_mut_ptr()),
+                false,
+                YAML_BLOCK_MAPPING_STYLE,
+            )
+        } else if line.starts_with(b"-MAP") {
+            yaml_mapping_end_event_initialize(event)
+        } else if line.starts_with(b"+SEQ") {
+            yaml_sequence_start_event_initialize(
+                event,
+                get_anchor(b'&', line, anchor.as_mut_ptr()),
+                get_tag(line, tag.as_mut_ptr()),
+                false,
+                YAML_BLOCK_SEQUENCE_STYLE,
+            )
+        } else if line.starts_with(b"-SEQ") {
+            yaml_sequence_end_event_initialize(event)
+        } else if line.starts_with(b"=VAL") {
+            let mut value = [0i8; 1024];
+            let mut style = YAML_ANY_SCALAR_STYLE;
+            get_value(line, value.as_mut_ptr(), &mut style);
+            let implicit = get_tag(line, tag.as_mut_ptr()).is_null();
+            yaml_scalar_event_initialize(
+                event,
+                get_anchor(b'&', line, anchor.as_mut_ptr()),
+                get_tag(line, tag.as_mut_ptr()),
+                value.as_mut_ptr() as *mut u8,
+                -1,
+                implicit,
+                implicit,
+                style,
+            )
+        } else if line.starts_with(b"=ALI") {
+            yaml_alias_event_initialize(event, get_anchor(b'*', line, anchor.as_mut_ptr()))
+        } else {
+            let line = line as *mut [u8] as *mut i8;
+            break Err(format!("Unknown event: '{}'", CStr::from_ptr(line)).into());
+        };
+
+        if result.fail {
+            break Err("Memory error: Not enough memory for creating an event".into());
+        }
+        if yaml_emitter_emit(emitter, event).fail {
+            break Err(match (*emitter).error {
+                YAML_MEMORY_ERROR => "Memory error: Not enough memory for emitting".into(),
+                YAML_WRITER_ERROR => {
+                    format!("Writer error: {}", CStr::from_ptr((*emitter).problem)).into()
+                }
+                YAML_EMITTER_ERROR => {
+                    format!("Emitter error: {}", CStr::from_ptr((*emitter).problem)).into()
+                }
+                // Couldn't happen.
+                _ => "Internal error".into(),
+            });
+        }
+    };
+
+    yaml_emitter_delete(emitter);
+    result
+}
+
+struct ReadBuf {
+    buf: [u8; 1024],
+    offset: usize,
+    filled: usize,
+}
+
+impl ReadBuf {
+    fn new() -> Self {
+        ReadBuf {
+            buf: [0; 1024],
+            offset: 0,
+            filled: 0,
+        }
+    }
+
+    fn get_line(&mut self, input: &mut dyn Read) -> Option<&mut [u8]> {
+        loop {
+            for i in self.offset..self.offset + self.filled {
+                if self.buf[i] == b'\n' {
+                    self.buf[i] = b'\0';
+                    let line = &mut self.buf[self.offset..=i];
+                    self.offset = i + 1;
+                    self.filled -= line.len();
+                    return Some(line);
+                }
+            }
+            let mut remainder = &mut self.buf[self.offset + self.filled..];
+            if remainder.is_empty() {
+                if self.offset == 0 {
+                    let _ = writeln!(
+                        io::stderr(),
+                        "Line too long: '{}'",
+                        String::from_utf8_lossy(&self.buf),
+                    );
+                    process::abort();
+                }
+                self.buf.copy_within(self.offset.., 0);
+                self.offset = 0;
+                remainder = &mut self.buf;
+            }
+            let n = input.read(remainder).ok()?;
+            self.filled += n;
+            if n == 0 {
+                return None;
+            }
+        }
+    }
+}
+
+unsafe fn get_anchor(sigil: u8, line: &[u8], anchor: *mut u8) -> *mut u8 {
+    let start = match line.iter().position(|ch| *ch == sigil) {
+        Some(offset) => offset + 1,
+        None => return ptr::null_mut::<u8>(),
+    };
+    let end = match line[start..].iter().position(|ch| *ch == b' ') {
+        Some(offset) => start + offset,
+        None => line.len(),
+    };
+    ptr::copy_nonoverlapping(line[start..end].as_ptr(), anchor, end - start);
+    *anchor.add(end - start) = b'\0';
+    anchor
+}
+
+unsafe fn get_tag(line: &[u8], tag: *mut u8) -> *mut u8 {
+    let start = match line.iter().position(|ch| *ch == b'<') {
+        Some(offset) => offset + 1,
+        None => return ptr::null_mut::<u8>(),
+    };
+    let end = match line[start..].iter().position(|ch| *ch == b'>') {
+        Some(offset) => start + offset,
+        None => return ptr::null_mut::<u8>(),
+    };
+    ptr::copy_nonoverlapping(line[start..end].as_ptr(), tag, end - start);
+    *tag.add(end - start) = b'\0';
+    tag
+}
+
+unsafe fn get_value(line: &[u8], value: *mut i8, style: *mut yaml_scalar_style_t) {
+    let line_len = line.len();
+    let line = line as *const [u8] as *mut i8;
+    let mut start = ptr::null_mut::<i8>();
+    let end = line.add(line_len);
+    let mut c = line.offset(4);
+    while c < end {
+        if *c as u8 == b' ' {
+            start = c.offset(1);
+            *style = match *start as u8 {
+                b':' => YAML_PLAIN_SCALAR_STYLE,
+                b'\'' => YAML_SINGLE_QUOTED_SCALAR_STYLE,
+                b'"' => YAML_DOUBLE_QUOTED_SCALAR_STYLE,
+                b'|' => YAML_LITERAL_SCALAR_STYLE,
+                b'>' => YAML_FOLDED_SCALAR_STYLE,
+                _ => {
+                    start = ptr::null_mut::<i8>();
+                    c = c.offset(1);
+                    continue;
+                }
+            };
+            start = start.offset(1);
+            break;
+        }
+        c = c.offset(1);
+    }
+    if start.is_null() {
+        process::abort();
+    }
+
+    let mut i = 0;
+    c = start;
+    while c < end {
+        *value.offset(i) = if *c as u8 == b'\\' {
+            c = c.offset(1);
+            match *c as u8 {
+                b'\\' => b'\\' as i8,
+                b'0' => b'\0' as i8,
+                b'b' => b'\x08' as i8,
+                b'n' => b'\n' as i8,
+                b'r' => b'\r' as i8,
+                b't' => b'\t' as i8,
+                _ => process::abort(),
+            }
+        } else {
+            *c
+        };
+        i += 1;
+        c = c.offset(1);
+    }
+    *value.offset(i) = b'\0' as i8;
+}
+
+fn main() -> ExitCode {
+    let args = env::args_os().skip(1);
+    if args.len() == 0 {
+        let _ = writeln!(
+            io::stderr(),
+            "Usage: run-emitter-test-suite <test.event>...",
+        );
+        return ExitCode::FAILURE;
+    }
+    for arg in args {
+        let mut stdin = File::open(arg).unwrap();
+        let mut stdout = io::stdout();
+        let result = unsafe { unsafe_main(&mut stdin, &mut stdout) };
+        if let Err(err) = result {
+            let _ = writeln!(io::stderr(), "{}", err);
+            return ExitCode::FAILURE;
+        }
+    }
+    ExitCode::SUCCESS
+}
diff --git a/src/bin/run-parser-test-suite.rs b/src/bin/run-parser-test-suite.rs
new file mode 100644
index 0000000..439ee03
--- /dev/null
+++ b/src/bin/run-parser-test-suite.rs
@@ -0,0 +1,222 @@
+#![warn(clippy::pedantic)]
+#![allow(
+    clippy::cast_lossless,
+    clippy::cast_possible_truncation,
+    clippy::cast_possible_wrap,
+    clippy::cast_sign_loss,
+    clippy::items_after_statements,
+    clippy::let_underscore_untyped,
+    clippy::missing_errors_doc,
+    clippy::missing_safety_doc,
+    clippy::too_many_lines
+)]
+
+mod cstr;
+
+use self::cstr::CStr;
+use std::env;
+use std::error::Error;
+use std::ffi::c_void;
+use std::fmt::Write as _;
+use std::fs::File;
+use std::io::{self, Read, Write};
+use std::mem::MaybeUninit;
+use std::process::{self, ExitCode};
+use std::ptr::addr_of_mut;
+use std::slice;
+use unsafe_libyaml::{
+    yaml_event_delete, yaml_event_t, yaml_event_type_t, yaml_parser_delete, yaml_parser_initialize,
+    yaml_parser_parse, yaml_parser_set_input, yaml_parser_t, YAML_ALIAS_EVENT,
+    YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_START_EVENT, YAML_DOUBLE_QUOTED_SCALAR_STYLE,
+    YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE, YAML_MAPPING_END_EVENT,
+    YAML_MAPPING_START_EVENT, YAML_NO_EVENT, YAML_PLAIN_SCALAR_STYLE, YAML_SCALAR_EVENT,
+    YAML_SEQUENCE_END_EVENT, YAML_SEQUENCE_START_EVENT, YAML_SINGLE_QUOTED_SCALAR_STYLE,
+    YAML_STREAM_END_EVENT, YAML_STREAM_START_EVENT,
+};
+
+pub(crate) unsafe fn unsafe_main(
+    mut stdin: &mut dyn Read,
+    stdout: &mut dyn Write,
+) -> Result<(), Box<dyn Error>> {
+    let mut parser = MaybeUninit::<yaml_parser_t>::uninit();
+    let parser = parser.as_mut_ptr();
+    if yaml_parser_initialize(parser).fail {
+        return Err("Could not initialize the parser object".into());
+    }
+
+    unsafe fn read_from_stdio(
+        data: *mut c_void,
+        buffer: *mut u8,
+        size: u64,
+        size_read: *mut u64,
+    ) -> i32 {
+        let stdin: *mut &mut dyn Read = data.cast();
+        let slice = slice::from_raw_parts_mut(buffer.cast(), size as usize);
+        match (*stdin).read(slice) {
+            Ok(n) => {
+                *size_read = n as u64;
+                1
+            }
+            Err(_) => 0,
+        }
+    }
+
+    yaml_parser_set_input(parser, read_from_stdio, addr_of_mut!(stdin).cast());
+
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    loop {
+        if yaml_parser_parse(parser, event).fail {
+            let mut error = format!("Parse error: {}", CStr::from_ptr((*parser).problem));
+            if (*parser).problem_mark.line != 0 || (*parser).problem_mark.column != 0 {
+                let _ = write!(
+                    error,
+                    "\nLine: {} Column: {}",
+                    ((*parser).problem_mark.line).wrapping_add(1_u64),
+                    ((*parser).problem_mark.column).wrapping_add(1_u64),
+                );
+            }
+            yaml_parser_delete(parser);
+            return Err(error.into());
+        }
+
+        let type_: yaml_event_type_t = (*event).type_;
+        if type_ == YAML_NO_EVENT {
+            let _ = writeln!(stdout, "???");
+        } else if type_ == YAML_STREAM_START_EVENT {
+            let _ = writeln!(stdout, "+STR");
+        } else if type_ == YAML_STREAM_END_EVENT {
+            let _ = writeln!(stdout, "-STR");
+        } else if type_ == YAML_DOCUMENT_START_EVENT {
+            let _ = write!(stdout, "+DOC");
+            if !(*event).data.document_start.implicit {
+                let _ = write!(stdout, " ---");
+            }
+            let _ = writeln!(stdout);
+        } else if type_ == YAML_DOCUMENT_END_EVENT {
+            let _ = write!(stdout, "-DOC");
+            if !(*event).data.document_end.implicit {
+                let _ = write!(stdout, " ...");
+            }
+            let _ = writeln!(stdout);
+        } else if type_ == YAML_MAPPING_START_EVENT {
+            let _ = write!(stdout, "+MAP");
+            if !(*event).data.mapping_start.anchor.is_null() {
+                let _ = write!(
+                    stdout,
+                    " &{}",
+                    CStr::from_ptr((*event).data.mapping_start.anchor as *const i8),
+                );
+            }
+            if !(*event).data.mapping_start.tag.is_null() {
+                let _ = write!(
+                    stdout,
+                    " <{}>",
+                    CStr::from_ptr((*event).data.mapping_start.tag as *const i8),
+                );
+            }
+            let _ = writeln!(stdout);
+        } else if type_ == YAML_MAPPING_END_EVENT {
+            let _ = writeln!(stdout, "-MAP");
+        } else if type_ == YAML_SEQUENCE_START_EVENT {
+            let _ = write!(stdout, "+SEQ");
+            if !(*event).data.sequence_start.anchor.is_null() {
+                let _ = write!(
+                    stdout,
+                    " &{}",
+                    CStr::from_ptr((*event).data.sequence_start.anchor as *const i8),
+                );
+            }
+            if !(*event).data.sequence_start.tag.is_null() {
+                let _ = write!(
+                    stdout,
+                    " <{}>",
+                    CStr::from_ptr((*event).data.sequence_start.tag as *const i8),
+                );
+            }
+            let _ = writeln!(stdout);
+        } else if type_ == YAML_SEQUENCE_END_EVENT {
+            let _ = writeln!(stdout, "-SEQ");
+        } else if type_ == YAML_SCALAR_EVENT {
+            let _ = write!(stdout, "=VAL");
+            if !(*event).data.scalar.anchor.is_null() {
+                let _ = write!(
+                    stdout,
+                    " &{}",
+                    CStr::from_ptr((*event).data.scalar.anchor as *const i8),
+                );
+            }
+            if !(*event).data.scalar.tag.is_null() {
+                let _ = write!(
+                    stdout,
+                    " <{}>",
+                    CStr::from_ptr((*event).data.scalar.tag as *const i8),
+                );
+            }
+            let _ = stdout.write_all(match (*event).data.scalar.style {
+                YAML_PLAIN_SCALAR_STYLE => b" :",
+                YAML_SINGLE_QUOTED_SCALAR_STYLE => b" '",
+                YAML_DOUBLE_QUOTED_SCALAR_STYLE => b" \"",
+                YAML_LITERAL_SCALAR_STYLE => b" |",
+                YAML_FOLDED_SCALAR_STYLE => b" >",
+                _ => process::abort(),
+            });
+            print_escaped(
+                stdout,
+                (*event).data.scalar.value,
+                (*event).data.scalar.length,
+            );
+            let _ = writeln!(stdout);
+        } else if type_ == YAML_ALIAS_EVENT {
+            let _ = writeln!(
+                stdout,
+                "=ALI *{}",
+                CStr::from_ptr((*event).data.alias.anchor as *const i8),
+            );
+        } else {
+            process::abort();
+        }
+
+        yaml_event_delete(event);
+        if type_ == YAML_STREAM_END_EVENT {
+            break;
+        }
+    }
+    yaml_parser_delete(parser);
+    Ok(())
+}
+
+unsafe fn print_escaped(stdout: &mut dyn Write, mut str: *mut u8, length: u64) {
+    let end = str.offset(length as isize);
+    while str < end {
+        let repr = match &*str {
+            b'\\' => b"\\\\",
+            b'\0' => b"\\0",
+            b'\x08' => b"\\b",
+            b'\n' => b"\\n",
+            b'\r' => b"\\r",
+            b'\t' => b"\\t",
+            c => slice::from_ref(c),
+        };
+        let _ = stdout.write_all(repr);
+        str = str.offset(1);
+    }
+}
+
+fn main() -> ExitCode {
+    let args = env::args_os().skip(1);
+    if args.len() == 0 {
+        let _ = writeln!(io::stderr(), "Usage: run-parser-test-suite <in.yaml>...");
+        return ExitCode::FAILURE;
+    }
+    for arg in args {
+        let mut stdin = File::open(arg).unwrap();
+        let mut stdout = io::stdout();
+        let result = unsafe { unsafe_main(&mut stdin, &mut stdout) };
+        if let Err(err) = result {
+            let _ = writeln!(io::stderr(), "{}", err);
+            return ExitCode::FAILURE;
+        }
+    }
+    ExitCode::SUCCESS
+}
diff --git a/src/dumper.rs b/src/dumper.rs
new file mode 100644
index 0000000..47ebf3e
--- /dev/null
+++ b/src/dumper.rs
@@ -0,0 +1,449 @@
+use crate::api::{yaml_free, yaml_malloc};
+use crate::externs::{memset, strcmp};
+use crate::fmt::WriteToPtr;
+use crate::success::{Success, FAIL, OK};
+use crate::yaml::{
+    yaml_anchors_t, yaml_char_t, yaml_document_t, yaml_emitter_t, yaml_event_t, yaml_mark_t,
+    yaml_node_item_t, yaml_node_pair_t, yaml_node_t, YAML_ALIAS_EVENT, YAML_ANY_ENCODING,
+    YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_START_EVENT, YAML_MAPPING_END_EVENT, YAML_MAPPING_NODE,
+    YAML_MAPPING_START_EVENT, YAML_SCALAR_EVENT, YAML_SCALAR_NODE, YAML_SEQUENCE_END_EVENT,
+    YAML_SEQUENCE_NODE, YAML_SEQUENCE_START_EVENT, YAML_STREAM_END_EVENT, YAML_STREAM_START_EVENT,
+};
+use crate::{libc, yaml_document_delete, yaml_emitter_emit, PointerExt};
+use core::mem::{size_of, MaybeUninit};
+use core::ptr::{self, addr_of_mut};
+
+/// Start a YAML stream.
+///
+/// This function should be used before yaml_emitter_dump() is called.
+pub unsafe fn yaml_emitter_open(emitter: *mut yaml_emitter_t) -> Success {
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    __assert!(!emitter.is_null());
+    __assert!(!(*emitter).opened);
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_STREAM_START_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    (*event).data.stream_start.encoding = YAML_ANY_ENCODING;
+    if yaml_emitter_emit(emitter, event).fail {
+        return FAIL;
+    }
+    (*emitter).opened = true;
+    OK
+}
+
+/// Finish a YAML stream.
+///
+/// This function should be used after yaml_emitter_dump() is called.
+pub unsafe fn yaml_emitter_close(emitter: *mut yaml_emitter_t) -> Success {
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    __assert!(!emitter.is_null());
+    __assert!((*emitter).opened);
+    if (*emitter).closed {
+        return OK;
+    }
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_STREAM_END_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    if yaml_emitter_emit(emitter, event).fail {
+        return FAIL;
+    }
+    (*emitter).closed = true;
+    OK
+}
+
+/// 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 destroys its content after it is
+/// emitted. The document object is destroyed even if the function fails.
+pub unsafe fn yaml_emitter_dump(
+    emitter: *mut yaml_emitter_t,
+    document: *mut yaml_document_t,
+) -> Success {
+    let current_block: u64;
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    __assert!(!emitter.is_null());
+    __assert!(!document.is_null());
+    let fresh0 = addr_of_mut!((*emitter).document);
+    *fresh0 = document;
+    if !(*emitter).opened {
+        if yaml_emitter_open(emitter).fail {
+            current_block = 5018439318894558507;
+        } else {
+            current_block = 15619007995458559411;
+        }
+    } else {
+        current_block = 15619007995458559411;
+    }
+    match current_block {
+        15619007995458559411 => {
+            if STACK_EMPTY!((*document).nodes) {
+                if yaml_emitter_close(emitter).ok {
+                    yaml_emitter_delete_document_and_anchors(emitter);
+                    return OK;
+                }
+            } else {
+                __assert!((*emitter).opened);
+                let fresh1 = addr_of_mut!((*emitter).anchors);
+                *fresh1 = yaml_malloc(
+                    (size_of::<yaml_anchors_t>() as libc::c_ulong)
+                        .wrapping_mul((*document).nodes.top.c_offset_from((*document).nodes.start)
+                            as libc::c_long as libc::c_ulong),
+                ) as *mut yaml_anchors_t;
+                memset(
+                    (*emitter).anchors as *mut libc::c_void,
+                    0,
+                    (size_of::<yaml_anchors_t>() as libc::c_ulong)
+                        .wrapping_mul((*document).nodes.top.c_offset_from((*document).nodes.start)
+                            as libc::c_long as libc::c_ulong),
+                );
+                memset(
+                    event as *mut libc::c_void,
+                    0,
+                    size_of::<yaml_event_t>() as libc::c_ulong,
+                );
+                (*event).type_ = YAML_DOCUMENT_START_EVENT;
+                (*event).start_mark = mark;
+                (*event).end_mark = mark;
+                (*event).data.document_start.version_directive = (*document).version_directive;
+                (*event).data.document_start.tag_directives.start =
+                    (*document).tag_directives.start;
+                (*event).data.document_start.tag_directives.end = (*document).tag_directives.end;
+                (*event).data.document_start.implicit = (*document).start_implicit;
+                if yaml_emitter_emit(emitter, event).ok {
+                    yaml_emitter_anchor_node(emitter, 1);
+                    if yaml_emitter_dump_node(emitter, 1).ok {
+                        memset(
+                            event as *mut libc::c_void,
+                            0,
+                            size_of::<yaml_event_t>() as libc::c_ulong,
+                        );
+                        (*event).type_ = YAML_DOCUMENT_END_EVENT;
+                        (*event).start_mark = mark;
+                        (*event).end_mark = mark;
+                        (*event).data.document_end.implicit = (*document).end_implicit;
+                        if yaml_emitter_emit(emitter, event).ok {
+                            yaml_emitter_delete_document_and_anchors(emitter);
+                            return OK;
+                        }
+                    }
+                }
+            }
+        }
+        _ => {}
+    }
+    yaml_emitter_delete_document_and_anchors(emitter);
+    FAIL
+}
+
+unsafe fn yaml_emitter_delete_document_and_anchors(emitter: *mut yaml_emitter_t) {
+    let mut index: libc::c_int;
+    if (*emitter).anchors.is_null() {
+        yaml_document_delete((*emitter).document);
+        let fresh2 = addr_of_mut!((*emitter).document);
+        *fresh2 = ptr::null_mut::<yaml_document_t>();
+        return;
+    }
+    index = 0;
+    while (*(*emitter).document)
+        .nodes
+        .start
+        .wrapping_offset(index as isize)
+        < (*(*emitter).document).nodes.top
+    {
+        let mut node: yaml_node_t = *(*(*emitter).document)
+            .nodes
+            .start
+            .wrapping_offset(index as isize);
+        if !(*(*emitter).anchors.wrapping_offset(index as isize)).serialized {
+            yaml_free(node.tag as *mut libc::c_void);
+            if node.type_ == YAML_SCALAR_NODE {
+                yaml_free(node.data.scalar.value as *mut libc::c_void);
+            }
+        }
+        if node.type_ == YAML_SEQUENCE_NODE {
+            STACK_DEL!(node.data.sequence.items);
+        }
+        if node.type_ == YAML_MAPPING_NODE {
+            STACK_DEL!(node.data.mapping.pairs);
+        }
+        index += 1;
+    }
+    STACK_DEL!((*(*emitter).document).nodes);
+    yaml_free((*emitter).anchors as *mut libc::c_void);
+    let fresh6 = addr_of_mut!((*emitter).anchors);
+    *fresh6 = ptr::null_mut::<yaml_anchors_t>();
+    (*emitter).last_anchor_id = 0;
+    let fresh7 = addr_of_mut!((*emitter).document);
+    *fresh7 = ptr::null_mut::<yaml_document_t>();
+}
+
+unsafe fn yaml_emitter_anchor_node_sub(emitter: *mut yaml_emitter_t, index: libc::c_int) {
+    (*((*emitter).anchors).offset((index - 1) as isize)).references += 1;
+    if (*(*emitter).anchors.offset((index - 1) as isize)).references == 2 {
+        (*emitter).last_anchor_id += 1;
+        (*(*emitter).anchors.offset((index - 1) as isize)).anchor = (*emitter).last_anchor_id;
+    }
+}
+
+unsafe fn yaml_emitter_anchor_node(emitter: *mut yaml_emitter_t, index: libc::c_int) {
+    let node: *mut yaml_node_t = (*(*emitter).document)
+        .nodes
+        .start
+        .wrapping_offset(index as isize)
+        .wrapping_offset(-1_isize);
+    let mut item: *mut yaml_node_item_t;
+    let mut pair: *mut yaml_node_pair_t;
+    let fresh8 =
+        addr_of_mut!((*((*emitter).anchors).wrapping_offset((index - 1) as isize)).references);
+    *fresh8 += 1;
+    if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).references == 1 {
+        match (*node).type_ {
+            YAML_SEQUENCE_NODE => {
+                item = (*node).data.sequence.items.start;
+                while item < (*node).data.sequence.items.top {
+                    yaml_emitter_anchor_node_sub(emitter, *item);
+                    item = item.wrapping_offset(1);
+                }
+            }
+            YAML_MAPPING_NODE => {
+                pair = (*node).data.mapping.pairs.start;
+                while pair < (*node).data.mapping.pairs.top {
+                    yaml_emitter_anchor_node_sub(emitter, (*pair).key);
+                    yaml_emitter_anchor_node_sub(emitter, (*pair).value);
+                    pair = pair.wrapping_offset(1);
+                }
+            }
+            _ => {}
+        }
+    } else if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).references == 2 {
+        let fresh9 = addr_of_mut!((*emitter).last_anchor_id);
+        *fresh9 += 1;
+        (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).anchor = *fresh9;
+    }
+}
+
+unsafe fn yaml_emitter_generate_anchor(
+    _emitter: *mut yaml_emitter_t,
+    anchor_id: libc::c_int,
+) -> *mut yaml_char_t {
+    let anchor: *mut yaml_char_t = yaml_malloc(16_u64) as *mut yaml_char_t;
+    write!(WriteToPtr::new(anchor), "id{:03}\0", anchor_id);
+    anchor
+}
+
+unsafe fn yaml_emitter_dump_node(emitter: *mut yaml_emitter_t, index: libc::c_int) -> Success {
+    let node: *mut yaml_node_t = (*(*emitter).document)
+        .nodes
+        .start
+        .wrapping_offset(index as isize)
+        .wrapping_offset(-1_isize);
+    let anchor_id: libc::c_int = (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).anchor;
+    let mut anchor: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    if anchor_id != 0 {
+        anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
+    }
+    if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).serialized {
+        return yaml_emitter_dump_alias(emitter, anchor);
+    }
+    (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).serialized = true;
+    match (*node).type_ {
+        YAML_SCALAR_NODE => yaml_emitter_dump_scalar(emitter, node, anchor),
+        YAML_SEQUENCE_NODE => yaml_emitter_dump_sequence(emitter, node, anchor),
+        YAML_MAPPING_NODE => yaml_emitter_dump_mapping(emitter, node, anchor),
+        _ => __assert!(false),
+    }
+}
+
+unsafe fn yaml_emitter_dump_alias(
+    emitter: *mut yaml_emitter_t,
+    anchor: *mut yaml_char_t,
+) -> Success {
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_ALIAS_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    (*event).data.alias.anchor = anchor;
+    yaml_emitter_emit(emitter, event)
+}
+
+unsafe fn yaml_emitter_dump_scalar(
+    emitter: *mut yaml_emitter_t,
+    node: *mut yaml_node_t,
+    anchor: *mut yaml_char_t,
+) -> Success {
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    let plain_implicit = strcmp(
+        (*node).tag as *mut libc::c_char,
+        b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char,
+    ) == 0;
+    let quoted_implicit = strcmp(
+        (*node).tag as *mut libc::c_char,
+        b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char,
+    ) == 0;
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_SCALAR_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    (*event).data.scalar.anchor = anchor;
+    (*event).data.scalar.tag = (*node).tag;
+    (*event).data.scalar.value = (*node).data.scalar.value;
+    (*event).data.scalar.length = (*node).data.scalar.length;
+    (*event).data.scalar.plain_implicit = plain_implicit;
+    (*event).data.scalar.quoted_implicit = quoted_implicit;
+    (*event).data.scalar.style = (*node).data.scalar.style;
+    yaml_emitter_emit(emitter, event)
+}
+
+unsafe fn yaml_emitter_dump_sequence(
+    emitter: *mut yaml_emitter_t,
+    node: *mut yaml_node_t,
+    anchor: *mut yaml_char_t,
+) -> Success {
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    let implicit = strcmp(
+        (*node).tag as *mut libc::c_char,
+        b"tag:yaml.org,2002:seq\0" as *const u8 as *const libc::c_char,
+    ) == 0;
+    let mut item: *mut yaml_node_item_t;
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_SEQUENCE_START_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    (*event).data.sequence_start.anchor = anchor;
+    (*event).data.sequence_start.tag = (*node).tag;
+    (*event).data.sequence_start.implicit = implicit;
+    (*event).data.sequence_start.style = (*node).data.sequence.style;
+    if yaml_emitter_emit(emitter, event).fail {
+        return FAIL;
+    }
+    item = (*node).data.sequence.items.start;
+    while item < (*node).data.sequence.items.top {
+        if yaml_emitter_dump_node(emitter, *item).fail {
+            return FAIL;
+        }
+        item = item.wrapping_offset(1);
+    }
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_SEQUENCE_END_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    yaml_emitter_emit(emitter, event)
+}
+
+unsafe fn yaml_emitter_dump_mapping(
+    emitter: *mut yaml_emitter_t,
+    node: *mut yaml_node_t,
+    anchor: *mut yaml_char_t,
+) -> Success {
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    let mark = yaml_mark_t {
+        index: 0_u64,
+        line: 0_u64,
+        column: 0_u64,
+    };
+    let implicit = strcmp(
+        (*node).tag as *mut libc::c_char,
+        b"tag:yaml.org,2002:map\0" as *const u8 as *const libc::c_char,
+    ) == 0;
+    let mut pair: *mut yaml_node_pair_t;
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_MAPPING_START_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    (*event).data.mapping_start.anchor = anchor;
+    (*event).data.mapping_start.tag = (*node).tag;
+    (*event).data.mapping_start.implicit = implicit;
+    (*event).data.mapping_start.style = (*node).data.mapping.style;
+    if yaml_emitter_emit(emitter, event).fail {
+        return FAIL;
+    }
+    pair = (*node).data.mapping.pairs.start;
+    while pair < (*node).data.mapping.pairs.top {
+        if yaml_emitter_dump_node(emitter, (*pair).key).fail {
+            return FAIL;
+        }
+        if yaml_emitter_dump_node(emitter, (*pair).value).fail {
+            return FAIL;
+        }
+        pair = pair.wrapping_offset(1);
+    }
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_MAPPING_END_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    yaml_emitter_emit(emitter, event)
+}
diff --git a/src/emitter.rs b/src/emitter.rs
new file mode 100644
index 0000000..11f5cbd
--- /dev/null
+++ b/src/emitter.rs
@@ -0,0 +1,2384 @@
+use crate::api::{yaml_free, yaml_queue_extend, yaml_stack_extend, yaml_strdup};
+use crate::externs::{strcmp, strlen, strncmp};
+use crate::success::{Success, FAIL, OK};
+use crate::yaml::{size_t, yaml_char_t, yaml_string_t};
+use crate::{
+    libc, yaml_emitter_flush, yaml_emitter_t, yaml_event_delete, yaml_event_t, yaml_scalar_style_t,
+    yaml_tag_directive_t, yaml_version_directive_t, PointerExt, YAML_ALIAS_EVENT, YAML_ANY_BREAK,
+    YAML_ANY_ENCODING, YAML_ANY_SCALAR_STYLE, YAML_CRLN_BREAK, YAML_CR_BREAK,
+    YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_START_EVENT, YAML_DOUBLE_QUOTED_SCALAR_STYLE,
+    YAML_EMITTER_ERROR, YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE, YAML_EMIT_BLOCK_MAPPING_KEY_STATE,
+    YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE, YAML_EMIT_BLOCK_MAPPING_VALUE_STATE,
+    YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE, YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE,
+    YAML_EMIT_DOCUMENT_CONTENT_STATE, YAML_EMIT_DOCUMENT_END_STATE, YAML_EMIT_DOCUMENT_START_STATE,
+    YAML_EMIT_END_STATE, YAML_EMIT_FIRST_DOCUMENT_START_STATE,
+    YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE, YAML_EMIT_FLOW_MAPPING_KEY_STATE,
+    YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE, YAML_EMIT_FLOW_MAPPING_VALUE_STATE,
+    YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE, YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE,
+    YAML_EMIT_STREAM_START_STATE, YAML_FLOW_MAPPING_STYLE, YAML_FLOW_SEQUENCE_STYLE,
+    YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE, YAML_LN_BREAK, YAML_MAPPING_END_EVENT,
+    YAML_MAPPING_START_EVENT, YAML_PLAIN_SCALAR_STYLE, YAML_SCALAR_EVENT, YAML_SEQUENCE_END_EVENT,
+    YAML_SEQUENCE_START_EVENT, YAML_SINGLE_QUOTED_SCALAR_STYLE, YAML_STREAM_END_EVENT,
+    YAML_STREAM_START_EVENT, YAML_UTF8_ENCODING,
+};
+use core::ptr::{self, addr_of_mut};
+
+unsafe fn FLUSH(emitter: *mut yaml_emitter_t) -> Success {
+    if (*emitter).buffer.pointer.wrapping_offset(5_isize) < (*emitter).buffer.end {
+        OK
+    } else {
+        yaml_emitter_flush(emitter)
+    }
+}
+
+unsafe fn PUT(emitter: *mut yaml_emitter_t, value: u8) -> Success {
+    if FLUSH(emitter).fail {
+        return FAIL;
+    }
+    let fresh40 = addr_of_mut!((*emitter).buffer.pointer);
+    let fresh41 = *fresh40;
+    *fresh40 = (*fresh40).wrapping_offset(1);
+    *fresh41 = value;
+    let fresh42 = addr_of_mut!((*emitter).column);
+    *fresh42 += 1;
+    OK
+}
+
+unsafe fn PUT_BREAK(emitter: *mut yaml_emitter_t) -> Success {
+    if FLUSH(emitter).fail {
+        return FAIL;
+    }
+    if (*emitter).line_break == YAML_CR_BREAK {
+        let fresh62 = addr_of_mut!((*emitter).buffer.pointer);
+        let fresh63 = *fresh62;
+        *fresh62 = (*fresh62).wrapping_offset(1);
+        *fresh63 = b'\r';
+    } else if (*emitter).line_break == YAML_LN_BREAK {
+        let fresh64 = addr_of_mut!((*emitter).buffer.pointer);
+        let fresh65 = *fresh64;
+        *fresh64 = (*fresh64).wrapping_offset(1);
+        *fresh65 = b'\n';
+    } else if (*emitter).line_break == YAML_CRLN_BREAK {
+        let fresh66 = addr_of_mut!((*emitter).buffer.pointer);
+        let fresh67 = *fresh66;
+        *fresh66 = (*fresh66).wrapping_offset(1);
+        *fresh67 = b'\r';
+        let fresh68 = addr_of_mut!((*emitter).buffer.pointer);
+        let fresh69 = *fresh68;
+        *fresh68 = (*fresh68).wrapping_offset(1);
+        *fresh69 = b'\n';
+    };
+    (*emitter).column = 0;
+    let fresh70 = addr_of_mut!((*emitter).line);
+    *fresh70 += 1;
+    OK
+}
+
+unsafe fn WRITE(emitter: *mut yaml_emitter_t, string: *mut yaml_string_t) -> Success {
+    if FLUSH(emitter).fail {
+        return FAIL;
+    }
+    COPY!((*emitter).buffer, *string);
+    let fresh107 = addr_of_mut!((*emitter).column);
+    *fresh107 += 1;
+    OK
+}
+
+unsafe fn WRITE_BREAK(emitter: *mut yaml_emitter_t, string: *mut yaml_string_t) -> Success {
+    if FLUSH(emitter).fail {
+        return FAIL;
+    }
+    if CHECK!(*string, b'\n') {
+        let _ = PUT_BREAK(emitter);
+        (*string).pointer = (*string).pointer.wrapping_offset(1);
+    } else {
+        COPY!((*emitter).buffer, *string);
+        (*emitter).column = 0;
+        let fresh300 = addr_of_mut!((*emitter).line);
+        *fresh300 += 1;
+    }
+    OK
+}
+
+macro_rules! WRITE {
+    ($emitter:expr, $string:expr) => {
+        WRITE($emitter, addr_of_mut!($string))
+    };
+}
+
+macro_rules! WRITE_BREAK {
+    ($emitter:expr, $string:expr) => {
+        WRITE_BREAK($emitter, addr_of_mut!($string))
+    };
+}
+
+unsafe fn yaml_emitter_set_emitter_error(
+    emitter: *mut yaml_emitter_t,
+    problem: *const libc::c_char,
+) -> Success {
+    (*emitter).error = YAML_EMITTER_ERROR;
+    let fresh0 = addr_of_mut!((*emitter).problem);
+    *fresh0 = problem;
+    FAIL
+}
+
+/// Emit an event.
+///
+/// The event object may be generated using the yaml_parser_parse() function.
+/// The emitter takes the responsibility for the event object and destroys its
+/// content after it is emitted. The event object is destroyed even if the
+/// function fails.
+pub unsafe fn yaml_emitter_emit(emitter: *mut yaml_emitter_t, event: *mut yaml_event_t) -> Success {
+    ENQUEUE!((*emitter).events, *event);
+    while yaml_emitter_need_more_events(emitter).fail {
+        if yaml_emitter_analyze_event(emitter, (*emitter).events.head).fail {
+            return FAIL;
+        }
+        if yaml_emitter_state_machine(emitter, (*emitter).events.head).fail {
+            return FAIL;
+        }
+        yaml_event_delete(addr_of_mut!(DEQUEUE!((*emitter).events)));
+    }
+    OK
+}
+
+unsafe fn yaml_emitter_need_more_events(emitter: *mut yaml_emitter_t) -> Success {
+    let mut level: libc::c_int = 0;
+    let mut event: *mut yaml_event_t;
+    if QUEUE_EMPTY!((*emitter).events) {
+        return OK;
+    }
+    let accumulate = match (*(*emitter).events.head).type_ {
+        YAML_DOCUMENT_START_EVENT => 1,
+        YAML_SEQUENCE_START_EVENT => 2,
+        YAML_MAPPING_START_EVENT => 3,
+        _ => return FAIL,
+    };
+    if (*emitter).events.tail.c_offset_from((*emitter).events.head) as libc::c_long
+        > accumulate as libc::c_long
+    {
+        return FAIL;
+    }
+    event = (*emitter).events.head;
+    while event != (*emitter).events.tail {
+        match (*event).type_ {
+            YAML_STREAM_START_EVENT
+            | YAML_DOCUMENT_START_EVENT
+            | YAML_SEQUENCE_START_EVENT
+            | YAML_MAPPING_START_EVENT => {
+                level += 1;
+            }
+            YAML_STREAM_END_EVENT
+            | YAML_DOCUMENT_END_EVENT
+            | YAML_SEQUENCE_END_EVENT
+            | YAML_MAPPING_END_EVENT => {
+                level -= 1;
+            }
+            _ => {}
+        }
+        if level == 0 {
+            return FAIL;
+        }
+        event = event.wrapping_offset(1);
+    }
+    OK
+}
+
+unsafe fn yaml_emitter_append_tag_directive(
+    emitter: *mut yaml_emitter_t,
+    value: yaml_tag_directive_t,
+    allow_duplicates: bool,
+) -> Success {
+    let mut tag_directive: *mut yaml_tag_directive_t;
+    let mut copy = yaml_tag_directive_t {
+        handle: ptr::null_mut::<yaml_char_t>(),
+        prefix: ptr::null_mut::<yaml_char_t>(),
+    };
+    tag_directive = (*emitter).tag_directives.start;
+    while tag_directive != (*emitter).tag_directives.top {
+        if strcmp(
+            value.handle as *mut libc::c_char,
+            (*tag_directive).handle as *mut libc::c_char,
+        ) == 0
+        {
+            if allow_duplicates {
+                return OK;
+            }
+            return yaml_emitter_set_emitter_error(
+                emitter,
+                b"duplicate %TAG directive\0" as *const u8 as *const libc::c_char,
+            );
+        }
+        tag_directive = tag_directive.wrapping_offset(1);
+    }
+    copy.handle = yaml_strdup(value.handle);
+    copy.prefix = yaml_strdup(value.prefix);
+    PUSH!((*emitter).tag_directives, copy);
+    OK
+}
+
+unsafe fn yaml_emitter_increase_indent(emitter: *mut yaml_emitter_t, flow: bool, indentless: bool) {
+    PUSH!((*emitter).indents, (*emitter).indent);
+    if (*emitter).indent < 0 {
+        (*emitter).indent = if flow { (*emitter).best_indent } else { 0 };
+    } else if !indentless {
+        (*emitter).indent += (*emitter).best_indent;
+    }
+}
+
+unsafe fn yaml_emitter_state_machine(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    match (*emitter).state {
+        YAML_EMIT_STREAM_START_STATE => yaml_emitter_emit_stream_start(emitter, event),
+        YAML_EMIT_FIRST_DOCUMENT_START_STATE => {
+            yaml_emitter_emit_document_start(emitter, event, true)
+        }
+        YAML_EMIT_DOCUMENT_START_STATE => yaml_emitter_emit_document_start(emitter, event, false),
+        YAML_EMIT_DOCUMENT_CONTENT_STATE => yaml_emitter_emit_document_content(emitter, event),
+        YAML_EMIT_DOCUMENT_END_STATE => yaml_emitter_emit_document_end(emitter, event),
+        YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE => {
+            yaml_emitter_emit_flow_sequence_item(emitter, event, true)
+        }
+        YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE => {
+            yaml_emitter_emit_flow_sequence_item(emitter, event, false)
+        }
+        YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE => {
+            yaml_emitter_emit_flow_mapping_key(emitter, event, true)
+        }
+        YAML_EMIT_FLOW_MAPPING_KEY_STATE => {
+            yaml_emitter_emit_flow_mapping_key(emitter, event, false)
+        }
+        YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE => {
+            yaml_emitter_emit_flow_mapping_value(emitter, event, true)
+        }
+        YAML_EMIT_FLOW_MAPPING_VALUE_STATE => {
+            yaml_emitter_emit_flow_mapping_value(emitter, event, false)
+        }
+        YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE => {
+            yaml_emitter_emit_block_sequence_item(emitter, event, true)
+        }
+        YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE => {
+            yaml_emitter_emit_block_sequence_item(emitter, event, false)
+        }
+        YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE => {
+            yaml_emitter_emit_block_mapping_key(emitter, event, true)
+        }
+        YAML_EMIT_BLOCK_MAPPING_KEY_STATE => {
+            yaml_emitter_emit_block_mapping_key(emitter, event, false)
+        }
+        YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE => {
+            yaml_emitter_emit_block_mapping_value(emitter, event, true)
+        }
+        YAML_EMIT_BLOCK_MAPPING_VALUE_STATE => {
+            yaml_emitter_emit_block_mapping_value(emitter, event, false)
+        }
+        YAML_EMIT_END_STATE => yaml_emitter_set_emitter_error(
+            emitter,
+            b"expected nothing after STREAM-END\0" as *const u8 as *const libc::c_char,
+        ),
+    }
+}
+
+unsafe fn yaml_emitter_emit_stream_start(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    (*emitter).open_ended = 0;
+    if (*event).type_ == YAML_STREAM_START_EVENT {
+        if (*emitter).encoding == YAML_ANY_ENCODING {
+            (*emitter).encoding = (*event).data.stream_start.encoding;
+        }
+        if (*emitter).encoding == YAML_ANY_ENCODING {
+            (*emitter).encoding = YAML_UTF8_ENCODING;
+        }
+        if (*emitter).best_indent < 2 || (*emitter).best_indent > 9 {
+            (*emitter).best_indent = 2;
+        }
+        if (*emitter).best_width >= 0 && (*emitter).best_width <= (*emitter).best_indent * 2 {
+            (*emitter).best_width = 80;
+        }
+        if (*emitter).best_width < 0 {
+            (*emitter).best_width = libc::c_int::MAX;
+        }
+        if (*emitter).line_break == YAML_ANY_BREAK {
+            (*emitter).line_break = YAML_LN_BREAK;
+        }
+        (*emitter).indent = -1;
+        (*emitter).line = 0;
+        (*emitter).column = 0;
+        (*emitter).whitespace = true;
+        (*emitter).indention = true;
+        if (*emitter).encoding != YAML_UTF8_ENCODING {
+            if yaml_emitter_write_bom(emitter).fail {
+                return FAIL;
+            }
+        }
+        (*emitter).state = YAML_EMIT_FIRST_DOCUMENT_START_STATE;
+        return OK;
+    }
+    yaml_emitter_set_emitter_error(
+        emitter,
+        b"expected STREAM-START\0" as *const u8 as *const libc::c_char,
+    )
+}
+
+unsafe fn yaml_emitter_emit_document_start(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+    first: bool,
+) -> Success {
+    if (*event).type_ == YAML_DOCUMENT_START_EVENT {
+        let mut default_tag_directives: [yaml_tag_directive_t; 3] = [
+            yaml_tag_directive_t {
+                handle: b"!\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
+                prefix: b"!\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
+            },
+            yaml_tag_directive_t {
+                handle: b"!!\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
+                prefix: b"tag:yaml.org,2002:\0" as *const u8 as *const libc::c_char
+                    as *mut yaml_char_t,
+            },
+            yaml_tag_directive_t {
+                handle: ptr::null_mut::<yaml_char_t>(),
+                prefix: ptr::null_mut::<yaml_char_t>(),
+            },
+        ];
+        let mut tag_directive: *mut yaml_tag_directive_t;
+        let mut implicit;
+        if !(*event).data.document_start.version_directive.is_null() {
+            if yaml_emitter_analyze_version_directive(
+                emitter,
+                *(*event).data.document_start.version_directive,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+        }
+        tag_directive = (*event).data.document_start.tag_directives.start;
+        while tag_directive != (*event).data.document_start.tag_directives.end {
+            if yaml_emitter_analyze_tag_directive(emitter, *tag_directive).fail {
+                return FAIL;
+            }
+            if yaml_emitter_append_tag_directive(emitter, *tag_directive, false).fail {
+                return FAIL;
+            }
+            tag_directive = tag_directive.wrapping_offset(1);
+        }
+        tag_directive = default_tag_directives.as_mut_ptr();
+        while !(*tag_directive).handle.is_null() {
+            if yaml_emitter_append_tag_directive(emitter, *tag_directive, true).fail {
+                return FAIL;
+            }
+            tag_directive = tag_directive.wrapping_offset(1);
+        }
+        implicit = (*event).data.document_start.implicit;
+        if !first || (*emitter).canonical {
+            implicit = false;
+        }
+        if (!(*event).data.document_start.version_directive.is_null()
+            || (*event).data.document_start.tag_directives.start
+                != (*event).data.document_start.tag_directives.end)
+            && (*emitter).open_ended != 0
+        {
+            if yaml_emitter_write_indicator(
+                emitter,
+                b"...\0" as *const u8 as *const libc::c_char,
+                true,
+                false,
+                false,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+            if yaml_emitter_write_indent(emitter).fail {
+                return FAIL;
+            }
+        }
+        (*emitter).open_ended = 0;
+        if !(*event).data.document_start.version_directive.is_null() {
+            implicit = false;
+            if yaml_emitter_write_indicator(
+                emitter,
+                b"%YAML\0" as *const u8 as *const libc::c_char,
+                true,
+                false,
+                false,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+            if (*(*event).data.document_start.version_directive).minor == 1 {
+                if yaml_emitter_write_indicator(
+                    emitter,
+                    b"1.1\0" as *const u8 as *const libc::c_char,
+                    true,
+                    false,
+                    false,
+                )
+                .fail
+                {
+                    return FAIL;
+                }
+            } else if yaml_emitter_write_indicator(
+                emitter,
+                b"1.2\0" as *const u8 as *const libc::c_char,
+                true,
+                false,
+                false,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+            if yaml_emitter_write_indent(emitter).fail {
+                return FAIL;
+            }
+        }
+        if (*event).data.document_start.tag_directives.start
+            != (*event).data.document_start.tag_directives.end
+        {
+            implicit = false;
+            tag_directive = (*event).data.document_start.tag_directives.start;
+            while tag_directive != (*event).data.document_start.tag_directives.end {
+                if yaml_emitter_write_indicator(
+                    emitter,
+                    b"%TAG\0" as *const u8 as *const libc::c_char,
+                    true,
+                    false,
+                    false,
+                )
+                .fail
+                {
+                    return FAIL;
+                }
+                if yaml_emitter_write_tag_handle(
+                    emitter,
+                    (*tag_directive).handle,
+                    strlen((*tag_directive).handle as *mut libc::c_char),
+                )
+                .fail
+                {
+                    return FAIL;
+                }
+                if yaml_emitter_write_tag_content(
+                    emitter,
+                    (*tag_directive).prefix,
+                    strlen((*tag_directive).prefix as *mut libc::c_char),
+                    true,
+                )
+                .fail
+                {
+                    return FAIL;
+                }
+                if yaml_emitter_write_indent(emitter).fail {
+                    return FAIL;
+                }
+                tag_directive = tag_directive.wrapping_offset(1);
+            }
+        }
+        if yaml_emitter_check_empty_document(emitter) {
+            implicit = false;
+        }
+        if !implicit {
+            if yaml_emitter_write_indent(emitter).fail {
+                return FAIL;
+            }
+            if yaml_emitter_write_indicator(
+                emitter,
+                b"---\0" as *const u8 as *const libc::c_char,
+                true,
+                false,
+                false,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+            if (*emitter).canonical {
+                if yaml_emitter_write_indent(emitter).fail {
+                    return FAIL;
+                }
+            }
+        }
+        (*emitter).state = YAML_EMIT_DOCUMENT_CONTENT_STATE;
+        (*emitter).open_ended = 0;
+        return OK;
+    } else if (*event).type_ == YAML_STREAM_END_EVENT {
+        if (*emitter).open_ended == 2 {
+            if yaml_emitter_write_indicator(
+                emitter,
+                b"...\0" as *const u8 as *const libc::c_char,
+                true,
+                false,
+                false,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+            (*emitter).open_ended = 0;
+            if yaml_emitter_write_indent(emitter).fail {
+                return FAIL;
+            }
+        }
+        if yaml_emitter_flush(emitter).fail {
+            return FAIL;
+        }
+        (*emitter).state = YAML_EMIT_END_STATE;
+        return OK;
+    }
+    yaml_emitter_set_emitter_error(
+        emitter,
+        b"expected DOCUMENT-START or STREAM-END\0" as *const u8 as *const libc::c_char,
+    )
+}
+
+unsafe fn yaml_emitter_emit_document_content(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    PUSH!((*emitter).states, YAML_EMIT_DOCUMENT_END_STATE);
+    yaml_emitter_emit_node(emitter, event, true, false, false, false)
+}
+
+unsafe fn yaml_emitter_emit_document_end(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    if (*event).type_ == YAML_DOCUMENT_END_EVENT {
+        if yaml_emitter_write_indent(emitter).fail {
+            return FAIL;
+        }
+        if !(*event).data.document_end.implicit {
+            if yaml_emitter_write_indicator(
+                emitter,
+                b"...\0" as *const u8 as *const libc::c_char,
+                true,
+                false,
+                false,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+            (*emitter).open_ended = 0;
+            if yaml_emitter_write_indent(emitter).fail {
+                return FAIL;
+            }
+        } else if (*emitter).open_ended == 0 {
+            (*emitter).open_ended = 1;
+        }
+        if yaml_emitter_flush(emitter).fail {
+            return FAIL;
+        }
+        (*emitter).state = YAML_EMIT_DOCUMENT_START_STATE;
+        while !STACK_EMPTY!((*emitter).tag_directives) {
+            let tag_directive = POP!((*emitter).tag_directives);
+            yaml_free(tag_directive.handle as *mut libc::c_void);
+            yaml_free(tag_directive.prefix as *mut libc::c_void);
+        }
+        return OK;
+    }
+    yaml_emitter_set_emitter_error(
+        emitter,
+        b"expected DOCUMENT-END\0" as *const u8 as *const libc::c_char,
+    )
+}
+
+unsafe fn yaml_emitter_emit_flow_sequence_item(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+    first: bool,
+) -> Success {
+    if first {
+        if yaml_emitter_write_indicator(
+            emitter,
+            b"[\0" as *const u8 as *const libc::c_char,
+            true,
+            true,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        yaml_emitter_increase_indent(emitter, true, false);
+        let fresh12 = addr_of_mut!((*emitter).flow_level);
+        *fresh12 += 1;
+    }
+    if (*event).type_ == YAML_SEQUENCE_END_EVENT {
+        let fresh13 = addr_of_mut!((*emitter).flow_level);
+        *fresh13 -= 1;
+        (*emitter).indent = POP!((*emitter).indents);
+        if (*emitter).canonical && !first {
+            if yaml_emitter_write_indicator(
+                emitter,
+                b",\0" as *const u8 as *const libc::c_char,
+                false,
+                false,
+                false,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+            if yaml_emitter_write_indent(emitter).fail {
+                return FAIL;
+            }
+        }
+        if yaml_emitter_write_indicator(
+            emitter,
+            b"]\0" as *const u8 as *const libc::c_char,
+            false,
+            false,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        (*emitter).state = POP!((*emitter).states);
+        return OK;
+    }
+    if !first {
+        if yaml_emitter_write_indicator(
+            emitter,
+            b",\0" as *const u8 as *const libc::c_char,
+            false,
+            false,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+    }
+    if (*emitter).canonical || (*emitter).column > (*emitter).best_width {
+        if yaml_emitter_write_indent(emitter).fail {
+            return FAIL;
+        }
+    }
+    PUSH!((*emitter).states, YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE);
+    yaml_emitter_emit_node(emitter, event, false, true, false, false)
+}
+
+unsafe fn yaml_emitter_emit_flow_mapping_key(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+    first: bool,
+) -> Success {
+    if first {
+        if yaml_emitter_write_indicator(
+            emitter,
+            b"{\0" as *const u8 as *const libc::c_char,
+            true,
+            true,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        yaml_emitter_increase_indent(emitter, true, false);
+        let fresh18 = addr_of_mut!((*emitter).flow_level);
+        *fresh18 += 1;
+    }
+    if (*event).type_ == YAML_MAPPING_END_EVENT {
+        if STACK_EMPTY!((*emitter).indents) {
+            return FAIL;
+        }
+        let fresh19 = addr_of_mut!((*emitter).flow_level);
+        *fresh19 -= 1;
+        (*emitter).indent = POP!((*emitter).indents);
+        if (*emitter).canonical && !first {
+            if yaml_emitter_write_indicator(
+                emitter,
+                b",\0" as *const u8 as *const libc::c_char,
+                false,
+                false,
+                false,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+            if yaml_emitter_write_indent(emitter).fail {
+                return FAIL;
+            }
+        }
+        if yaml_emitter_write_indicator(
+            emitter,
+            b"}\0" as *const u8 as *const libc::c_char,
+            false,
+            false,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        (*emitter).state = POP!((*emitter).states);
+        return OK;
+    }
+    if !first {
+        if yaml_emitter_write_indicator(
+            emitter,
+            b",\0" as *const u8 as *const libc::c_char,
+            false,
+            false,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+    }
+    if (*emitter).canonical || (*emitter).column > (*emitter).best_width {
+        if yaml_emitter_write_indent(emitter).fail {
+            return FAIL;
+        }
+    }
+    if !(*emitter).canonical && yaml_emitter_check_simple_key(emitter) {
+        PUSH!((*emitter).states, YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE);
+        yaml_emitter_emit_node(emitter, event, false, false, true, true)
+    } else {
+        if yaml_emitter_write_indicator(
+            emitter,
+            b"?\0" as *const u8 as *const libc::c_char,
+            true,
+            false,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        PUSH!((*emitter).states, YAML_EMIT_FLOW_MAPPING_VALUE_STATE);
+        yaml_emitter_emit_node(emitter, event, false, false, true, false)
+    }
+}
+
+unsafe fn yaml_emitter_emit_flow_mapping_value(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+    simple: bool,
+) -> Success {
+    if simple {
+        if yaml_emitter_write_indicator(
+            emitter,
+            b":\0" as *const u8 as *const libc::c_char,
+            false,
+            false,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+    } else {
+        if (*emitter).canonical || (*emitter).column > (*emitter).best_width {
+            if yaml_emitter_write_indent(emitter).fail {
+                return FAIL;
+            }
+        }
+        if yaml_emitter_write_indicator(
+            emitter,
+            b":\0" as *const u8 as *const libc::c_char,
+            true,
+            false,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+    }
+    PUSH!((*emitter).states, YAML_EMIT_FLOW_MAPPING_KEY_STATE);
+    yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+unsafe fn yaml_emitter_emit_block_sequence_item(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+    first: bool,
+) -> Success {
+    if first {
+        yaml_emitter_increase_indent(
+            emitter,
+            false,
+            (*emitter).mapping_context && !(*emitter).indention,
+        );
+    }
+    if (*event).type_ == YAML_SEQUENCE_END_EVENT {
+        (*emitter).indent = POP!((*emitter).indents);
+        (*emitter).state = POP!((*emitter).states);
+        return OK;
+    }
+    if yaml_emitter_write_indent(emitter).fail {
+        return FAIL;
+    }
+    if yaml_emitter_write_indicator(
+        emitter,
+        b"-\0" as *const u8 as *const libc::c_char,
+        true,
+        false,
+        true,
+    )
+    .fail
+    {
+        return FAIL;
+    }
+    PUSH!((*emitter).states, YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE);
+    yaml_emitter_emit_node(emitter, event, false, true, false, false)
+}
+
+unsafe fn yaml_emitter_emit_block_mapping_key(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+    first: bool,
+) -> Success {
+    if first {
+        yaml_emitter_increase_indent(emitter, false, false);
+    }
+    if (*event).type_ == YAML_MAPPING_END_EVENT {
+        (*emitter).indent = POP!((*emitter).indents);
+        (*emitter).state = POP!((*emitter).states);
+        return OK;
+    }
+    if yaml_emitter_write_indent(emitter).fail {
+        return FAIL;
+    }
+    if yaml_emitter_check_simple_key(emitter) {
+        PUSH!(
+            (*emitter).states,
+            YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE
+        );
+        yaml_emitter_emit_node(emitter, event, false, false, true, true)
+    } else {
+        if yaml_emitter_write_indicator(
+            emitter,
+            b"?\0" as *const u8 as *const libc::c_char,
+            true,
+            false,
+            true,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        PUSH!((*emitter).states, YAML_EMIT_BLOCK_MAPPING_VALUE_STATE);
+        yaml_emitter_emit_node(emitter, event, false, false, true, false)
+    }
+}
+
+unsafe fn yaml_emitter_emit_block_mapping_value(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+    simple: bool,
+) -> Success {
+    if simple {
+        if yaml_emitter_write_indicator(
+            emitter,
+            b":\0" as *const u8 as *const libc::c_char,
+            false,
+            false,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+    } else {
+        if yaml_emitter_write_indent(emitter).fail {
+            return FAIL;
+        }
+        if yaml_emitter_write_indicator(
+            emitter,
+            b":\0" as *const u8 as *const libc::c_char,
+            true,
+            false,
+            true,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+    }
+    PUSH!((*emitter).states, YAML_EMIT_BLOCK_MAPPING_KEY_STATE);
+    yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+unsafe fn yaml_emitter_emit_node(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+    root: bool,
+    sequence: bool,
+    mapping: bool,
+    simple_key: bool,
+) -> Success {
+    (*emitter).root_context = root;
+    (*emitter).sequence_context = sequence;
+    (*emitter).mapping_context = mapping;
+    (*emitter).simple_key_context = simple_key;
+    match (*event).type_ {
+        YAML_ALIAS_EVENT => yaml_emitter_emit_alias(emitter, event),
+        YAML_SCALAR_EVENT => yaml_emitter_emit_scalar(emitter, event),
+        YAML_SEQUENCE_START_EVENT => yaml_emitter_emit_sequence_start(emitter, event),
+        YAML_MAPPING_START_EVENT => yaml_emitter_emit_mapping_start(emitter, event),
+        _ => yaml_emitter_set_emitter_error(
+            emitter,
+            b"expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS\0" as *const u8
+                as *const libc::c_char,
+        ),
+    }
+}
+
+unsafe fn yaml_emitter_emit_alias(
+    emitter: *mut yaml_emitter_t,
+    _event: *mut yaml_event_t,
+) -> Success {
+    if yaml_emitter_process_anchor(emitter).fail {
+        return FAIL;
+    }
+    if (*emitter).simple_key_context {
+        if PUT(emitter, b' ').fail {
+            return FAIL;
+        }
+    }
+    (*emitter).state = POP!((*emitter).states);
+    OK
+}
+
+unsafe fn yaml_emitter_emit_scalar(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    if yaml_emitter_select_scalar_style(emitter, event).fail {
+        return FAIL;
+    }
+    if yaml_emitter_process_anchor(emitter).fail {
+        return FAIL;
+    }
+    if yaml_emitter_process_tag(emitter).fail {
+        return FAIL;
+    }
+    yaml_emitter_increase_indent(emitter, true, false);
+    if yaml_emitter_process_scalar(emitter).fail {
+        return FAIL;
+    }
+    (*emitter).indent = POP!((*emitter).indents);
+    (*emitter).state = POP!((*emitter).states);
+    OK
+}
+
+unsafe fn yaml_emitter_emit_sequence_start(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    if yaml_emitter_process_anchor(emitter).fail {
+        return FAIL;
+    }
+    if yaml_emitter_process_tag(emitter).fail {
+        return FAIL;
+    }
+    if (*emitter).flow_level != 0
+        || (*emitter).canonical
+        || (*event).data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE
+        || yaml_emitter_check_empty_sequence(emitter)
+    {
+        (*emitter).state = YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE;
+    } else {
+        (*emitter).state = YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE;
+    }
+    OK
+}
+
+unsafe fn yaml_emitter_emit_mapping_start(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    if yaml_emitter_process_anchor(emitter).fail {
+        return FAIL;
+    }
+    if yaml_emitter_process_tag(emitter).fail {
+        return FAIL;
+    }
+    if (*emitter).flow_level != 0
+        || (*emitter).canonical
+        || (*event).data.mapping_start.style == YAML_FLOW_MAPPING_STYLE
+        || yaml_emitter_check_empty_mapping(emitter)
+    {
+        (*emitter).state = YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE;
+    } else {
+        (*emitter).state = YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE;
+    }
+    OK
+}
+
+unsafe fn yaml_emitter_check_empty_document(_emitter: *mut yaml_emitter_t) -> bool {
+    false
+}
+
+unsafe fn yaml_emitter_check_empty_sequence(emitter: *mut yaml_emitter_t) -> bool {
+    if ((*emitter).events.tail.c_offset_from((*emitter).events.head) as libc::c_long) < 2_i64 {
+        return false;
+    }
+    (*(*emitter).events.head).type_ == YAML_SEQUENCE_START_EVENT
+        && (*(*emitter).events.head.wrapping_offset(1_isize)).type_ == YAML_SEQUENCE_END_EVENT
+}
+
+unsafe fn yaml_emitter_check_empty_mapping(emitter: *mut yaml_emitter_t) -> bool {
+    if ((*emitter).events.tail.c_offset_from((*emitter).events.head) as libc::c_long) < 2_i64 {
+        return false;
+    }
+    (*(*emitter).events.head).type_ == YAML_MAPPING_START_EVENT
+        && (*(*emitter).events.head.wrapping_offset(1_isize)).type_ == YAML_MAPPING_END_EVENT
+}
+
+unsafe fn yaml_emitter_check_simple_key(emitter: *mut yaml_emitter_t) -> bool {
+    let event: *mut yaml_event_t = (*emitter).events.head;
+    let mut length: size_t = 0_u64;
+    match (*event).type_ {
+        YAML_ALIAS_EVENT => {
+            length = (length as libc::c_ulong).wrapping_add((*emitter).anchor_data.anchor_length)
+                as size_t as size_t;
+        }
+        YAML_SCALAR_EVENT => {
+            if (*emitter).scalar_data.multiline {
+                return false;
+            }
+            length = (length as libc::c_ulong).wrapping_add(
+                (*emitter)
+                    .anchor_data
+                    .anchor_length
+                    .wrapping_add((*emitter).tag_data.handle_length)
+                    .wrapping_add((*emitter).tag_data.suffix_length)
+                    .wrapping_add((*emitter).scalar_data.length),
+            ) as size_t as size_t;
+        }
+        YAML_SEQUENCE_START_EVENT => {
+            if !yaml_emitter_check_empty_sequence(emitter) {
+                return false;
+            }
+            length = (length as libc::c_ulong).wrapping_add(
+                (*emitter)
+                    .anchor_data
+                    .anchor_length
+                    .wrapping_add((*emitter).tag_data.handle_length)
+                    .wrapping_add((*emitter).tag_data.suffix_length),
+            ) as size_t as size_t;
+        }
+        YAML_MAPPING_START_EVENT => {
+            if !yaml_emitter_check_empty_mapping(emitter) {
+                return false;
+            }
+            length = (length as libc::c_ulong).wrapping_add(
+                (*emitter)
+                    .anchor_data
+                    .anchor_length
+                    .wrapping_add((*emitter).tag_data.handle_length)
+                    .wrapping_add((*emitter).tag_data.suffix_length),
+            ) as size_t as size_t;
+        }
+        _ => return false,
+    }
+    if length > 128_u64 {
+        return false;
+    }
+    true
+}
+
+unsafe fn yaml_emitter_select_scalar_style(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let mut style: yaml_scalar_style_t = (*event).data.scalar.style;
+    let no_tag = (*emitter).tag_data.handle.is_null() && (*emitter).tag_data.suffix.is_null();
+    if no_tag && !(*event).data.scalar.plain_implicit && !(*event).data.scalar.quoted_implicit {
+        return yaml_emitter_set_emitter_error(
+            emitter,
+            b"neither tag nor implicit flags are specified\0" as *const u8 as *const libc::c_char,
+        );
+    }
+    if style == YAML_ANY_SCALAR_STYLE {
+        style = YAML_PLAIN_SCALAR_STYLE;
+    }
+    if (*emitter).canonical {
+        style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
+    }
+    if (*emitter).simple_key_context && (*emitter).scalar_data.multiline {
+        style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
+    }
+    if style == YAML_PLAIN_SCALAR_STYLE {
+        if (*emitter).flow_level != 0 && !(*emitter).scalar_data.flow_plain_allowed
+            || (*emitter).flow_level == 0 && !(*emitter).scalar_data.block_plain_allowed
+        {
+            style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
+        }
+        if (*emitter).scalar_data.length == 0
+            && ((*emitter).flow_level != 0 || (*emitter).simple_key_context)
+        {
+            style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
+        }
+        if no_tag && !(*event).data.scalar.plain_implicit {
+            style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
+        }
+    }
+    if style == YAML_SINGLE_QUOTED_SCALAR_STYLE {
+        if !(*emitter).scalar_data.single_quoted_allowed {
+            style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
+        }
+    }
+    if style == YAML_LITERAL_SCALAR_STYLE || style == YAML_FOLDED_SCALAR_STYLE {
+        if !(*emitter).scalar_data.block_allowed
+            || (*emitter).flow_level != 0
+            || (*emitter).simple_key_context
+        {
+            style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
+        }
+    }
+    if no_tag && !(*event).data.scalar.quoted_implicit && style != YAML_PLAIN_SCALAR_STYLE {
+        let fresh46 = addr_of_mut!((*emitter).tag_data.handle);
+        *fresh46 = b"!\0" as *const u8 as *const libc::c_char as *mut yaml_char_t;
+        (*emitter).tag_data.handle_length = 1_u64;
+    }
+    (*emitter).scalar_data.style = style;
+    OK
+}
+
+unsafe fn yaml_emitter_process_anchor(emitter: *mut yaml_emitter_t) -> Success {
+    if (*emitter).anchor_data.anchor.is_null() {
+        return OK;
+    }
+    if yaml_emitter_write_indicator(
+        emitter,
+        if (*emitter).anchor_data.alias {
+            b"*\0" as *const u8 as *const libc::c_char
+        } else {
+            b"&\0" as *const u8 as *const libc::c_char
+        },
+        true,
+        false,
+        false,
+    )
+    .fail
+    {
+        return FAIL;
+    }
+    yaml_emitter_write_anchor(
+        emitter,
+        (*emitter).anchor_data.anchor,
+        (*emitter).anchor_data.anchor_length,
+    )
+}
+
+unsafe fn yaml_emitter_process_tag(emitter: *mut yaml_emitter_t) -> Success {
+    if (*emitter).tag_data.handle.is_null() && (*emitter).tag_data.suffix.is_null() {
+        return OK;
+    }
+    if !(*emitter).tag_data.handle.is_null() {
+        if yaml_emitter_write_tag_handle(
+            emitter,
+            (*emitter).tag_data.handle,
+            (*emitter).tag_data.handle_length,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        if !(*emitter).tag_data.suffix.is_null() {
+            if yaml_emitter_write_tag_content(
+                emitter,
+                (*emitter).tag_data.suffix,
+                (*emitter).tag_data.suffix_length,
+                false,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+        }
+    } else {
+        if yaml_emitter_write_indicator(
+            emitter,
+            b"!<\0" as *const u8 as *const libc::c_char,
+            true,
+            false,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        if yaml_emitter_write_tag_content(
+            emitter,
+            (*emitter).tag_data.suffix,
+            (*emitter).tag_data.suffix_length,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        if yaml_emitter_write_indicator(
+            emitter,
+            b">\0" as *const u8 as *const libc::c_char,
+            false,
+            false,
+            false,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+    }
+    OK
+}
+
+unsafe fn yaml_emitter_process_scalar(emitter: *mut yaml_emitter_t) -> Success {
+    match (*emitter).scalar_data.style {
+        YAML_PLAIN_SCALAR_STYLE => {
+            return yaml_emitter_write_plain_scalar(
+                emitter,
+                (*emitter).scalar_data.value,
+                (*emitter).scalar_data.length,
+                !(*emitter).simple_key_context,
+            );
+        }
+        YAML_SINGLE_QUOTED_SCALAR_STYLE => {
+            return yaml_emitter_write_single_quoted_scalar(
+                emitter,
+                (*emitter).scalar_data.value,
+                (*emitter).scalar_data.length,
+                !(*emitter).simple_key_context,
+            );
+        }
+        YAML_DOUBLE_QUOTED_SCALAR_STYLE => {
+            return yaml_emitter_write_double_quoted_scalar(
+                emitter,
+                (*emitter).scalar_data.value,
+                (*emitter).scalar_data.length,
+                !(*emitter).simple_key_context,
+            );
+        }
+        YAML_LITERAL_SCALAR_STYLE => {
+            return yaml_emitter_write_literal_scalar(
+                emitter,
+                (*emitter).scalar_data.value,
+                (*emitter).scalar_data.length,
+            );
+        }
+        YAML_FOLDED_SCALAR_STYLE => {
+            return yaml_emitter_write_folded_scalar(
+                emitter,
+                (*emitter).scalar_data.value,
+                (*emitter).scalar_data.length,
+            );
+        }
+        _ => {}
+    }
+    FAIL
+}
+
+unsafe fn yaml_emitter_analyze_version_directive(
+    emitter: *mut yaml_emitter_t,
+    version_directive: yaml_version_directive_t,
+) -> Success {
+    if version_directive.major != 1 || version_directive.minor != 1 && version_directive.minor != 2
+    {
+        return yaml_emitter_set_emitter_error(
+            emitter,
+            b"incompatible %YAML directive\0" as *const u8 as *const libc::c_char,
+        );
+    }
+    OK
+}
+
+unsafe fn yaml_emitter_analyze_tag_directive(
+    emitter: *mut yaml_emitter_t,
+    tag_directive: yaml_tag_directive_t,
+) -> Success {
+    let handle_length: size_t = strlen(tag_directive.handle as *mut libc::c_char);
+    let prefix_length: size_t = strlen(tag_directive.prefix as *mut libc::c_char);
+    let mut handle = STRING_ASSIGN!(tag_directive.handle, handle_length);
+    let prefix = STRING_ASSIGN!(tag_directive.prefix, prefix_length);
+    if handle.start == handle.end {
+        return yaml_emitter_set_emitter_error(
+            emitter,
+            b"tag handle must not be empty\0" as *const u8 as *const libc::c_char,
+        );
+    }
+    if *handle.start != b'!' {
+        return yaml_emitter_set_emitter_error(
+            emitter,
+            b"tag handle must start with '!'\0" as *const u8 as *const libc::c_char,
+        );
+    }
+    if *handle.end.wrapping_offset(-1_isize) != b'!' {
+        return yaml_emitter_set_emitter_error(
+            emitter,
+            b"tag handle must end with '!'\0" as *const u8 as *const libc::c_char,
+        );
+    }
+    handle.pointer = handle.pointer.wrapping_offset(1);
+    while handle.pointer < handle.end.wrapping_offset(-1_isize) {
+        if !IS_ALPHA!(handle) {
+            return yaml_emitter_set_emitter_error(
+                emitter,
+                b"tag handle must contain alphanumerical characters only\0" as *const u8
+                    as *const libc::c_char,
+            );
+        }
+        MOVE!(handle);
+    }
+    if prefix.start == prefix.end {
+        return yaml_emitter_set_emitter_error(
+            emitter,
+            b"tag prefix must not be empty\0" as *const u8 as *const libc::c_char,
+        );
+    }
+    OK
+}
+
+unsafe fn yaml_emitter_analyze_anchor(
+    emitter: *mut yaml_emitter_t,
+    anchor: *mut yaml_char_t,
+    alias: bool,
+) -> Success {
+    let anchor_length: size_t = strlen(anchor as *mut libc::c_char);
+    let mut string = STRING_ASSIGN!(anchor, anchor_length);
+    if string.start == string.end {
+        return yaml_emitter_set_emitter_error(
+            emitter,
+            if alias {
+                b"alias value must not be empty\0" as *const u8 as *const libc::c_char
+            } else {
+                b"anchor value must not be empty\0" as *const u8 as *const libc::c_char
+            },
+        );
+    }
+    while string.pointer != string.end {
+        if !IS_ALPHA!(string) {
+            return yaml_emitter_set_emitter_error(
+                emitter,
+                if alias {
+                    b"alias value must contain alphanumerical characters only\0" as *const u8
+                        as *const libc::c_char
+                } else {
+                    b"anchor value must contain alphanumerical characters only\0" as *const u8
+                        as *const libc::c_char
+                },
+            );
+        }
+        MOVE!(string);
+    }
+    let fresh47 = addr_of_mut!((*emitter).anchor_data.anchor);
+    *fresh47 = string.start;
+    (*emitter).anchor_data.anchor_length =
+        string.end.c_offset_from(string.start) as libc::c_long as size_t;
+    (*emitter).anchor_data.alias = alias;
+    OK
+}
+
+unsafe fn yaml_emitter_analyze_tag(emitter: *mut yaml_emitter_t, tag: *mut yaml_char_t) -> Success {
+    let mut tag_directive: *mut yaml_tag_directive_t;
+    let tag_length: size_t = strlen(tag as *mut libc::c_char);
+    let string = STRING_ASSIGN!(tag, tag_length);
+    if string.start == string.end {
+        return yaml_emitter_set_emitter_error(
+            emitter,
+            b"tag value must not be empty\0" as *const u8 as *const libc::c_char,
+        );
+    }
+    tag_directive = (*emitter).tag_directives.start;
+    while tag_directive != (*emitter).tag_directives.top {
+        let prefix_length: size_t = strlen((*tag_directive).prefix as *mut libc::c_char);
+        if prefix_length < string.end.c_offset_from(string.start) as libc::c_long as size_t
+            && strncmp(
+                (*tag_directive).prefix as *mut libc::c_char,
+                string.start as *mut libc::c_char,
+                prefix_length,
+            ) == 0
+        {
+            let fresh48 = addr_of_mut!((*emitter).tag_data.handle);
+            *fresh48 = (*tag_directive).handle;
+            (*emitter).tag_data.handle_length =
+                strlen((*tag_directive).handle as *mut libc::c_char);
+            let fresh49 = addr_of_mut!((*emitter).tag_data.suffix);
+            *fresh49 = string.start.wrapping_offset(prefix_length as isize);
+            (*emitter).tag_data.suffix_length = (string.end.c_offset_from(string.start)
+                as libc::c_long as libc::c_ulong)
+                .wrapping_sub(prefix_length);
+            return OK;
+        }
+        tag_directive = tag_directive.wrapping_offset(1);
+    }
+    let fresh50 = addr_of_mut!((*emitter).tag_data.suffix);
+    *fresh50 = string.start;
+    (*emitter).tag_data.suffix_length =
+        string.end.c_offset_from(string.start) as libc::c_long as size_t;
+    OK
+}
+
+unsafe fn yaml_emitter_analyze_scalar(
+    emitter: *mut yaml_emitter_t,
+    value: *mut yaml_char_t,
+    length: size_t,
+) -> Success {
+    let mut block_indicators = false;
+    let mut flow_indicators = false;
+    let mut line_breaks = false;
+    let mut special_characters = false;
+    let mut leading_space = false;
+    let mut leading_break = false;
+    let mut trailing_space = false;
+    let mut trailing_break = false;
+    let mut break_space = false;
+    let mut space_break = false;
+    let mut preceded_by_whitespace;
+    let mut followed_by_whitespace;
+    let mut previous_space = false;
+    let mut previous_break = false;
+    let mut string = STRING_ASSIGN!(value, length);
+    let fresh51 = addr_of_mut!((*emitter).scalar_data.value);
+    *fresh51 = value;
+    (*emitter).scalar_data.length = length;
+    if string.start == string.end {
+        (*emitter).scalar_data.multiline = false;
+        (*emitter).scalar_data.flow_plain_allowed = false;
+        (*emitter).scalar_data.block_plain_allowed = true;
+        (*emitter).scalar_data.single_quoted_allowed = true;
+        (*emitter).scalar_data.block_allowed = false;
+        return OK;
+    }
+    if CHECK_AT!(string, b'-', 0) && CHECK_AT!(string, b'-', 1) && CHECK_AT!(string, b'-', 2)
+        || CHECK_AT!(string, b'.', 0) && CHECK_AT!(string, b'.', 1) && CHECK_AT!(string, b'.', 2)
+    {
+        block_indicators = true;
+        flow_indicators = true;
+    }
+    preceded_by_whitespace = true;
+    followed_by_whitespace = IS_BLANKZ_AT!(string, WIDTH!(string));
+    while string.pointer != string.end {
+        if string.start == string.pointer {
+            if CHECK!(string, b'#')
+                || CHECK!(string, b',')
+                || CHECK!(string, b'[')
+                || CHECK!(string, b']')
+                || CHECK!(string, b'{')
+                || CHECK!(string, b'}')
+                || CHECK!(string, b'&')
+                || CHECK!(string, b'*')
+                || CHECK!(string, b'!')
+                || CHECK!(string, b'|')
+                || CHECK!(string, b'>')
+                || CHECK!(string, b'\'')
+                || CHECK!(string, b'"')
+                || CHECK!(string, b'%')
+                || CHECK!(string, b'@')
+                || CHECK!(string, b'`')
+            {
+                flow_indicators = true;
+                block_indicators = true;
+            }
+            if CHECK!(string, b'?') || CHECK!(string, b':') {
+                flow_indicators = true;
+                if followed_by_whitespace {
+                    block_indicators = true;
+                }
+            }
+            if CHECK!(string, b'-') && followed_by_whitespace {
+                flow_indicators = true;
+                block_indicators = true;
+            }
+        } else {
+            if CHECK!(string, b',')
+                || CHECK!(string, b'?')
+                || CHECK!(string, b'[')
+                || CHECK!(string, b']')
+                || CHECK!(string, b'{')
+                || CHECK!(string, b'}')
+            {
+                flow_indicators = true;
+            }
+            if CHECK!(string, b':') {
+                flow_indicators = true;
+                if followed_by_whitespace {
+                    block_indicators = true;
+                }
+            }
+            if CHECK!(string, b'#') && preceded_by_whitespace {
+                flow_indicators = true;
+                block_indicators = true;
+            }
+        }
+        if !IS_PRINTABLE!(string) || !IS_ASCII!(string) && !(*emitter).unicode {
+            special_characters = true;
+        }
+        if IS_BREAK!(string) {
+            line_breaks = true;
+        }
+        if IS_SPACE!(string) {
+            if string.start == string.pointer {
+                leading_space = true;
+            }
+            if string.pointer.wrapping_offset(WIDTH!(string) as isize) == string.end {
+                trailing_space = true;
+            }
+            if previous_break {
+                break_space = true;
+            }
+            previous_space = true;
+            previous_break = false;
+        } else if IS_BREAK!(string) {
+            if string.start == string.pointer {
+                leading_break = true;
+            }
+            if string.pointer.wrapping_offset(WIDTH!(string) as isize) == string.end {
+                trailing_break = true;
+            }
+            if previous_space {
+                space_break = true;
+            }
+            previous_space = false;
+            previous_break = true;
+        } else {
+            previous_space = false;
+            previous_break = false;
+        }
+        preceded_by_whitespace = IS_BLANKZ!(string);
+        MOVE!(string);
+        if string.pointer != string.end {
+            followed_by_whitespace = IS_BLANKZ_AT!(string, WIDTH!(string));
+        }
+    }
+    (*emitter).scalar_data.multiline = line_breaks;
+    (*emitter).scalar_data.flow_plain_allowed = true;
+    (*emitter).scalar_data.block_plain_allowed = true;
+    (*emitter).scalar_data.single_quoted_allowed = true;
+    (*emitter).scalar_data.block_allowed = true;
+    if leading_space || leading_break || trailing_space || trailing_break {
+        (*emitter).scalar_data.flow_plain_allowed = false;
+        (*emitter).scalar_data.block_plain_allowed = false;
+    }
+    if trailing_space {
+        (*emitter).scalar_data.block_allowed = false;
+    }
+    if break_space {
+        (*emitter).scalar_data.flow_plain_allowed = false;
+        (*emitter).scalar_data.block_plain_allowed = false;
+        (*emitter).scalar_data.single_quoted_allowed = false;
+    }
+    if space_break || special_characters {
+        (*emitter).scalar_data.flow_plain_allowed = false;
+        (*emitter).scalar_data.block_plain_allowed = false;
+        (*emitter).scalar_data.single_quoted_allowed = false;
+        (*emitter).scalar_data.block_allowed = false;
+    }
+    if line_breaks {
+        (*emitter).scalar_data.flow_plain_allowed = false;
+        (*emitter).scalar_data.block_plain_allowed = false;
+    }
+    if flow_indicators {
+        (*emitter).scalar_data.flow_plain_allowed = false;
+    }
+    if block_indicators {
+        (*emitter).scalar_data.block_plain_allowed = false;
+    }
+    OK
+}
+
+unsafe fn yaml_emitter_analyze_event(
+    emitter: *mut yaml_emitter_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let fresh52 = addr_of_mut!((*emitter).anchor_data.anchor);
+    *fresh52 = ptr::null_mut::<yaml_char_t>();
+    (*emitter).anchor_data.anchor_length = 0_u64;
+    let fresh53 = addr_of_mut!((*emitter).tag_data.handle);
+    *fresh53 = ptr::null_mut::<yaml_char_t>();
+    (*emitter).tag_data.handle_length = 0_u64;
+    let fresh54 = addr_of_mut!((*emitter).tag_data.suffix);
+    *fresh54 = ptr::null_mut::<yaml_char_t>();
+    (*emitter).tag_data.suffix_length = 0_u64;
+    let fresh55 = addr_of_mut!((*emitter).scalar_data.value);
+    *fresh55 = ptr::null_mut::<yaml_char_t>();
+    (*emitter).scalar_data.length = 0_u64;
+    match (*event).type_ {
+        YAML_ALIAS_EVENT => yaml_emitter_analyze_anchor(emitter, (*event).data.alias.anchor, true),
+        YAML_SCALAR_EVENT => {
+            if !(*event).data.scalar.anchor.is_null() {
+                if yaml_emitter_analyze_anchor(emitter, (*event).data.scalar.anchor, false).fail {
+                    return FAIL;
+                }
+            }
+            if !(*event).data.scalar.tag.is_null()
+                && ((*emitter).canonical
+                    || !(*event).data.scalar.plain_implicit
+                        && !(*event).data.scalar.quoted_implicit)
+            {
+                if yaml_emitter_analyze_tag(emitter, (*event).data.scalar.tag).fail {
+                    return FAIL;
+                }
+            }
+            yaml_emitter_analyze_scalar(
+                emitter,
+                (*event).data.scalar.value,
+                (*event).data.scalar.length,
+            )
+        }
+        YAML_SEQUENCE_START_EVENT => {
+            if !(*event).data.sequence_start.anchor.is_null() {
+                if yaml_emitter_analyze_anchor(emitter, (*event).data.sequence_start.anchor, false)
+                    .fail
+                {
+                    return FAIL;
+                }
+            }
+            if !(*event).data.sequence_start.tag.is_null()
+                && ((*emitter).canonical || !(*event).data.sequence_start.implicit)
+            {
+                if yaml_emitter_analyze_tag(emitter, (*event).data.sequence_start.tag).fail {
+                    return FAIL;
+                }
+            }
+            OK
+        }
+        YAML_MAPPING_START_EVENT => {
+            if !(*event).data.mapping_start.anchor.is_null() {
+                if yaml_emitter_analyze_anchor(emitter, (*event).data.mapping_start.anchor, false)
+                    .fail
+                {
+                    return FAIL;
+                }
+            }
+            if !(*event).data.mapping_start.tag.is_null()
+                && ((*emitter).canonical || !(*event).data.mapping_start.implicit)
+            {
+                if yaml_emitter_analyze_tag(emitter, (*event).data.mapping_start.tag).fail {
+                    return FAIL;
+                }
+            }
+            OK
+        }
+        _ => OK,
+    }
+}
+
+unsafe fn yaml_emitter_write_bom(emitter: *mut yaml_emitter_t) -> Success {
+    if FLUSH(emitter).fail {
+        return FAIL;
+    }
+    let fresh56 = addr_of_mut!((*emitter).buffer.pointer);
+    let fresh57 = *fresh56;
+    *fresh56 = (*fresh56).wrapping_offset(1);
+    *fresh57 = b'\xEF';
+    let fresh58 = addr_of_mut!((*emitter).buffer.pointer);
+    let fresh59 = *fresh58;
+    *fresh58 = (*fresh58).wrapping_offset(1);
+    *fresh59 = b'\xBB';
+    let fresh60 = addr_of_mut!((*emitter).buffer.pointer);
+    let fresh61 = *fresh60;
+    *fresh60 = (*fresh60).wrapping_offset(1);
+    *fresh61 = b'\xBF';
+    OK
+}
+
+unsafe fn yaml_emitter_write_indent(emitter: *mut yaml_emitter_t) -> Success {
+    let indent: libc::c_int = if (*emitter).indent >= 0 {
+        (*emitter).indent
+    } else {
+        0
+    };
+    if !(*emitter).indention
+        || (*emitter).column > indent
+        || (*emitter).column == indent && !(*emitter).whitespace
+    {
+        if PUT_BREAK(emitter).fail {
+            return FAIL;
+        }
+    }
+    while (*emitter).column < indent {
+        if PUT(emitter, b' ').fail {
+            return FAIL;
+        }
+    }
+    (*emitter).whitespace = true;
+    (*emitter).indention = true;
+    OK
+}
+
+unsafe fn yaml_emitter_write_indicator(
+    emitter: *mut yaml_emitter_t,
+    indicator: *const libc::c_char,
+    need_whitespace: bool,
+    is_whitespace: bool,
+    is_indention: bool,
+) -> Success {
+    let indicator_length: size_t = strlen(indicator);
+    let mut string = STRING_ASSIGN!(indicator as *mut yaml_char_t, indicator_length);
+    if need_whitespace && !(*emitter).whitespace {
+        if PUT(emitter, b' ').fail {
+            return FAIL;
+        }
+    }
+    while string.pointer != string.end {
+        if WRITE!(emitter, string).fail {
+            return FAIL;
+        }
+    }
+    (*emitter).whitespace = is_whitespace;
+    (*emitter).indention = (*emitter).indention && is_indention;
+    OK
+}
+
+unsafe fn yaml_emitter_write_anchor(
+    emitter: *mut yaml_emitter_t,
+    value: *mut yaml_char_t,
+    length: size_t,
+) -> Success {
+    let mut string = STRING_ASSIGN!(value, length);
+    while string.pointer != string.end {
+        if WRITE!(emitter, string).fail {
+            return FAIL;
+        }
+    }
+    (*emitter).whitespace = false;
+    (*emitter).indention = false;
+    OK
+}
+
+unsafe fn yaml_emitter_write_tag_handle(
+    emitter: *mut yaml_emitter_t,
+    value: *mut yaml_char_t,
+    length: size_t,
+) -> Success {
+    let mut string = STRING_ASSIGN!(value, length);
+    if !(*emitter).whitespace {
+        if PUT(emitter, b' ').fail {
+            return FAIL;
+        }
+    }
+    while string.pointer != string.end {
+        if WRITE!(emitter, string).fail {
+            return FAIL;
+        }
+    }
+    (*emitter).whitespace = false;
+    (*emitter).indention = false;
+    OK
+}
+
+unsafe fn yaml_emitter_write_tag_content(
+    emitter: *mut yaml_emitter_t,
+    value: *mut yaml_char_t,
+    length: size_t,
+    need_whitespace: bool,
+) -> Success {
+    let mut string = STRING_ASSIGN!(value, length);
+    if need_whitespace && !(*emitter).whitespace {
+        if PUT(emitter, b' ').fail {
+            return FAIL;
+        }
+    }
+    while string.pointer != string.end {
+        if IS_ALPHA!(string)
+            || CHECK!(string, b';')
+            || CHECK!(string, b'/')
+            || CHECK!(string, b'?')
+            || CHECK!(string, b':')
+            || CHECK!(string, b'@')
+            || CHECK!(string, b'&')
+            || CHECK!(string, b'=')
+            || CHECK!(string, b'+')
+            || CHECK!(string, b'$')
+            || CHECK!(string, b',')
+            || CHECK!(string, b'_')
+            || CHECK!(string, b'.')
+            || CHECK!(string, b'~')
+            || CHECK!(string, b'*')
+            || CHECK!(string, b'\'')
+            || CHECK!(string, b'(')
+            || CHECK!(string, b')')
+            || CHECK!(string, b'[')
+            || CHECK!(string, b']')
+        {
+            if WRITE!(emitter, string).fail {
+                return FAIL;
+            }
+        } else {
+            let mut width = WIDTH!(string);
+            loop {
+                let fresh207 = width;
+                width -= 1;
+                if !(fresh207 != 0) {
+                    break;
+                }
+                let fresh208 = string.pointer;
+                string.pointer = string.pointer.wrapping_offset(1);
+                let value = *fresh208;
+                if PUT(emitter, b'%').fail {
+                    return FAIL;
+                }
+                if PUT(
+                    emitter,
+                    (value >> 4).wrapping_add(if (value >> 4) < 10 { b'0' } else { b'A' - 10 }),
+                )
+                .fail
+                {
+                    return FAIL;
+                }
+                if PUT(
+                    emitter,
+                    (value & 0x0F).wrapping_add(if (value & 0x0F) < 10 { b'0' } else { b'A' - 10 }),
+                )
+                .fail
+                {
+                    return FAIL;
+                }
+            }
+        }
+    }
+    (*emitter).whitespace = false;
+    (*emitter).indention = false;
+    OK
+}
+
+unsafe fn yaml_emitter_write_plain_scalar(
+    emitter: *mut yaml_emitter_t,
+    value: *mut yaml_char_t,
+    length: size_t,
+    allow_breaks: bool,
+) -> Success {
+    let mut spaces = false;
+    let mut breaks = false;
+    let mut string = STRING_ASSIGN!(value, length);
+    if !(*emitter).whitespace && (length != 0 || (*emitter).flow_level != 0) {
+        if PUT(emitter, b' ').fail {
+            return FAIL;
+        }
+    }
+    while string.pointer != string.end {
+        if IS_SPACE!(string) {
+            if allow_breaks
+                && !spaces
+                && (*emitter).column > (*emitter).best_width
+                && !IS_SPACE_AT!(string, 1)
+            {
+                if yaml_emitter_write_indent(emitter).fail {
+                    return FAIL;
+                }
+                MOVE!(string);
+            } else if WRITE!(emitter, string).fail {
+                return FAIL;
+            }
+            spaces = true;
+        } else if IS_BREAK!(string) {
+            if !breaks && CHECK!(string, b'\n') {
+                if PUT_BREAK(emitter).fail {
+                    return FAIL;
+                }
+            }
+            if WRITE_BREAK!(emitter, string).fail {
+                return FAIL;
+            }
+            (*emitter).indention = true;
+            breaks = true;
+        } else {
+            if breaks {
+                if yaml_emitter_write_indent(emitter).fail {
+                    return FAIL;
+                }
+            }
+            if WRITE!(emitter, string).fail {
+                return FAIL;
+            }
+            (*emitter).indention = false;
+            spaces = false;
+            breaks = false;
+        }
+    }
+    (*emitter).whitespace = false;
+    (*emitter).indention = false;
+    OK
+}
+
+unsafe fn yaml_emitter_write_single_quoted_scalar(
+    emitter: *mut yaml_emitter_t,
+    value: *mut yaml_char_t,
+    length: size_t,
+    allow_breaks: bool,
+) -> Success {
+    let mut spaces = false;
+    let mut breaks = false;
+    let mut string = STRING_ASSIGN!(value, length);
+    if yaml_emitter_write_indicator(
+        emitter,
+        b"'\0" as *const u8 as *const libc::c_char,
+        true,
+        false,
+        false,
+    )
+    .fail
+    {
+        return FAIL;
+    }
+    while string.pointer != string.end {
+        if IS_SPACE!(string) {
+            if allow_breaks
+                && !spaces
+                && (*emitter).column > (*emitter).best_width
+                && string.pointer != string.start
+                && string.pointer != string.end.wrapping_offset(-1_isize)
+                && !IS_SPACE_AT!(string, 1)
+            {
+                if yaml_emitter_write_indent(emitter).fail {
+                    return FAIL;
+                }
+                MOVE!(string);
+            } else if WRITE!(emitter, string).fail {
+                return FAIL;
+            }
+            spaces = true;
+        } else if IS_BREAK!(string) {
+            if !breaks && CHECK!(string, b'\n') {
+                if PUT_BREAK(emitter).fail {
+                    return FAIL;
+                }
+            }
+            if WRITE_BREAK!(emitter, string).fail {
+                return FAIL;
+            }
+            (*emitter).indention = true;
+            breaks = true;
+        } else {
+            if breaks {
+                if yaml_emitter_write_indent(emitter).fail {
+                    return FAIL;
+                }
+            }
+            if CHECK!(string, b'\'') {
+                if PUT(emitter, b'\'').fail {
+                    return FAIL;
+                }
+            }
+            if WRITE!(emitter, string).fail {
+                return FAIL;
+            }
+            (*emitter).indention = false;
+            spaces = false;
+            breaks = false;
+        }
+    }
+    if breaks {
+        if yaml_emitter_write_indent(emitter).fail {
+            return FAIL;
+        }
+    }
+    if yaml_emitter_write_indicator(
+        emitter,
+        b"'\0" as *const u8 as *const libc::c_char,
+        false,
+        false,
+        false,
+    )
+    .fail
+    {
+        return FAIL;
+    }
+    (*emitter).whitespace = false;
+    (*emitter).indention = false;
+    OK
+}
+
+unsafe fn yaml_emitter_write_double_quoted_scalar(
+    emitter: *mut yaml_emitter_t,
+    value: *mut yaml_char_t,
+    length: size_t,
+    allow_breaks: bool,
+) -> Success {
+    let mut spaces = false;
+    let mut string = STRING_ASSIGN!(value, length);
+    if yaml_emitter_write_indicator(
+        emitter,
+        b"\"\0" as *const u8 as *const libc::c_char,
+        true,
+        false,
+        false,
+    )
+    .fail
+    {
+        return FAIL;
+    }
+    while string.pointer != string.end {
+        if !IS_PRINTABLE!(string)
+            || !(*emitter).unicode && !IS_ASCII!(string)
+            || IS_BOM!(string)
+            || IS_BREAK!(string)
+            || CHECK!(string, b'"')
+            || CHECK!(string, b'\\')
+        {
+            let mut octet: libc::c_uchar;
+            let mut width: libc::c_uint;
+            let mut value_0: libc::c_uint;
+            let mut k: libc::c_int;
+            octet = *string.pointer;
+            width = if octet & 0x80 == 0x00 {
+                1
+            } else if octet & 0xE0 == 0xC0 {
+                2
+            } else if octet & 0xF0 == 0xE0 {
+                3
+            } else if octet & 0xF8 == 0xF0 {
+                4
+            } else {
+                0
+            };
+            value_0 = if octet & 0x80 == 0 {
+                octet & 0x7F
+            } else if octet & 0xE0 == 0xC0 {
+                octet & 0x1F
+            } else if octet & 0xF0 == 0xE0 {
+                octet & 0x0F
+            } else if octet & 0xF8 == 0xF0 {
+                octet & 0x07
+            } else {
+                0
+            } as libc::c_uint;
+            k = 1;
+            while k < width as libc::c_int {
+                octet = *string.pointer.wrapping_offset(k as isize);
+                value_0 = (value_0 << 6).wrapping_add((octet & 0x3F) as libc::c_uint);
+                k += 1;
+            }
+            string.pointer = string.pointer.wrapping_offset(width as isize);
+            if PUT(emitter, b'\\').fail {
+                return FAIL;
+            }
+            match value_0 {
+                0x00 => {
+                    if PUT(emitter, b'0').fail {
+                        return FAIL;
+                    }
+                }
+                0x07 => {
+                    if PUT(emitter, b'a').fail {
+                        return FAIL;
+                    }
+                }
+                0x08 => {
+                    if PUT(emitter, b'b').fail {
+                        return FAIL;
+                    }
+                }
+                0x09 => {
+                    if PUT(emitter, b't').fail {
+                        return FAIL;
+                    }
+                }
+                0x0A => {
+                    if PUT(emitter, b'n').fail {
+                        return FAIL;
+                    }
+                }
+                0x0B => {
+                    if PUT(emitter, b'v').fail {
+                        return FAIL;
+                    }
+                }
+                0x0C => {
+                    if PUT(emitter, b'f').fail {
+                        return FAIL;
+                    }
+                }
+                0x0D => {
+                    if PUT(emitter, b'r').fail {
+                        return FAIL;
+                    }
+                }
+                0x1B => {
+                    if PUT(emitter, b'e').fail {
+                        return FAIL;
+                    }
+                }
+                0x22 => {
+                    if PUT(emitter, b'"').fail {
+                        return FAIL;
+                    }
+                }
+                0x5C => {
+                    if PUT(emitter, b'\\').fail {
+                        return FAIL;
+                    }
+                }
+                0x85 => {
+                    if PUT(emitter, b'N').fail {
+                        return FAIL;
+                    }
+                }
+                0xA0 => {
+                    if PUT(emitter, b'_').fail {
+                        return FAIL;
+                    }
+                }
+                0x2028 => {
+                    if PUT(emitter, b'L').fail {
+                        return FAIL;
+                    }
+                }
+                0x2029 => {
+                    if PUT(emitter, b'P').fail {
+                        return FAIL;
+                    }
+                }
+                _ => {
+                    if value_0 <= 0xFF {
+                        if PUT(emitter, b'x').fail {
+                            return FAIL;
+                        }
+                        width = 2;
+                    } else if value_0 <= 0xFFFF {
+                        if PUT(emitter, b'u').fail {
+                            return FAIL;
+                        }
+                        width = 4;
+                    } else {
+                        if PUT(emitter, b'U').fail {
+                            return FAIL;
+                        }
+                        width = 8;
+                    }
+                    k = width.wrapping_sub(1).wrapping_mul(4) as libc::c_int;
+                    while k >= 0 {
+                        let digit: libc::c_int = (value_0 >> k & 0x0F) as libc::c_int;
+                        if PUT(
+                            emitter,
+                            (digit + if digit < 10 { b'0' } else { b'A' - 10 } as i32) as u8,
+                        )
+                        .fail
+                        {
+                            return FAIL;
+                        }
+                        k -= 4;
+                    }
+                }
+            }
+            spaces = false;
+        } else if IS_SPACE!(string) {
+            if allow_breaks
+                && !spaces
+                && (*emitter).column > (*emitter).best_width
+                && string.pointer != string.start
+                && string.pointer != string.end.wrapping_offset(-1_isize)
+            {
+                if yaml_emitter_write_indent(emitter).fail {
+                    return FAIL;
+                }
+                if IS_SPACE_AT!(string, 1) {
+                    if PUT(emitter, b'\\').fail {
+                        return FAIL;
+                    }
+                }
+                MOVE!(string);
+            } else if WRITE!(emitter, string).fail {
+                return FAIL;
+            }
+            spaces = true;
+        } else {
+            if WRITE!(emitter, string).fail {
+                return FAIL;
+            }
+            spaces = false;
+        }
+    }
+    if yaml_emitter_write_indicator(
+        emitter,
+        b"\"\0" as *const u8 as *const libc::c_char,
+        false,
+        false,
+        false,
+    )
+    .fail
+    {
+        return FAIL;
+    }
+    (*emitter).whitespace = false;
+    (*emitter).indention = false;
+    OK
+}
+
+unsafe fn yaml_emitter_write_block_scalar_hints(
+    emitter: *mut yaml_emitter_t,
+    mut string: yaml_string_t,
+) -> Success {
+    let mut indent_hint: [libc::c_char; 2] = [0; 2];
+    let mut chomp_hint: *const libc::c_char = ptr::null::<libc::c_char>();
+    if IS_SPACE!(string) || IS_BREAK!(string) {
+        indent_hint[0] = (b'0' as libc::c_int + (*emitter).best_indent) as libc::c_char;
+        indent_hint[1] = '\0' as libc::c_char;
+        if yaml_emitter_write_indicator(emitter, indent_hint.as_mut_ptr(), false, false, false).fail
+        {
+            return FAIL;
+        }
+    }
+    (*emitter).open_ended = 0;
+    string.pointer = string.end;
+    if string.start == string.pointer {
+        chomp_hint = b"-\0" as *const u8 as *const libc::c_char;
+    } else {
+        loop {
+            string.pointer = string.pointer.wrapping_offset(-1);
+            if !(*string.pointer & 0xC0 == 0x80) {
+                break;
+            }
+        }
+        if !IS_BREAK!(string) {
+            chomp_hint = b"-\0" as *const u8 as *const libc::c_char;
+        } else if string.start == string.pointer {
+            chomp_hint = b"+\0" as *const u8 as *const libc::c_char;
+            (*emitter).open_ended = 2;
+        } else {
+            loop {
+                string.pointer = string.pointer.wrapping_offset(-1);
+                if !(*string.pointer & 0xC0 == 0x80) {
+                    break;
+                }
+            }
+            if IS_BREAK!(string) {
+                chomp_hint = b"+\0" as *const u8 as *const libc::c_char;
+                (*emitter).open_ended = 2;
+            }
+        }
+    }
+    if !chomp_hint.is_null() {
+        if yaml_emitter_write_indicator(emitter, chomp_hint, false, false, false).fail {
+            return FAIL;
+        }
+    }
+    OK
+}
+
+unsafe fn yaml_emitter_write_literal_scalar(
+    emitter: *mut yaml_emitter_t,
+    value: *mut yaml_char_t,
+    length: size_t,
+) -> Success {
+    let mut breaks = true;
+    let mut string = STRING_ASSIGN!(value, length);
+    if yaml_emitter_write_indicator(
+        emitter,
+        b"|\0" as *const u8 as *const libc::c_char,
+        true,
+        false,
+        false,
+    )
+    .fail
+    {
+        return FAIL;
+    }
+    if yaml_emitter_write_block_scalar_hints(emitter, string).fail {
+        return FAIL;
+    }
+    if PUT_BREAK(emitter).fail {
+        return FAIL;
+    }
+    (*emitter).indention = true;
+    (*emitter).whitespace = true;
+    while string.pointer != string.end {
+        if IS_BREAK!(string) {
+            if WRITE_BREAK!(emitter, string).fail {
+                return FAIL;
+            }
+            (*emitter).indention = true;
+            breaks = true;
+        } else {
+            if breaks {
+                if yaml_emitter_write_indent(emitter).fail {
+                    return FAIL;
+                }
+            }
+            if WRITE!(emitter, string).fail {
+                return FAIL;
+            }
+            (*emitter).indention = false;
+            breaks = false;
+        }
+    }
+    OK
+}
+
+unsafe fn yaml_emitter_write_folded_scalar(
+    emitter: *mut yaml_emitter_t,
+    value: *mut yaml_char_t,
+    length: size_t,
+) -> Success {
+    let mut breaks = true;
+    let mut leading_spaces = true;
+    let mut string = STRING_ASSIGN!(value, length);
+    if yaml_emitter_write_indicator(
+        emitter,
+        b">\0" as *const u8 as *const libc::c_char,
+        true,
+        false,
+        false,
+    )
+    .fail
+    {
+        return FAIL;
+    }
+    if yaml_emitter_write_block_scalar_hints(emitter, string).fail {
+        return FAIL;
+    }
+    if PUT_BREAK(emitter).fail {
+        return FAIL;
+    }
+    (*emitter).indention = true;
+    (*emitter).whitespace = true;
+    while string.pointer != string.end {
+        if IS_BREAK!(string) {
+            if !breaks && !leading_spaces && CHECK!(string, b'\n') {
+                let mut k: libc::c_int = 0;
+                while IS_BREAK_AT!(string, k as isize) {
+                    k += WIDTH_AT!(string, k as isize);
+                }
+                if !IS_BLANKZ_AT!(string, k) {
+                    if PUT_BREAK(emitter).fail {
+                        return FAIL;
+                    }
+                }
+            }
+            if WRITE_BREAK!(emitter, string).fail {
+                return FAIL;
+            }
+            (*emitter).indention = true;
+            breaks = true;
+        } else {
+            if breaks {
+                if yaml_emitter_write_indent(emitter).fail {
+                    return FAIL;
+                }
+                leading_spaces = IS_BLANK!(string);
+            }
+            if !breaks
+                && IS_SPACE!(string)
+                && !IS_SPACE_AT!(string, 1)
+                && (*emitter).column > (*emitter).best_width
+            {
+                if yaml_emitter_write_indent(emitter).fail {
+                    return FAIL;
+                }
+                MOVE!(string);
+            } else if WRITE!(emitter, string).fail {
+                return FAIL;
+            }
+            (*emitter).indention = false;
+            breaks = false;
+        }
+    }
+    OK
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..aece24d
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,307 @@
+//! [![github]](https://github.com/dtolnay/unsafe-libyaml)&ensp;[![crates-io]](https://crates.io/crates/unsafe-libyaml)&ensp;[![docs-rs]](https://docs.rs/unsafe-libyaml)
+//!
+//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
+
+#![no_std]
+#![doc(html_root_url = "https://docs.rs/unsafe-libyaml/0.2.9")]
+#![allow(non_camel_case_types, non_snake_case)]
+#![warn(clippy::pedantic)]
+#![allow(
+    clippy::bool_to_int_with_if,
+    clippy::cast_lossless,
+    clippy::cast_possible_truncation,
+    clippy::cast_possible_wrap,
+    clippy::cast_ptr_alignment,
+    clippy::cast_sign_loss,
+    clippy::collapsible_if,
+    clippy::doc_markdown,
+    clippy::fn_params_excessive_bools,
+    clippy::if_not_else,
+    clippy::items_after_statements,
+    clippy::let_underscore_untyped,
+    clippy::manual_range_contains,
+    clippy::manual_swap,
+    clippy::missing_panics_doc,
+    clippy::missing_safety_doc,
+    clippy::module_name_repetitions,
+    clippy::must_use_candidate,
+    clippy::nonminimal_bool,
+    clippy::ptr_as_ptr,
+    clippy::redundant_else,
+    clippy::similar_names,
+    clippy::single_match,
+    clippy::single_match_else,
+    clippy::too_many_arguments,
+    clippy::too_many_lines,
+    clippy::unnecessary_cast,
+    clippy::unreadable_literal,
+    clippy::while_immutable_condition, // https://github.com/rust-lang/rust-clippy/issues/3548
+)]
+
+extern crate alloc;
+
+use core::mem::size_of;
+
+mod libc {
+    pub use core::ffi::c_void;
+    pub use core::primitive::{
+        i32 as c_int, i64 as c_long, i8 as c_char, i8 as c_schar, u16 as c_ushort, u32 as c_uint,
+        u64 as c_ulong, u8 as c_uchar,
+    };
+}
+
+#[macro_use]
+mod externs {
+    use crate::libc;
+    use alloc::alloc::{self as rust, Layout};
+    use core::mem::{self, MaybeUninit};
+    use core::ptr;
+    use core::slice;
+
+    const HEADER: usize = mem::size_of::<usize>();
+
+    // `max_align_t` may be bigger than this, but libyaml does not use `long
+    // double` or u128.
+    const MALLOC_ALIGN: usize = mem::align_of::<usize>();
+
+    pub unsafe fn malloc(size: libc::c_ulong) -> *mut libc::c_void {
+        let size = HEADER + size as usize;
+        let layout = Layout::from_size_align_unchecked(size, MALLOC_ALIGN);
+        let memory = rust::alloc(layout);
+        if memory.is_null() {
+            rust::handle_alloc_error(layout);
+        }
+        memory.cast::<usize>().write(size);
+        memory.add(HEADER).cast()
+    }
+
+    pub unsafe fn realloc(ptr: *mut libc::c_void, new_size: libc::c_ulong) -> *mut libc::c_void {
+        let mut memory = ptr.cast::<u8>().sub(HEADER);
+        let size = memory.cast::<usize>().read();
+        let layout = Layout::from_size_align_unchecked(size, MALLOC_ALIGN);
+        let new_size = HEADER + new_size as usize;
+        memory = rust::realloc(memory, layout, new_size);
+        if memory.is_null() {
+            let layout = Layout::from_size_align_unchecked(new_size, MALLOC_ALIGN);
+            rust::handle_alloc_error(layout);
+        }
+        memory.cast::<usize>().write(new_size);
+        memory.add(HEADER).cast()
+    }
+
+    pub unsafe fn free(ptr: *mut libc::c_void) {
+        let memory = ptr.cast::<u8>().sub(HEADER);
+        let size = memory.cast::<usize>().read();
+        let layout = Layout::from_size_align_unchecked(size, MALLOC_ALIGN);
+        rust::dealloc(memory, layout);
+    }
+
+    pub unsafe fn memcmp(
+        lhs: *const libc::c_void,
+        rhs: *const libc::c_void,
+        count: libc::c_ulong,
+    ) -> libc::c_int {
+        let lhs = slice::from_raw_parts(lhs.cast::<u8>(), count as usize);
+        let rhs = slice::from_raw_parts(rhs.cast::<u8>(), count as usize);
+        lhs.cmp(rhs) as libc::c_int
+    }
+
+    pub unsafe fn memcpy(
+        dest: *mut libc::c_void,
+        src: *const libc::c_void,
+        count: libc::c_ulong,
+    ) -> *mut libc::c_void {
+        ptr::copy_nonoverlapping(
+            src.cast::<MaybeUninit<u8>>(),
+            dest.cast::<MaybeUninit<u8>>(),
+            count as usize,
+        );
+        dest
+    }
+
+    pub unsafe fn memmove(
+        dest: *mut libc::c_void,
+        src: *const libc::c_void,
+        count: libc::c_ulong,
+    ) -> *mut libc::c_void {
+        ptr::copy(
+            src.cast::<MaybeUninit<u8>>(),
+            dest.cast::<MaybeUninit<u8>>(),
+            count as usize,
+        );
+        dest
+    }
+
+    pub unsafe fn memset(
+        dest: *mut libc::c_void,
+        ch: libc::c_int,
+        count: libc::c_ulong,
+    ) -> *mut libc::c_void {
+        ptr::write_bytes(dest.cast::<u8>(), ch as u8, count as usize);
+        dest
+    }
+
+    pub unsafe fn strcmp(lhs: *const libc::c_char, rhs: *const libc::c_char) -> libc::c_int {
+        let lhs = slice::from_raw_parts(lhs.cast::<u8>(), strlen(lhs) as usize);
+        let rhs = slice::from_raw_parts(rhs.cast::<u8>(), strlen(rhs) as usize);
+        lhs.cmp(rhs) as libc::c_int
+    }
+
+    pub unsafe fn strdup(src: *const libc::c_char) -> *mut libc::c_char {
+        let len = strlen(src);
+        let dest = malloc(len + 1);
+        memcpy(dest, src.cast(), len + 1);
+        dest.cast()
+    }
+
+    pub unsafe fn strlen(str: *const libc::c_char) -> libc::c_ulong {
+        let mut end = str;
+        while *end != 0 {
+            end = end.add(1);
+        }
+        end.offset_from(str) as libc::c_ulong
+    }
+
+    pub unsafe fn strncmp(
+        lhs: *const libc::c_char,
+        rhs: *const libc::c_char,
+        mut count: libc::c_ulong,
+    ) -> libc::c_int {
+        let mut lhs = lhs.cast::<u8>();
+        let mut rhs = rhs.cast::<u8>();
+        while count > 0 && *lhs != 0 && *lhs == *rhs {
+            lhs = lhs.add(1);
+            rhs = rhs.add(1);
+            count -= 1;
+        }
+        if count == 0 {
+            0
+        } else {
+            (*lhs).cmp(&*rhs) as libc::c_int
+        }
+    }
+
+    macro_rules! __assert {
+        (false $(,)?) => {
+            $crate::externs::__assert_fail(stringify!(false), file!(), line!())
+        };
+        ($assertion:expr $(,)?) => {
+            if !$assertion {
+                $crate::externs::__assert_fail(stringify!($assertion), file!(), line!());
+            }
+        };
+    }
+
+    pub(crate) unsafe fn __assert_fail(
+        __assertion: &'static str,
+        __file: &'static str,
+        __line: u32,
+    ) -> ! {
+        struct Abort;
+        impl Drop for Abort {
+            fn drop(&mut self) {
+                panic!();
+            }
+        }
+        let _abort_on_panic = Abort;
+        panic!("{}:{}: Assertion `{}` failed.", __file, __line, __assertion);
+    }
+}
+
+mod fmt {
+    use crate::yaml::yaml_char_t;
+    use core::fmt::{self, Write};
+    use core::ptr;
+
+    pub struct WriteToPtr {
+        ptr: *mut yaml_char_t,
+    }
+
+    impl WriteToPtr {
+        pub unsafe fn new(ptr: *mut yaml_char_t) -> Self {
+            WriteToPtr { ptr }
+        }
+
+        pub fn write_fmt(&mut self, args: fmt::Arguments) {
+            let _ = Write::write_fmt(self, args);
+        }
+    }
+
+    impl Write for WriteToPtr {
+        fn write_str(&mut self, s: &str) -> fmt::Result {
+            unsafe {
+                ptr::copy_nonoverlapping(s.as_ptr(), self.ptr, s.len());
+                self.ptr = self.ptr.add(s.len());
+            }
+            Ok(())
+        }
+    }
+}
+
+trait PointerExt: Sized {
+    fn c_offset_from(self, origin: Self) -> isize;
+}
+
+impl<T> PointerExt for *const T {
+    fn c_offset_from(self, origin: *const T) -> isize {
+        (self as isize - origin as isize) / size_of::<T>() as isize
+    }
+}
+
+impl<T> PointerExt for *mut T {
+    fn c_offset_from(self, origin: *mut T) -> isize {
+        (self as isize - origin as isize) / size_of::<T>() as isize
+    }
+}
+
+#[macro_use]
+mod macros;
+
+mod api;
+mod dumper;
+mod emitter;
+mod loader;
+mod parser;
+mod reader;
+mod scanner;
+mod success;
+mod writer;
+mod yaml;
+
+pub use crate::api::{
+    yaml_alias_event_initialize, yaml_document_add_mapping, yaml_document_add_scalar,
+    yaml_document_add_sequence, yaml_document_append_mapping_pair,
+    yaml_document_append_sequence_item, yaml_document_delete, yaml_document_end_event_initialize,
+    yaml_document_get_node, yaml_document_get_root_node, yaml_document_initialize,
+    yaml_document_start_event_initialize, yaml_emitter_delete, yaml_emitter_initialize,
+    yaml_emitter_set_break, yaml_emitter_set_canonical, yaml_emitter_set_encoding,
+    yaml_emitter_set_indent, yaml_emitter_set_output, yaml_emitter_set_output_string,
+    yaml_emitter_set_unicode, yaml_emitter_set_width, yaml_event_delete,
+    yaml_mapping_end_event_initialize, yaml_mapping_start_event_initialize, yaml_parser_delete,
+    yaml_parser_initialize, yaml_parser_set_encoding, yaml_parser_set_input,
+    yaml_parser_set_input_string, yaml_scalar_event_initialize, yaml_sequence_end_event_initialize,
+    yaml_sequence_start_event_initialize, yaml_stream_end_event_initialize,
+    yaml_stream_start_event_initialize, yaml_token_delete,
+};
+pub use crate::dumper::{yaml_emitter_close, yaml_emitter_dump, yaml_emitter_open};
+pub use crate::emitter::yaml_emitter_emit;
+pub use crate::loader::yaml_parser_load;
+pub use crate::parser::yaml_parser_parse;
+pub use crate::scanner::yaml_parser_scan;
+pub use crate::writer::yaml_emitter_flush;
+pub use crate::yaml::{
+    yaml_alias_data_t, yaml_break_t, yaml_document_t, yaml_emitter_state_t, yaml_emitter_t,
+    yaml_encoding_t, yaml_error_type_t, yaml_event_t, yaml_event_type_t, yaml_mapping_style_t,
+    yaml_mark_t, yaml_node_item_t, yaml_node_pair_t, yaml_node_t, yaml_node_type_t,
+    yaml_parser_state_t, yaml_parser_t, yaml_read_handler_t, yaml_scalar_style_t,
+    yaml_sequence_style_t, yaml_simple_key_t, yaml_stack_t, yaml_tag_directive_t, yaml_token_t,
+    yaml_token_type_t, yaml_version_directive_t, yaml_write_handler_t,
+};
+#[doc(hidden)]
+pub use crate::yaml::{
+    yaml_break_t::*, yaml_emitter_state_t::*, yaml_encoding_t::*, yaml_error_type_t::*,
+    yaml_event_type_t::*, yaml_mapping_style_t::*, yaml_node_type_t::*, yaml_parser_state_t::*,
+    yaml_scalar_style_t::*, yaml_sequence_style_t::*, yaml_token_type_t::*,
+};
diff --git a/src/loader.rs b/src/loader.rs
new file mode 100644
index 0000000..6d562c0
--- /dev/null
+++ b/src/loader.rs
@@ -0,0 +1,579 @@
+use crate::api::{yaml_free, yaml_malloc, yaml_stack_extend, yaml_strdup};
+use crate::externs::{memset, strcmp};
+use crate::success::{Success, FAIL, OK};
+use crate::yaml::yaml_char_t;
+use crate::{
+    libc, yaml_alias_data_t, yaml_document_delete, yaml_document_t, yaml_event_t, yaml_mark_t,
+    yaml_node_item_t, yaml_node_pair_t, yaml_node_t, yaml_parser_parse, yaml_parser_t, PointerExt,
+    YAML_ALIAS_EVENT, YAML_COMPOSER_ERROR, YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_START_EVENT,
+    YAML_MAPPING_END_EVENT, YAML_MAPPING_NODE, YAML_MAPPING_START_EVENT, YAML_MEMORY_ERROR,
+    YAML_SCALAR_EVENT, YAML_SCALAR_NODE, YAML_SEQUENCE_END_EVENT, YAML_SEQUENCE_NODE,
+    YAML_SEQUENCE_START_EVENT, YAML_STREAM_END_EVENT, YAML_STREAM_START_EVENT,
+};
+use core::mem::{size_of, MaybeUninit};
+use core::ptr::{self, addr_of_mut};
+
+#[repr(C)]
+struct loader_ctx {
+    start: *mut libc::c_int,
+    end: *mut libc::c_int,
+    top: *mut libc::c_int,
+}
+
+/// 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.
+pub unsafe fn yaml_parser_load(
+    parser: *mut yaml_parser_t,
+    document: *mut yaml_document_t,
+) -> Success {
+    let current_block: u64;
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    __assert!(!parser.is_null());
+    __assert!(!document.is_null());
+    memset(
+        document as *mut libc::c_void,
+        0,
+        size_of::<yaml_document_t>() as libc::c_ulong,
+    );
+    STACK_INIT!((*document).nodes, yaml_node_t);
+    if !(*parser).stream_start_produced {
+        if yaml_parser_parse(parser, event).fail {
+            current_block = 6234624449317607669;
+        } else {
+            __assert!((*event).type_ == YAML_STREAM_START_EVENT);
+            current_block = 7815301370352969686;
+        }
+    } else {
+        current_block = 7815301370352969686;
+    }
+    if current_block != 6234624449317607669 {
+        if (*parser).stream_end_produced {
+            return OK;
+        }
+        if yaml_parser_parse(parser, event).ok {
+            if (*event).type_ == YAML_STREAM_END_EVENT {
+                return OK;
+            }
+            STACK_INIT!((*parser).aliases, yaml_alias_data_t);
+            let fresh6 = addr_of_mut!((*parser).document);
+            *fresh6 = document;
+            if yaml_parser_load_document(parser, event).ok {
+                yaml_parser_delete_aliases(parser);
+                let fresh7 = addr_of_mut!((*parser).document);
+                *fresh7 = ptr::null_mut::<yaml_document_t>();
+                return OK;
+            }
+        }
+    }
+    yaml_parser_delete_aliases(parser);
+    yaml_document_delete(document);
+    let fresh8 = addr_of_mut!((*parser).document);
+    *fresh8 = ptr::null_mut::<yaml_document_t>();
+    FAIL
+}
+
+unsafe fn yaml_parser_set_composer_error(
+    parser: *mut yaml_parser_t,
+    problem: *const libc::c_char,
+    problem_mark: yaml_mark_t,
+) -> Success {
+    (*parser).error = YAML_COMPOSER_ERROR;
+    let fresh9 = addr_of_mut!((*parser).problem);
+    *fresh9 = problem;
+    (*parser).problem_mark = problem_mark;
+    FAIL
+}
+
+unsafe fn yaml_parser_set_composer_error_context(
+    parser: *mut yaml_parser_t,
+    context: *const libc::c_char,
+    context_mark: yaml_mark_t,
+    problem: *const libc::c_char,
+    problem_mark: yaml_mark_t,
+) -> Success {
+    (*parser).error = YAML_COMPOSER_ERROR;
+    let fresh10 = addr_of_mut!((*parser).context);
+    *fresh10 = context;
+    (*parser).context_mark = context_mark;
+    let fresh11 = addr_of_mut!((*parser).problem);
+    *fresh11 = problem;
+    (*parser).problem_mark = problem_mark;
+    FAIL
+}
+
+unsafe fn yaml_parser_delete_aliases(parser: *mut yaml_parser_t) {
+    while !STACK_EMPTY!((*parser).aliases) {
+        yaml_free(POP!((*parser).aliases).anchor as *mut libc::c_void);
+    }
+    STACK_DEL!((*parser).aliases);
+}
+
+unsafe fn yaml_parser_load_document(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let mut ctx = loader_ctx {
+        start: ptr::null_mut::<libc::c_int>(),
+        end: ptr::null_mut::<libc::c_int>(),
+        top: ptr::null_mut::<libc::c_int>(),
+    };
+    __assert!((*event).type_ == YAML_DOCUMENT_START_EVENT);
+    let fresh16 = addr_of_mut!((*(*parser).document).version_directive);
+    *fresh16 = (*event).data.document_start.version_directive;
+    let fresh17 = addr_of_mut!((*(*parser).document).tag_directives.start);
+    *fresh17 = (*event).data.document_start.tag_directives.start;
+    let fresh18 = addr_of_mut!((*(*parser).document).tag_directives.end);
+    *fresh18 = (*event).data.document_start.tag_directives.end;
+    (*(*parser).document).start_implicit = (*event).data.document_start.implicit;
+    (*(*parser).document).start_mark = (*event).start_mark;
+    STACK_INIT!(ctx, libc::c_int);
+    if yaml_parser_load_nodes(parser, addr_of_mut!(ctx)).fail {
+        STACK_DEL!(ctx);
+        return FAIL;
+    }
+    STACK_DEL!(ctx);
+    OK
+}
+
+unsafe fn yaml_parser_load_nodes(parser: *mut yaml_parser_t, ctx: *mut loader_ctx) -> Success {
+    let mut event = MaybeUninit::<yaml_event_t>::uninit();
+    let event = event.as_mut_ptr();
+    loop {
+        if yaml_parser_parse(parser, event).fail {
+            return FAIL;
+        }
+        match (*event).type_ {
+            YAML_ALIAS_EVENT => {
+                if yaml_parser_load_alias(parser, event, ctx).fail {
+                    return FAIL;
+                }
+            }
+            YAML_SCALAR_EVENT => {
+                if yaml_parser_load_scalar(parser, event, ctx).fail {
+                    return FAIL;
+                }
+            }
+            YAML_SEQUENCE_START_EVENT => {
+                if yaml_parser_load_sequence(parser, event, ctx).fail {
+                    return FAIL;
+                }
+            }
+            YAML_SEQUENCE_END_EVENT => {
+                if yaml_parser_load_sequence_end(parser, event, ctx).fail {
+                    return FAIL;
+                }
+            }
+            YAML_MAPPING_START_EVENT => {
+                if yaml_parser_load_mapping(parser, event, ctx).fail {
+                    return FAIL;
+                }
+            }
+            YAML_MAPPING_END_EVENT => {
+                if yaml_parser_load_mapping_end(parser, event, ctx).fail {
+                    return FAIL;
+                }
+            }
+            YAML_DOCUMENT_END_EVENT => {}
+            _ => {
+                __assert!(false);
+            }
+        }
+        if (*event).type_ == YAML_DOCUMENT_END_EVENT {
+            break;
+        }
+    }
+    (*(*parser).document).end_implicit = (*event).data.document_end.implicit;
+    (*(*parser).document).end_mark = (*event).end_mark;
+    OK
+}
+
+unsafe fn yaml_parser_register_anchor(
+    parser: *mut yaml_parser_t,
+    index: libc::c_int,
+    anchor: *mut yaml_char_t,
+) -> Success {
+    let mut data = MaybeUninit::<yaml_alias_data_t>::uninit();
+    let data = data.as_mut_ptr();
+    let mut alias_data: *mut yaml_alias_data_t;
+    if anchor.is_null() {
+        return OK;
+    }
+    (*data).anchor = anchor;
+    (*data).index = index;
+    (*data).mark = (*(*(*parser).document)
+        .nodes
+        .start
+        .wrapping_offset((index - 1) as isize))
+    .start_mark;
+    alias_data = (*parser).aliases.start;
+    while alias_data != (*parser).aliases.top {
+        if strcmp(
+            (*alias_data).anchor as *mut libc::c_char,
+            anchor as *mut libc::c_char,
+        ) == 0
+        {
+            yaml_free(anchor as *mut libc::c_void);
+            return yaml_parser_set_composer_error_context(
+                parser,
+                b"found duplicate anchor; first occurrence\0" as *const u8 as *const libc::c_char,
+                (*alias_data).mark,
+                b"second occurrence\0" as *const u8 as *const libc::c_char,
+                (*data).mark,
+            );
+        }
+        alias_data = alias_data.wrapping_offset(1);
+    }
+    PUSH!((*parser).aliases, *data);
+    OK
+}
+
+unsafe fn yaml_parser_load_node_add(
+    parser: *mut yaml_parser_t,
+    ctx: *mut loader_ctx,
+    index: libc::c_int,
+) -> Success {
+    if STACK_EMPTY!(*ctx) {
+        return OK;
+    }
+    let parent_index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
+    let parent: *mut yaml_node_t = addr_of_mut!(
+        *((*(*parser).document).nodes.start).wrapping_offset((parent_index - 1) as isize)
+    );
+    let current_block_17: u64;
+    match (*parent).type_ {
+        YAML_SEQUENCE_NODE => {
+            if STACK_LIMIT!(parser, (*parent).data.sequence.items).fail {
+                return FAIL;
+            }
+            PUSH!((*parent).data.sequence.items, index);
+        }
+        YAML_MAPPING_NODE => {
+            let mut pair = MaybeUninit::<yaml_node_pair_t>::uninit();
+            let pair = pair.as_mut_ptr();
+            if !STACK_EMPTY!((*parent).data.mapping.pairs) {
+                let p: *mut yaml_node_pair_t =
+                    (*parent).data.mapping.pairs.top.wrapping_offset(-1_isize);
+                if (*p).key != 0 && (*p).value == 0 {
+                    (*p).value = index;
+                    current_block_17 = 11307063007268554308;
+                } else {
+                    current_block_17 = 17407779659766490442;
+                }
+            } else {
+                current_block_17 = 17407779659766490442;
+            }
+            match current_block_17 {
+                11307063007268554308 => {}
+                _ => {
+                    (*pair).key = index;
+                    (*pair).value = 0;
+                    if STACK_LIMIT!(parser, (*parent).data.mapping.pairs).fail {
+                        return FAIL;
+                    }
+                    PUSH!((*parent).data.mapping.pairs, *pair);
+                }
+            }
+        }
+        _ => {
+            __assert!(false);
+        }
+    }
+    OK
+}
+
+unsafe fn yaml_parser_load_alias(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    ctx: *mut loader_ctx,
+) -> Success {
+    let anchor: *mut yaml_char_t = (*event).data.alias.anchor;
+    let mut alias_data: *mut yaml_alias_data_t;
+    alias_data = (*parser).aliases.start;
+    while alias_data != (*parser).aliases.top {
+        if strcmp(
+            (*alias_data).anchor as *mut libc::c_char,
+            anchor as *mut libc::c_char,
+        ) == 0
+        {
+            yaml_free(anchor as *mut libc::c_void);
+            return yaml_parser_load_node_add(parser, ctx, (*alias_data).index);
+        }
+        alias_data = alias_data.wrapping_offset(1);
+    }
+    yaml_free(anchor as *mut libc::c_void);
+    yaml_parser_set_composer_error(
+        parser,
+        b"found undefined alias\0" as *const u8 as *const libc::c_char,
+        (*event).start_mark,
+    )
+}
+
+unsafe fn yaml_parser_load_scalar(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    ctx: *mut loader_ctx,
+) -> Success {
+    let current_block: u64;
+    let mut node = MaybeUninit::<yaml_node_t>::uninit();
+    let node = node.as_mut_ptr();
+    let index: libc::c_int;
+    let mut tag: *mut yaml_char_t = (*event).data.scalar.tag;
+    if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
+        if tag.is_null()
+            || strcmp(
+                tag as *mut libc::c_char,
+                b"!\0" as *const u8 as *const libc::c_char,
+            ) == 0
+        {
+            yaml_free(tag as *mut libc::c_void);
+            tag = yaml_strdup(
+                b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
+            );
+            if tag.is_null() {
+                current_block = 10579931339944277179;
+            } else {
+                current_block = 11006700562992250127;
+            }
+        } else {
+            current_block = 11006700562992250127;
+        }
+        if current_block != 10579931339944277179 {
+            memset(
+                node as *mut libc::c_void,
+                0,
+                size_of::<yaml_node_t>() as libc::c_ulong,
+            );
+            (*node).type_ = YAML_SCALAR_NODE;
+            (*node).tag = tag;
+            (*node).start_mark = (*event).start_mark;
+            (*node).end_mark = (*event).end_mark;
+            (*node).data.scalar.value = (*event).data.scalar.value;
+            (*node).data.scalar.length = (*event).data.scalar.length;
+            (*node).data.scalar.style = (*event).data.scalar.style;
+            PUSH!((*(*parser).document).nodes, *node);
+            index = (*(*parser).document)
+                .nodes
+                .top
+                .c_offset_from((*(*parser).document).nodes.start)
+                as libc::c_int;
+            if yaml_parser_register_anchor(parser, index, (*event).data.scalar.anchor).fail {
+                return FAIL;
+            }
+            return yaml_parser_load_node_add(parser, ctx, index);
+        }
+    }
+    yaml_free(tag as *mut libc::c_void);
+    yaml_free((*event).data.scalar.anchor as *mut libc::c_void);
+    yaml_free((*event).data.scalar.value as *mut libc::c_void);
+    FAIL
+}
+
+unsafe fn yaml_parser_load_sequence(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    ctx: *mut loader_ctx,
+) -> Success {
+    let current_block: u64;
+    let mut node = MaybeUninit::<yaml_node_t>::uninit();
+    let node = node.as_mut_ptr();
+    struct Items {
+        start: *mut yaml_node_item_t,
+        end: *mut yaml_node_item_t,
+        top: *mut yaml_node_item_t,
+    }
+    let mut items = Items {
+        start: ptr::null_mut::<yaml_node_item_t>(),
+        end: ptr::null_mut::<yaml_node_item_t>(),
+        top: ptr::null_mut::<yaml_node_item_t>(),
+    };
+    let index: libc::c_int;
+    let mut tag: *mut yaml_char_t = (*event).data.sequence_start.tag;
+    if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
+        if tag.is_null()
+            || strcmp(
+                tag as *mut libc::c_char,
+                b"!\0" as *const u8 as *const libc::c_char,
+            ) == 0
+        {
+            yaml_free(tag as *mut libc::c_void);
+            tag = yaml_strdup(
+                b"tag:yaml.org,2002:seq\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
+            );
+            if tag.is_null() {
+                current_block = 13474536459355229096;
+            } else {
+                current_block = 6937071982253665452;
+            }
+        } else {
+            current_block = 6937071982253665452;
+        }
+        if current_block != 13474536459355229096 {
+            STACK_INIT!(items, yaml_node_item_t);
+            memset(
+                node as *mut libc::c_void,
+                0,
+                size_of::<yaml_node_t>() as libc::c_ulong,
+            );
+            (*node).type_ = YAML_SEQUENCE_NODE;
+            (*node).tag = tag;
+            (*node).start_mark = (*event).start_mark;
+            (*node).end_mark = (*event).end_mark;
+            (*node).data.sequence.items.start = items.start;
+            (*node).data.sequence.items.end = items.end;
+            (*node).data.sequence.items.top = items.start;
+            (*node).data.sequence.style = (*event).data.sequence_start.style;
+            PUSH!((*(*parser).document).nodes, *node);
+            index = (*(*parser).document)
+                .nodes
+                .top
+                .c_offset_from((*(*parser).document).nodes.start)
+                as libc::c_int;
+            if yaml_parser_register_anchor(parser, index, (*event).data.sequence_start.anchor).fail
+            {
+                return FAIL;
+            }
+            if yaml_parser_load_node_add(parser, ctx, index).fail {
+                return FAIL;
+            }
+            if STACK_LIMIT!(parser, *ctx).fail {
+                return FAIL;
+            }
+            PUSH!(*ctx, index);
+            return OK;
+        }
+    }
+    yaml_free(tag as *mut libc::c_void);
+    yaml_free((*event).data.sequence_start.anchor as *mut libc::c_void);
+    FAIL
+}
+
+unsafe fn yaml_parser_load_sequence_end(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    ctx: *mut loader_ctx,
+) -> Success {
+    __assert!(((*ctx).top).c_offset_from((*ctx).start) as libc::c_long > 0_i64);
+    let index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
+    __assert!(
+        (*((*(*parser).document).nodes.start).wrapping_offset((index - 1) as isize)).type_
+            == YAML_SEQUENCE_NODE
+    );
+    (*(*(*parser).document)
+        .nodes
+        .start
+        .wrapping_offset((index - 1) as isize))
+    .end_mark = (*event).end_mark;
+    let _ = POP!(*ctx);
+    OK
+}
+
+unsafe fn yaml_parser_load_mapping(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    ctx: *mut loader_ctx,
+) -> Success {
+    let current_block: u64;
+    let mut node = MaybeUninit::<yaml_node_t>::uninit();
+    let node = node.as_mut_ptr();
+    struct Pairs {
+        start: *mut yaml_node_pair_t,
+        end: *mut yaml_node_pair_t,
+        top: *mut yaml_node_pair_t,
+    }
+    let mut pairs = Pairs {
+        start: ptr::null_mut::<yaml_node_pair_t>(),
+        end: ptr::null_mut::<yaml_node_pair_t>(),
+        top: ptr::null_mut::<yaml_node_pair_t>(),
+    };
+    let index: libc::c_int;
+    let mut tag: *mut yaml_char_t = (*event).data.mapping_start.tag;
+    if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
+        if tag.is_null()
+            || strcmp(
+                tag as *mut libc::c_char,
+                b"!\0" as *const u8 as *const libc::c_char,
+            ) == 0
+        {
+            yaml_free(tag as *mut libc::c_void);
+            tag = yaml_strdup(
+                b"tag:yaml.org,2002:map\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
+            );
+            if tag.is_null() {
+                current_block = 13635467803606088781;
+            } else {
+                current_block = 6937071982253665452;
+            }
+        } else {
+            current_block = 6937071982253665452;
+        }
+        if current_block != 13635467803606088781 {
+            STACK_INIT!(pairs, yaml_node_pair_t);
+            memset(
+                node as *mut libc::c_void,
+                0,
+                size_of::<yaml_node_t>() as libc::c_ulong,
+            );
+            (*node).type_ = YAML_MAPPING_NODE;
+            (*node).tag = tag;
+            (*node).start_mark = (*event).start_mark;
+            (*node).end_mark = (*event).end_mark;
+            (*node).data.mapping.pairs.start = pairs.start;
+            (*node).data.mapping.pairs.end = pairs.end;
+            (*node).data.mapping.pairs.top = pairs.start;
+            (*node).data.mapping.style = (*event).data.mapping_start.style;
+            PUSH!((*(*parser).document).nodes, *node);
+            index = (*(*parser).document)
+                .nodes
+                .top
+                .c_offset_from((*(*parser).document).nodes.start)
+                as libc::c_int;
+            if yaml_parser_register_anchor(parser, index, (*event).data.mapping_start.anchor).fail {
+                return FAIL;
+            }
+            if yaml_parser_load_node_add(parser, ctx, index).fail {
+                return FAIL;
+            }
+            if STACK_LIMIT!(parser, *ctx).fail {
+                return FAIL;
+            }
+            PUSH!(*ctx, index);
+            return OK;
+        }
+    }
+    yaml_free(tag as *mut libc::c_void);
+    yaml_free((*event).data.mapping_start.anchor as *mut libc::c_void);
+    FAIL
+}
+
+unsafe fn yaml_parser_load_mapping_end(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    ctx: *mut loader_ctx,
+) -> Success {
+    __assert!(((*ctx).top).c_offset_from((*ctx).start) as libc::c_long > 0_i64);
+    let index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
+    __assert!(
+        (*((*(*parser).document).nodes.start).wrapping_offset((index - 1) as isize)).type_
+            == YAML_MAPPING_NODE
+    );
+    (*(*(*parser).document)
+        .nodes
+        .start
+        .wrapping_offset((index - 1) as isize))
+    .end_mark = (*event).end_mark;
+    let _ = POP!(*ctx);
+    OK
+}
diff --git a/src/macros.rs b/src/macros.rs
new file mode 100644
index 0000000..9668929
--- /dev/null
+++ b/src/macros.rs
@@ -0,0 +1,514 @@
+macro_rules! BUFFER_INIT {
+    ($buffer:expr, $size:expr) => {{
+        let start = addr_of_mut!($buffer.start);
+        *start = yaml_malloc($size as size_t) as *mut yaml_char_t;
+        let pointer = addr_of_mut!($buffer.pointer);
+        *pointer = $buffer.start;
+        let last = addr_of_mut!($buffer.last);
+        *last = *pointer;
+        let end = addr_of_mut!($buffer.end);
+        *end = $buffer.start.wrapping_add($size as usize);
+    }};
+}
+
+macro_rules! BUFFER_DEL {
+    ($buffer:expr) => {{
+        yaml_free($buffer.start as *mut libc::c_void);
+        let end = addr_of_mut!($buffer.end);
+        *end = ptr::null_mut::<yaml_char_t>();
+        let pointer = addr_of_mut!($buffer.pointer);
+        *pointer = *end;
+        let start = addr_of_mut!($buffer.start);
+        *start = *pointer;
+    }};
+}
+
+macro_rules! STRING_ASSIGN {
+    ($string:expr, $length:expr) => {
+        yaml_string_t {
+            start: $string,
+            end: $string.wrapping_offset($length as isize),
+            pointer: $string,
+        }
+    };
+}
+
+macro_rules! STRING_INIT {
+    ($string:expr) => {{
+        $string.start = yaml_malloc(16) as *mut yaml_char_t;
+        $string.pointer = $string.start;
+        $string.end = $string.start.wrapping_add(16);
+        memset($string.start as *mut libc::c_void, 0, 16);
+    }};
+}
+
+macro_rules! STRING_DEL {
+    ($string:expr) => {{
+        yaml_free($string.start as *mut libc::c_void);
+        $string.end = ptr::null_mut::<yaml_char_t>();
+        $string.pointer = $string.end;
+        $string.start = $string.pointer;
+    }};
+}
+
+macro_rules! STRING_EXTEND {
+    ($string:expr) => {
+        if $string.pointer.wrapping_add(5) >= $string.end {
+            yaml_string_extend(
+                addr_of_mut!($string.start),
+                addr_of_mut!($string.pointer),
+                addr_of_mut!($string.end),
+            );
+        }
+    };
+}
+
+macro_rules! CLEAR {
+    ($string:expr) => {{
+        $string.pointer = $string.start;
+        memset(
+            $string.start as *mut libc::c_void,
+            0,
+            $string.end.c_offset_from($string.start) as libc::c_ulong,
+        );
+    }};
+}
+
+macro_rules! JOIN {
+    ($string_a:expr, $string_b:expr) => {{
+        yaml_string_join(
+            addr_of_mut!($string_a.start),
+            addr_of_mut!($string_a.pointer),
+            addr_of_mut!($string_a.end),
+            addr_of_mut!($string_b.start),
+            addr_of_mut!($string_b.pointer),
+            addr_of_mut!($string_b.end),
+        );
+        $string_b.pointer = $string_b.start;
+    }};
+}
+
+macro_rules! CHECK_AT {
+    ($string:expr, $octet:expr, $offset:expr) => {
+        *$string.pointer.offset($offset as isize) == $octet
+    };
+}
+
+macro_rules! CHECK {
+    ($string:expr, $octet:expr) => {
+        *$string.pointer == $octet
+    };
+}
+
+macro_rules! IS_ALPHA {
+    ($string:expr) => {
+        *$string.pointer >= b'0' && *$string.pointer <= b'9'
+            || *$string.pointer >= b'A' && *$string.pointer <= b'Z'
+            || *$string.pointer >= b'a' && *$string.pointer <= b'z'
+            || *$string.pointer == b'_'
+            || *$string.pointer == b'-'
+    };
+}
+
+macro_rules! IS_DIGIT {
+    ($string:expr) => {
+        *$string.pointer >= b'0' && *$string.pointer <= b'9'
+    };
+}
+
+macro_rules! AS_DIGIT {
+    ($string:expr) => {
+        (*$string.pointer - b'0') as libc::c_int
+    };
+}
+
+macro_rules! IS_HEX_AT {
+    ($string:expr, $offset:expr) => {
+        *$string.pointer.wrapping_offset($offset) >= b'0'
+            && *$string.pointer.wrapping_offset($offset) <= b'9'
+            || *$string.pointer.wrapping_offset($offset) >= b'A'
+                && *$string.pointer.wrapping_offset($offset) <= b'F'
+            || *$string.pointer.wrapping_offset($offset) >= b'a'
+                && *$string.pointer.wrapping_offset($offset) <= b'f'
+    };
+}
+
+macro_rules! AS_HEX_AT {
+    ($string:expr, $offset:expr) => {
+        if *$string.pointer.wrapping_offset($offset) >= b'A'
+            && *$string.pointer.wrapping_offset($offset) <= b'F'
+        {
+            *$string.pointer.wrapping_offset($offset) - b'A' + 10
+        } else if *$string.pointer.wrapping_offset($offset) >= b'a'
+            && *$string.pointer.wrapping_offset($offset) <= b'f'
+        {
+            *$string.pointer.wrapping_offset($offset) - b'a' + 10
+        } else {
+            *$string.pointer.wrapping_offset($offset) - b'0'
+        } as libc::c_int
+    };
+}
+
+macro_rules! IS_ASCII {
+    ($string:expr) => {
+        *$string.pointer <= b'\x7F'
+    };
+}
+
+macro_rules! IS_PRINTABLE {
+    ($string:expr) => {
+        match *$string.pointer {
+            // ASCII
+            0x0A | 0x20..=0x7E => true,
+            // U+A0 ... U+BF
+            0xC2 => match *$string.pointer.wrapping_offset(1) {
+                0xA0..=0xBF => true,
+                _ => false,
+            },
+            // U+C0 ... U+CFFF
+            0xC3..=0xEC => true,
+            // U+D000 ... U+D7FF
+            0xED => match *$string.pointer.wrapping_offset(1) {
+                0x00..=0x9F => true,
+                _ => false,
+            },
+            // U+E000 ... U+EFFF
+            0xEE => true,
+            // U+F000 ... U+FFFD
+            0xEF => match *$string.pointer.wrapping_offset(1) {
+                0xBB => match *$string.pointer.wrapping_offset(2) {
+                    // except U+FEFF
+                    0xBF => false,
+                    _ => true,
+                },
+                0xBF => match *$string.pointer.wrapping_offset(2) {
+                    0xBE | 0xBF => false,
+                    _ => true,
+                },
+                _ => true,
+            },
+            // U+10000 ... U+10FFFF
+            0xF0..=0xF4 => true,
+            _ => false,
+        }
+    };
+}
+
+macro_rules! IS_Z_AT {
+    ($string:expr, $offset:expr) => {
+        CHECK_AT!($string, b'\0', $offset)
+    };
+}
+
+macro_rules! IS_Z {
+    ($string:expr) => {
+        IS_Z_AT!($string, 0)
+    };
+}
+
+macro_rules! IS_BOM {
+    ($string:expr) => {
+        CHECK_AT!($string, b'\xEF', 0)
+            && CHECK_AT!($string, b'\xBB', 1)
+            && CHECK_AT!($string, b'\xBF', 2)
+    };
+}
+
+macro_rules! IS_SPACE_AT {
+    ($string:expr, $offset:expr) => {
+        CHECK_AT!($string, b' ', $offset)
+    };
+}
+
+macro_rules! IS_SPACE {
+    ($string:expr) => {
+        IS_SPACE_AT!($string, 0)
+    };
+}
+
+macro_rules! IS_TAB_AT {
+    ($string:expr, $offset:expr) => {
+        CHECK_AT!($string, b'\t', $offset)
+    };
+}
+
+macro_rules! IS_TAB {
+    ($string:expr) => {
+        IS_TAB_AT!($string, 0)
+    };
+}
+
+macro_rules! IS_BLANK_AT {
+    ($string:expr, $offset:expr) => {
+        IS_SPACE_AT!($string, $offset) || IS_TAB_AT!($string, $offset)
+    };
+}
+
+macro_rules! IS_BLANK {
+    ($string:expr) => {
+        IS_BLANK_AT!($string, 0)
+    };
+}
+
+macro_rules! IS_BREAK_AT {
+    ($string:expr, $offset:expr) => {
+        CHECK_AT!($string, b'\r', $offset)
+            || CHECK_AT!($string, b'\n', $offset)
+            || CHECK_AT!($string, b'\xC2', $offset) && CHECK_AT!($string, b'\x85', $offset + 1)
+            || CHECK_AT!($string, b'\xE2', $offset)
+                && CHECK_AT!($string, b'\x80', $offset + 1)
+                && CHECK_AT!($string, b'\xA8', $offset + 2)
+            || CHECK_AT!($string, b'\xE2', $offset)
+                && CHECK_AT!($string, b'\x80', $offset + 1)
+                && CHECK_AT!($string, b'\xA9', $offset + 2)
+    };
+}
+
+macro_rules! IS_BREAK {
+    ($string:expr) => {
+        IS_BREAK_AT!($string, 0)
+    };
+}
+
+macro_rules! IS_CRLF {
+    ($string:expr) => {
+        CHECK_AT!($string, b'\r', 0) && CHECK_AT!($string, b'\n', 1)
+    };
+}
+
+macro_rules! IS_BREAKZ_AT {
+    ($string:expr, $offset:expr) => {
+        IS_BREAK_AT!($string, $offset) || IS_Z_AT!($string, $offset)
+    };
+}
+
+macro_rules! IS_BREAKZ {
+    ($string:expr) => {
+        IS_BREAKZ_AT!($string, 0)
+    };
+}
+
+macro_rules! IS_BLANKZ_AT {
+    ($string:expr, $offset:expr) => {
+        IS_BLANK_AT!($string, $offset) || IS_BREAKZ_AT!($string, $offset)
+    };
+}
+
+macro_rules! IS_BLANKZ {
+    ($string:expr) => {
+        IS_BLANKZ_AT!($string, 0)
+    };
+}
+
+macro_rules! WIDTH_AT {
+    ($string:expr, $offset:expr) => {
+        if *$string.pointer.wrapping_offset($offset as isize) & 0x80 == 0x00 {
+            1
+        } else if *$string.pointer.wrapping_offset($offset as isize) & 0xE0 == 0xC0 {
+            2
+        } else if *$string.pointer.wrapping_offset($offset as isize) & 0xF0 == 0xE0 {
+            3
+        } else if *$string.pointer.wrapping_offset($offset as isize) & 0xF8 == 0xF0 {
+            4
+        } else {
+            0
+        }
+    };
+}
+
+macro_rules! WIDTH {
+    ($string:expr) => {
+        WIDTH_AT!($string, 0)
+    };
+}
+
+macro_rules! MOVE {
+    ($string:expr) => {
+        $string.pointer = $string.pointer.wrapping_offset(WIDTH!($string) as isize)
+    };
+}
+
+macro_rules! COPY {
+    ($string_a:expr, $string_b:expr) => {
+        if *$string_b.pointer & 0x80 == 0x00 {
+            *$string_a.pointer = *$string_b.pointer;
+            $string_a.pointer = $string_a.pointer.wrapping_offset(1);
+            $string_b.pointer = $string_b.pointer.wrapping_offset(1);
+        } else if *$string_b.pointer & 0xE0 == 0xC0 {
+            *$string_a.pointer = *$string_b.pointer;
+            $string_a.pointer = $string_a.pointer.wrapping_offset(1);
+            $string_b.pointer = $string_b.pointer.wrapping_offset(1);
+            *$string_a.pointer = *$string_b.pointer;
+            $string_a.pointer = $string_a.pointer.wrapping_offset(1);
+            $string_b.pointer = $string_b.pointer.wrapping_offset(1);
+        } else if *$string_b.pointer & 0xF0 == 0xE0 {
+            *$string_a.pointer = *$string_b.pointer;
+            $string_a.pointer = $string_a.pointer.wrapping_offset(1);
+            $string_b.pointer = $string_b.pointer.wrapping_offset(1);
+            *$string_a.pointer = *$string_b.pointer;
+            $string_a.pointer = $string_a.pointer.wrapping_offset(1);
+            $string_b.pointer = $string_b.pointer.wrapping_offset(1);
+            *$string_a.pointer = *$string_b.pointer;
+            $string_a.pointer = $string_a.pointer.wrapping_offset(1);
+            $string_b.pointer = $string_b.pointer.wrapping_offset(1);
+        } else if *$string_b.pointer & 0xF8 == 0xF0 {
+            *$string_a.pointer = *$string_b.pointer;
+            $string_a.pointer = $string_a.pointer.wrapping_offset(1);
+            $string_b.pointer = $string_b.pointer.wrapping_offset(1);
+            *$string_a.pointer = *$string_b.pointer;
+            $string_a.pointer = $string_a.pointer.wrapping_offset(1);
+            $string_b.pointer = $string_b.pointer.wrapping_offset(1);
+            *$string_a.pointer = *$string_b.pointer;
+            $string_a.pointer = $string_a.pointer.wrapping_offset(1);
+            $string_b.pointer = $string_b.pointer.wrapping_offset(1);
+            *$string_a.pointer = *$string_b.pointer;
+            $string_a.pointer = $string_a.pointer.wrapping_offset(1);
+            $string_b.pointer = $string_b.pointer.wrapping_offset(1);
+        }
+    };
+}
+
+macro_rules! STACK_INIT {
+    ($stack:expr, $type:ty) => {{
+        $stack.start = yaml_malloc(16 * size_of::<$type>() as libc::c_ulong) as *mut $type;
+        $stack.top = $stack.start;
+        $stack.end = $stack.start.offset(16_isize);
+    }};
+}
+
+macro_rules! STACK_DEL {
+    ($stack:expr) => {
+        yaml_free($stack.start as *mut libc::c_void);
+        $stack.end = ptr::null_mut();
+        $stack.top = ptr::null_mut();
+        $stack.start = ptr::null_mut();
+    };
+}
+
+macro_rules! STACK_EMPTY {
+    ($stack:expr) => {
+        $stack.start == $stack.top
+    };
+}
+
+macro_rules! STACK_LIMIT {
+    ($context:expr, $stack:expr) => {
+        if $stack.top.c_offset_from($stack.start) < libc::c_int::MAX as isize - 1 {
+            OK
+        } else {
+            (*$context).error = YAML_MEMORY_ERROR;
+            FAIL
+        }
+    };
+}
+
+macro_rules! PUSH {
+    (do $stack:expr, $push:expr) => {{
+        if $stack.top == $stack.end {
+            yaml_stack_extend(
+                addr_of_mut!($stack.start) as *mut *mut libc::c_void,
+                addr_of_mut!($stack.top) as *mut *mut libc::c_void,
+                addr_of_mut!($stack.end) as *mut *mut libc::c_void,
+            );
+        }
+        $push;
+        $stack.top = $stack.top.wrapping_offset(1);
+    }};
+    ($stack:expr, *$value:expr) => {
+        PUSH!(do $stack, ptr::copy_nonoverlapping($value, $stack.top, 1))
+    };
+    ($stack:expr, $value:expr) => {
+        PUSH!(do $stack, ptr::write($stack.top, $value))
+    };
+}
+
+macro_rules! POP {
+    ($stack:expr) => {
+        *{
+            $stack.top = $stack.top.offset(-1);
+            $stack.top
+        }
+    };
+}
+
+macro_rules! QUEUE_INIT {
+    ($queue:expr, $type:ty) => {{
+        $queue.start = yaml_malloc(16 * size_of::<$type>() as libc::c_ulong) as *mut $type;
+        $queue.tail = $queue.start;
+        $queue.head = $queue.tail;
+        $queue.end = $queue.start.offset(16_isize);
+    }};
+}
+
+macro_rules! QUEUE_DEL {
+    ($queue:expr) => {
+        yaml_free($queue.start as *mut libc::c_void);
+        $queue.end = ptr::null_mut();
+        $queue.tail = ptr::null_mut();
+        $queue.head = ptr::null_mut();
+        $queue.start = ptr::null_mut();
+    };
+}
+
+macro_rules! QUEUE_EMPTY {
+    ($queue:expr) => {
+        $queue.head == $queue.tail
+    };
+}
+
+macro_rules! ENQUEUE {
+    (do $queue:expr, $enqueue:expr) => {{
+        if $queue.tail == $queue.end {
+            yaml_queue_extend(
+                addr_of_mut!($queue.start) as *mut *mut libc::c_void,
+                addr_of_mut!($queue.head) as *mut *mut libc::c_void,
+                addr_of_mut!($queue.tail) as *mut *mut libc::c_void,
+                addr_of_mut!($queue.end) as *mut *mut libc::c_void,
+            );
+        }
+        $enqueue;
+        $queue.tail = $queue.tail.wrapping_offset(1);
+    }};
+    ($queue:expr, *$value:expr) => {
+        ENQUEUE!(do $queue, ptr::copy_nonoverlapping($value, $queue.tail, 1))
+    };
+    ($queue:expr, $value:expr) => {
+        ENQUEUE!(do $queue, ptr::write($queue.tail, $value))
+    };
+}
+
+macro_rules! DEQUEUE {
+    ($queue:expr) => {
+        *{
+            let head = $queue.head;
+            $queue.head = $queue.head.wrapping_offset(1);
+            head
+        }
+    };
+}
+
+macro_rules! QUEUE_INSERT {
+    ($queue:expr, $index:expr, $value:expr) => {{
+        if $queue.tail == $queue.end {
+            yaml_queue_extend(
+                addr_of_mut!($queue.start) as *mut *mut libc::c_void,
+                addr_of_mut!($queue.head) as *mut *mut libc::c_void,
+                addr_of_mut!($queue.tail) as *mut *mut libc::c_void,
+                addr_of_mut!($queue.end) as *mut *mut libc::c_void,
+            );
+        }
+        memmove(
+            $queue
+                .head
+                .wrapping_offset($index as isize)
+                .wrapping_offset(1_isize) as *mut libc::c_void,
+            $queue.head.wrapping_offset($index as isize) as *const libc::c_void,
+            ($queue.tail.c_offset_from($queue.head) as libc::c_ulong)
+                .wrapping_sub($index)
+                .wrapping_mul(size_of::<yaml_token_t>() as libc::c_ulong),
+        );
+        *$queue.head.wrapping_offset($index as isize) = $value;
+        let fresh14 = addr_of_mut!($queue.tail);
+        *fresh14 = (*fresh14).wrapping_offset(1);
+    }};
+}
diff --git a/src/parser.rs b/src/parser.rs
new file mode 100644
index 0000000..c4f4f35
--- /dev/null
+++ b/src/parser.rs
@@ -0,0 +1,1353 @@
+use crate::api::{yaml_free, yaml_malloc, yaml_stack_extend, yaml_strdup};
+use crate::externs::{memcpy, memset, strcmp, strlen};
+use crate::scanner::yaml_parser_fetch_more_tokens;
+use crate::success::{Success, FAIL, OK};
+use crate::yaml::{size_t, yaml_char_t};
+use crate::{
+    libc, yaml_event_t, yaml_mark_t, yaml_parser_t, yaml_tag_directive_t, yaml_token_t,
+    yaml_version_directive_t, YAML_ALIAS_EVENT, YAML_ALIAS_TOKEN, YAML_ANCHOR_TOKEN,
+    YAML_BLOCK_END_TOKEN, YAML_BLOCK_ENTRY_TOKEN, YAML_BLOCK_MAPPING_START_TOKEN,
+    YAML_BLOCK_MAPPING_STYLE, YAML_BLOCK_SEQUENCE_START_TOKEN, YAML_BLOCK_SEQUENCE_STYLE,
+    YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_END_TOKEN, YAML_DOCUMENT_START_EVENT,
+    YAML_DOCUMENT_START_TOKEN, YAML_FLOW_ENTRY_TOKEN, YAML_FLOW_MAPPING_END_TOKEN,
+    YAML_FLOW_MAPPING_START_TOKEN, YAML_FLOW_MAPPING_STYLE, YAML_FLOW_SEQUENCE_END_TOKEN,
+    YAML_FLOW_SEQUENCE_START_TOKEN, YAML_FLOW_SEQUENCE_STYLE, YAML_KEY_TOKEN,
+    YAML_MAPPING_END_EVENT, YAML_MAPPING_START_EVENT, YAML_NO_ERROR, YAML_PARSER_ERROR,
+    YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE, YAML_PARSE_BLOCK_MAPPING_KEY_STATE,
+    YAML_PARSE_BLOCK_MAPPING_VALUE_STATE, YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE,
+    YAML_PARSE_BLOCK_NODE_STATE, YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE,
+    YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE, YAML_PARSE_DOCUMENT_CONTENT_STATE,
+    YAML_PARSE_DOCUMENT_END_STATE, YAML_PARSE_DOCUMENT_START_STATE, YAML_PARSE_END_STATE,
+    YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE, YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE,
+    YAML_PARSE_FLOW_MAPPING_KEY_STATE, YAML_PARSE_FLOW_MAPPING_VALUE_STATE,
+    YAML_PARSE_FLOW_NODE_STATE, YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE,
+    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE,
+    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE, YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE,
+    YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE, YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE,
+    YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE, YAML_PARSE_STREAM_START_STATE,
+    YAML_PLAIN_SCALAR_STYLE, YAML_SCALAR_EVENT, YAML_SCALAR_TOKEN, YAML_SEQUENCE_END_EVENT,
+    YAML_SEQUENCE_START_EVENT, YAML_STREAM_END_EVENT, YAML_STREAM_END_TOKEN,
+    YAML_STREAM_START_EVENT, YAML_STREAM_START_TOKEN, YAML_TAG_DIRECTIVE_TOKEN, YAML_TAG_TOKEN,
+    YAML_VALUE_TOKEN, YAML_VERSION_DIRECTIVE_TOKEN,
+};
+use core::mem::size_of;
+use core::ptr::{self, addr_of_mut};
+
+unsafe fn PEEK_TOKEN(parser: *mut yaml_parser_t) -> *mut yaml_token_t {
+    if (*parser).token_available || yaml_parser_fetch_more_tokens(parser).ok {
+        (*parser).tokens.head
+    } else {
+        ptr::null_mut::<yaml_token_t>()
+    }
+}
+
+unsafe fn SKIP_TOKEN(parser: *mut yaml_parser_t) {
+    (*parser).token_available = false;
+    let fresh3 = addr_of_mut!((*parser).tokens_parsed);
+    *fresh3 = (*fresh3).wrapping_add(1);
+    (*parser).stream_end_produced = (*(*parser).tokens.head).type_ == YAML_STREAM_END_TOKEN;
+    let fresh4 = addr_of_mut!((*parser).tokens.head);
+    *fresh4 = (*fresh4).wrapping_offset(1);
+}
+
+/// Parse the input stream and produce the next parsing event.
+///
+/// Call the function subsequently to produce a sequence of events corresponding
+/// to the input stream. The initial event has the type YAML_STREAM_START_EVENT
+/// while the ending event has the type YAML_STREAM_END_EVENT.
+///
+/// An application is responsible for freeing any buffers associated with the
+/// produced event object using the yaml_event_delete() function.
+///
+/// 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.
+pub unsafe fn yaml_parser_parse(parser: *mut yaml_parser_t, event: *mut yaml_event_t) -> Success {
+    __assert!(!parser.is_null());
+    __assert!(!event.is_null());
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    if (*parser).stream_end_produced
+        || (*parser).error != YAML_NO_ERROR
+        || (*parser).state == YAML_PARSE_END_STATE
+    {
+        return OK;
+    }
+    yaml_parser_state_machine(parser, event)
+}
+
+unsafe fn yaml_parser_set_parser_error(
+    parser: *mut yaml_parser_t,
+    problem: *const libc::c_char,
+    problem_mark: yaml_mark_t,
+) {
+    (*parser).error = YAML_PARSER_ERROR;
+    let fresh0 = addr_of_mut!((*parser).problem);
+    *fresh0 = problem;
+    (*parser).problem_mark = problem_mark;
+}
+
+unsafe fn yaml_parser_set_parser_error_context(
+    parser: *mut yaml_parser_t,
+    context: *const libc::c_char,
+    context_mark: yaml_mark_t,
+    problem: *const libc::c_char,
+    problem_mark: yaml_mark_t,
+) {
+    (*parser).error = YAML_PARSER_ERROR;
+    let fresh1 = addr_of_mut!((*parser).context);
+    *fresh1 = context;
+    (*parser).context_mark = context_mark;
+    let fresh2 = addr_of_mut!((*parser).problem);
+    *fresh2 = problem;
+    (*parser).problem_mark = problem_mark;
+}
+
+unsafe fn yaml_parser_state_machine(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    match (*parser).state {
+        YAML_PARSE_STREAM_START_STATE => yaml_parser_parse_stream_start(parser, event),
+        YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE => {
+            yaml_parser_parse_document_start(parser, event, true)
+        }
+        YAML_PARSE_DOCUMENT_START_STATE => yaml_parser_parse_document_start(parser, event, false),
+        YAML_PARSE_DOCUMENT_CONTENT_STATE => yaml_parser_parse_document_content(parser, event),
+        YAML_PARSE_DOCUMENT_END_STATE => yaml_parser_parse_document_end(parser, event),
+        YAML_PARSE_BLOCK_NODE_STATE => yaml_parser_parse_node(parser, event, true, false),
+        YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE => {
+            yaml_parser_parse_node(parser, event, true, true)
+        }
+        YAML_PARSE_FLOW_NODE_STATE => yaml_parser_parse_node(parser, event, false, false),
+        YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE => {
+            yaml_parser_parse_block_sequence_entry(parser, event, true)
+        }
+        YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE => {
+            yaml_parser_parse_block_sequence_entry(parser, event, false)
+        }
+        YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE => {
+            yaml_parser_parse_indentless_sequence_entry(parser, event)
+        }
+        YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE => {
+            yaml_parser_parse_block_mapping_key(parser, event, true)
+        }
+        YAML_PARSE_BLOCK_MAPPING_KEY_STATE => {
+            yaml_parser_parse_block_mapping_key(parser, event, false)
+        }
+        YAML_PARSE_BLOCK_MAPPING_VALUE_STATE => {
+            yaml_parser_parse_block_mapping_value(parser, event)
+        }
+        YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE => {
+            yaml_parser_parse_flow_sequence_entry(parser, event, true)
+        }
+        YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE => {
+            yaml_parser_parse_flow_sequence_entry(parser, event, false)
+        }
+        YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE => {
+            yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event)
+        }
+        YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE => {
+            yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event)
+        }
+        YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE => {
+            yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event)
+        }
+        YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE => {
+            yaml_parser_parse_flow_mapping_key(parser, event, true)
+        }
+        YAML_PARSE_FLOW_MAPPING_KEY_STATE => {
+            yaml_parser_parse_flow_mapping_key(parser, event, false)
+        }
+        YAML_PARSE_FLOW_MAPPING_VALUE_STATE => {
+            yaml_parser_parse_flow_mapping_value(parser, event, false)
+        }
+        YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE => {
+            yaml_parser_parse_flow_mapping_value(parser, event, true)
+        }
+        _ => FAIL,
+    }
+}
+
+unsafe fn yaml_parser_parse_stream_start(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let token: *mut yaml_token_t = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ != YAML_STREAM_START_TOKEN {
+        yaml_parser_set_parser_error(
+            parser,
+            b"did not find expected <stream-start>\0" as *const u8 as *const libc::c_char,
+            (*token).start_mark,
+        );
+        return FAIL;
+    }
+    (*parser).state = YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE;
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_STREAM_START_EVENT;
+    (*event).start_mark = (*token).start_mark;
+    (*event).end_mark = (*token).start_mark;
+    (*event).data.stream_start.encoding = (*token).data.stream_start.encoding;
+    SKIP_TOKEN(parser);
+    OK
+}
+
+unsafe fn yaml_parser_parse_document_start(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    implicit: bool,
+) -> Success {
+    let mut token: *mut yaml_token_t;
+    let mut version_directive: *mut yaml_version_directive_t =
+        ptr::null_mut::<yaml_version_directive_t>();
+    struct TagDirectives {
+        start: *mut yaml_tag_directive_t,
+        end: *mut yaml_tag_directive_t,
+    }
+    let mut tag_directives = TagDirectives {
+        start: ptr::null_mut::<yaml_tag_directive_t>(),
+        end: ptr::null_mut::<yaml_tag_directive_t>(),
+    };
+    token = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if !implicit {
+        while (*token).type_ == YAML_DOCUMENT_END_TOKEN {
+            SKIP_TOKEN(parser);
+            token = PEEK_TOKEN(parser);
+            if token.is_null() {
+                return FAIL;
+            }
+        }
+    }
+    if implicit
+        && (*token).type_ != YAML_VERSION_DIRECTIVE_TOKEN
+        && (*token).type_ != YAML_TAG_DIRECTIVE_TOKEN
+        && (*token).type_ != YAML_DOCUMENT_START_TOKEN
+        && (*token).type_ != YAML_STREAM_END_TOKEN
+    {
+        if yaml_parser_process_directives(
+            parser,
+            ptr::null_mut::<*mut yaml_version_directive_t>(),
+            ptr::null_mut::<*mut yaml_tag_directive_t>(),
+            ptr::null_mut::<*mut yaml_tag_directive_t>(),
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        PUSH!((*parser).states, YAML_PARSE_DOCUMENT_END_STATE);
+        (*parser).state = YAML_PARSE_BLOCK_NODE_STATE;
+        memset(
+            event as *mut libc::c_void,
+            0,
+            size_of::<yaml_event_t>() as libc::c_ulong,
+        );
+        (*event).type_ = YAML_DOCUMENT_START_EVENT;
+        (*event).start_mark = (*token).start_mark;
+        (*event).end_mark = (*token).start_mark;
+        let fresh9 = addr_of_mut!((*event).data.document_start.version_directive);
+        *fresh9 = ptr::null_mut::<yaml_version_directive_t>();
+        let fresh10 = addr_of_mut!((*event).data.document_start.tag_directives.start);
+        *fresh10 = ptr::null_mut::<yaml_tag_directive_t>();
+        let fresh11 = addr_of_mut!((*event).data.document_start.tag_directives.end);
+        *fresh11 = ptr::null_mut::<yaml_tag_directive_t>();
+        (*event).data.document_start.implicit = true;
+        OK
+    } else if (*token).type_ != YAML_STREAM_END_TOKEN {
+        let end_mark: yaml_mark_t;
+        let start_mark: yaml_mark_t = (*token).start_mark;
+        if yaml_parser_process_directives(
+            parser,
+            addr_of_mut!(version_directive),
+            addr_of_mut!(tag_directives.start),
+            addr_of_mut!(tag_directives.end),
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        token = PEEK_TOKEN(parser);
+        if !token.is_null() {
+            if (*token).type_ != YAML_DOCUMENT_START_TOKEN {
+                yaml_parser_set_parser_error(
+                    parser,
+                    b"did not find expected <document start>\0" as *const u8 as *const libc::c_char,
+                    (*token).start_mark,
+                );
+            } else {
+                PUSH!((*parser).states, YAML_PARSE_DOCUMENT_END_STATE);
+                (*parser).state = YAML_PARSE_DOCUMENT_CONTENT_STATE;
+                end_mark = (*token).end_mark;
+                memset(
+                    event as *mut libc::c_void,
+                    0,
+                    size_of::<yaml_event_t>() as libc::c_ulong,
+                );
+                (*event).type_ = YAML_DOCUMENT_START_EVENT;
+                (*event).start_mark = start_mark;
+                (*event).end_mark = end_mark;
+                let fresh14 = addr_of_mut!((*event).data.document_start.version_directive);
+                *fresh14 = version_directive;
+                let fresh15 = addr_of_mut!((*event).data.document_start.tag_directives.start);
+                *fresh15 = tag_directives.start;
+                let fresh16 = addr_of_mut!((*event).data.document_start.tag_directives.end);
+                *fresh16 = tag_directives.end;
+                (*event).data.document_start.implicit = false;
+                SKIP_TOKEN(parser);
+                tag_directives.end = ptr::null_mut::<yaml_tag_directive_t>();
+                tag_directives.start = tag_directives.end;
+                return OK;
+            }
+        }
+        yaml_free(version_directive as *mut libc::c_void);
+        while tag_directives.start != tag_directives.end {
+            yaml_free((*tag_directives.end.wrapping_offset(-1_isize)).handle as *mut libc::c_void);
+            yaml_free((*tag_directives.end.wrapping_offset(-1_isize)).prefix as *mut libc::c_void);
+            tag_directives.end = tag_directives.end.wrapping_offset(-1);
+        }
+        yaml_free(tag_directives.start as *mut libc::c_void);
+        FAIL
+    } else {
+        (*parser).state = YAML_PARSE_END_STATE;
+        memset(
+            event as *mut libc::c_void,
+            0,
+            size_of::<yaml_event_t>() as libc::c_ulong,
+        );
+        (*event).type_ = YAML_STREAM_END_EVENT;
+        (*event).start_mark = (*token).start_mark;
+        (*event).end_mark = (*token).end_mark;
+        SKIP_TOKEN(parser);
+        OK
+    }
+}
+
+unsafe fn yaml_parser_parse_document_content(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let token: *mut yaml_token_t = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ == YAML_VERSION_DIRECTIVE_TOKEN
+        || (*token).type_ == YAML_TAG_DIRECTIVE_TOKEN
+        || (*token).type_ == YAML_DOCUMENT_START_TOKEN
+        || (*token).type_ == YAML_DOCUMENT_END_TOKEN
+        || (*token).type_ == YAML_STREAM_END_TOKEN
+    {
+        (*parser).state = POP!((*parser).states);
+        yaml_parser_process_empty_scalar(event, (*token).start_mark)
+    } else {
+        yaml_parser_parse_node(parser, event, true, false)
+    }
+}
+
+unsafe fn yaml_parser_parse_document_end(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let mut end_mark: yaml_mark_t;
+    let mut implicit = true;
+    let token: *mut yaml_token_t = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    end_mark = (*token).start_mark;
+    let start_mark: yaml_mark_t = end_mark;
+    if (*token).type_ == YAML_DOCUMENT_END_TOKEN {
+        end_mark = (*token).end_mark;
+        SKIP_TOKEN(parser);
+        implicit = false;
+    }
+    while !STACK_EMPTY!((*parser).tag_directives) {
+        let tag_directive = POP!((*parser).tag_directives);
+        yaml_free(tag_directive.handle as *mut libc::c_void);
+        yaml_free(tag_directive.prefix as *mut libc::c_void);
+    }
+    (*parser).state = YAML_PARSE_DOCUMENT_START_STATE;
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_DOCUMENT_END_EVENT;
+    (*event).start_mark = start_mark;
+    (*event).end_mark = end_mark;
+    (*event).data.document_end.implicit = implicit;
+    OK
+}
+
+unsafe fn yaml_parser_parse_node(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    block: bool,
+    indentless_sequence: bool,
+) -> Success {
+    let mut current_block: u64;
+    let mut token: *mut yaml_token_t;
+    let mut anchor: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut tag_handle: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut tag_suffix: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut tag: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut start_mark: yaml_mark_t;
+    let mut end_mark: yaml_mark_t;
+    let mut tag_mark = yaml_mark_t {
+        index: 0,
+        line: 0,
+        column: 0,
+    };
+    let implicit;
+    token = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ == YAML_ALIAS_TOKEN {
+        (*parser).state = POP!((*parser).states);
+        memset(
+            event as *mut libc::c_void,
+            0,
+            size_of::<yaml_event_t>() as libc::c_ulong,
+        );
+        (*event).type_ = YAML_ALIAS_EVENT;
+        (*event).start_mark = (*token).start_mark;
+        (*event).end_mark = (*token).end_mark;
+        let fresh26 = addr_of_mut!((*event).data.alias.anchor);
+        *fresh26 = (*token).data.alias.value;
+        SKIP_TOKEN(parser);
+        OK
+    } else {
+        end_mark = (*token).start_mark;
+        start_mark = end_mark;
+        if (*token).type_ == YAML_ANCHOR_TOKEN {
+            anchor = (*token).data.anchor.value;
+            start_mark = (*token).start_mark;
+            end_mark = (*token).end_mark;
+            SKIP_TOKEN(parser);
+            token = PEEK_TOKEN(parser);
+            if token.is_null() {
+                current_block = 17786380918591080555;
+            } else if (*token).type_ == YAML_TAG_TOKEN {
+                tag_handle = (*token).data.tag.handle;
+                tag_suffix = (*token).data.tag.suffix;
+                tag_mark = (*token).start_mark;
+                end_mark = (*token).end_mark;
+                SKIP_TOKEN(parser);
+                token = PEEK_TOKEN(parser);
+                if token.is_null() {
+                    current_block = 17786380918591080555;
+                } else {
+                    current_block = 11743904203796629665;
+                }
+            } else {
+                current_block = 11743904203796629665;
+            }
+        } else if (*token).type_ == YAML_TAG_TOKEN {
+            tag_handle = (*token).data.tag.handle;
+            tag_suffix = (*token).data.tag.suffix;
+            tag_mark = (*token).start_mark;
+            start_mark = tag_mark;
+            end_mark = (*token).end_mark;
+            SKIP_TOKEN(parser);
+            token = PEEK_TOKEN(parser);
+            if token.is_null() {
+                current_block = 17786380918591080555;
+            } else if (*token).type_ == YAML_ANCHOR_TOKEN {
+                anchor = (*token).data.anchor.value;
+                end_mark = (*token).end_mark;
+                SKIP_TOKEN(parser);
+                token = PEEK_TOKEN(parser);
+                if token.is_null() {
+                    current_block = 17786380918591080555;
+                } else {
+                    current_block = 11743904203796629665;
+                }
+            } else {
+                current_block = 11743904203796629665;
+            }
+        } else {
+            current_block = 11743904203796629665;
+        }
+        if current_block == 11743904203796629665 {
+            if !tag_handle.is_null() {
+                if *tag_handle == 0 {
+                    tag = tag_suffix;
+                    yaml_free(tag_handle as *mut libc::c_void);
+                    tag_suffix = ptr::null_mut::<yaml_char_t>();
+                    tag_handle = tag_suffix;
+                    current_block = 9437013279121998969;
+                } else {
+                    let mut tag_directive: *mut yaml_tag_directive_t;
+                    tag_directive = (*parser).tag_directives.start;
+                    loop {
+                        if !(tag_directive != (*parser).tag_directives.top) {
+                            current_block = 17728966195399430138;
+                            break;
+                        }
+                        if strcmp(
+                            (*tag_directive).handle as *mut libc::c_char,
+                            tag_handle as *mut libc::c_char,
+                        ) == 0
+                        {
+                            let prefix_len: size_t =
+                                strlen((*tag_directive).prefix as *mut libc::c_char);
+                            let suffix_len: size_t = strlen(tag_suffix as *mut libc::c_char);
+                            tag = yaml_malloc(
+                                prefix_len.wrapping_add(suffix_len).wrapping_add(1_u64),
+                            ) as *mut yaml_char_t;
+                            memcpy(
+                                tag as *mut libc::c_void,
+                                (*tag_directive).prefix as *const libc::c_void,
+                                prefix_len,
+                            );
+                            memcpy(
+                                tag.wrapping_offset(prefix_len as isize) as *mut libc::c_void,
+                                tag_suffix as *const libc::c_void,
+                                suffix_len,
+                            );
+                            *tag.wrapping_offset(prefix_len.wrapping_add(suffix_len) as isize) =
+                                b'\0';
+                            yaml_free(tag_handle as *mut libc::c_void);
+                            yaml_free(tag_suffix as *mut libc::c_void);
+                            tag_suffix = ptr::null_mut::<yaml_char_t>();
+                            tag_handle = tag_suffix;
+                            current_block = 17728966195399430138;
+                            break;
+                        } else {
+                            tag_directive = tag_directive.wrapping_offset(1);
+                        }
+                    }
+                    if current_block != 17786380918591080555 {
+                        if tag.is_null() {
+                            yaml_parser_set_parser_error_context(
+                                parser,
+                                b"while parsing a node\0" as *const u8 as *const libc::c_char,
+                                start_mark,
+                                b"found undefined tag handle\0" as *const u8 as *const libc::c_char,
+                                tag_mark,
+                            );
+                            current_block = 17786380918591080555;
+                        } else {
+                            current_block = 9437013279121998969;
+                        }
+                    }
+                }
+            } else {
+                current_block = 9437013279121998969;
+            }
+            if current_block != 17786380918591080555 {
+                implicit = tag.is_null() || *tag == 0;
+                if indentless_sequence && (*token).type_ == YAML_BLOCK_ENTRY_TOKEN {
+                    end_mark = (*token).end_mark;
+                    (*parser).state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
+                    memset(
+                        event as *mut libc::c_void,
+                        0,
+                        size_of::<yaml_event_t>() as libc::c_ulong,
+                    );
+                    (*event).type_ = YAML_SEQUENCE_START_EVENT;
+                    (*event).start_mark = start_mark;
+                    (*event).end_mark = end_mark;
+                    let fresh37 = addr_of_mut!((*event).data.sequence_start.anchor);
+                    *fresh37 = anchor;
+                    let fresh38 = addr_of_mut!((*event).data.sequence_start.tag);
+                    *fresh38 = tag;
+                    (*event).data.sequence_start.implicit = implicit;
+                    (*event).data.sequence_start.style = YAML_BLOCK_SEQUENCE_STYLE;
+                    return OK;
+                } else if (*token).type_ == YAML_SCALAR_TOKEN {
+                    let mut plain_implicit = false;
+                    let mut quoted_implicit = false;
+                    end_mark = (*token).end_mark;
+                    if (*token).data.scalar.style == YAML_PLAIN_SCALAR_STYLE && tag.is_null()
+                        || !tag.is_null()
+                            && strcmp(
+                                tag as *mut libc::c_char,
+                                b"!\0" as *const u8 as *const libc::c_char,
+                            ) == 0
+                    {
+                        plain_implicit = true;
+                    } else if tag.is_null() {
+                        quoted_implicit = true;
+                    }
+                    (*parser).state = POP!((*parser).states);
+                    memset(
+                        event as *mut libc::c_void,
+                        0,
+                        size_of::<yaml_event_t>() as libc::c_ulong,
+                    );
+                    (*event).type_ = YAML_SCALAR_EVENT;
+                    (*event).start_mark = start_mark;
+                    (*event).end_mark = end_mark;
+                    let fresh40 = addr_of_mut!((*event).data.scalar.anchor);
+                    *fresh40 = anchor;
+                    let fresh41 = addr_of_mut!((*event).data.scalar.tag);
+                    *fresh41 = tag;
+                    let fresh42 = addr_of_mut!((*event).data.scalar.value);
+                    *fresh42 = (*token).data.scalar.value;
+                    (*event).data.scalar.length = (*token).data.scalar.length;
+                    (*event).data.scalar.plain_implicit = plain_implicit;
+                    (*event).data.scalar.quoted_implicit = quoted_implicit;
+                    (*event).data.scalar.style = (*token).data.scalar.style;
+                    SKIP_TOKEN(parser);
+                    return OK;
+                } else if (*token).type_ == YAML_FLOW_SEQUENCE_START_TOKEN {
+                    end_mark = (*token).end_mark;
+                    (*parser).state = YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE;
+                    memset(
+                        event as *mut libc::c_void,
+                        0,
+                        size_of::<yaml_event_t>() as libc::c_ulong,
+                    );
+                    (*event).type_ = YAML_SEQUENCE_START_EVENT;
+                    (*event).start_mark = start_mark;
+                    (*event).end_mark = end_mark;
+                    let fresh45 = addr_of_mut!((*event).data.sequence_start.anchor);
+                    *fresh45 = anchor;
+                    let fresh46 = addr_of_mut!((*event).data.sequence_start.tag);
+                    *fresh46 = tag;
+                    (*event).data.sequence_start.implicit = implicit;
+                    (*event).data.sequence_start.style = YAML_FLOW_SEQUENCE_STYLE;
+                    return OK;
+                } else if (*token).type_ == YAML_FLOW_MAPPING_START_TOKEN {
+                    end_mark = (*token).end_mark;
+                    (*parser).state = YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE;
+                    memset(
+                        event as *mut libc::c_void,
+                        0,
+                        size_of::<yaml_event_t>() as libc::c_ulong,
+                    );
+                    (*event).type_ = YAML_MAPPING_START_EVENT;
+                    (*event).start_mark = start_mark;
+                    (*event).end_mark = end_mark;
+                    let fresh47 = addr_of_mut!((*event).data.mapping_start.anchor);
+                    *fresh47 = anchor;
+                    let fresh48 = addr_of_mut!((*event).data.mapping_start.tag);
+                    *fresh48 = tag;
+                    (*event).data.mapping_start.implicit = implicit;
+                    (*event).data.mapping_start.style = YAML_FLOW_MAPPING_STYLE;
+                    return OK;
+                } else if block && (*token).type_ == YAML_BLOCK_SEQUENCE_START_TOKEN {
+                    end_mark = (*token).end_mark;
+                    (*parser).state = YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE;
+                    memset(
+                        event as *mut libc::c_void,
+                        0,
+                        size_of::<yaml_event_t>() as libc::c_ulong,
+                    );
+                    (*event).type_ = YAML_SEQUENCE_START_EVENT;
+                    (*event).start_mark = start_mark;
+                    (*event).end_mark = end_mark;
+                    let fresh49 = addr_of_mut!((*event).data.sequence_start.anchor);
+                    *fresh49 = anchor;
+                    let fresh50 = addr_of_mut!((*event).data.sequence_start.tag);
+                    *fresh50 = tag;
+                    (*event).data.sequence_start.implicit = implicit;
+                    (*event).data.sequence_start.style = YAML_BLOCK_SEQUENCE_STYLE;
+                    return OK;
+                } else if block && (*token).type_ == YAML_BLOCK_MAPPING_START_TOKEN {
+                    end_mark = (*token).end_mark;
+                    (*parser).state = YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE;
+                    memset(
+                        event as *mut libc::c_void,
+                        0,
+                        size_of::<yaml_event_t>() as libc::c_ulong,
+                    );
+                    (*event).type_ = YAML_MAPPING_START_EVENT;
+                    (*event).start_mark = start_mark;
+                    (*event).end_mark = end_mark;
+                    let fresh51 = addr_of_mut!((*event).data.mapping_start.anchor);
+                    *fresh51 = anchor;
+                    let fresh52 = addr_of_mut!((*event).data.mapping_start.tag);
+                    *fresh52 = tag;
+                    (*event).data.mapping_start.implicit = implicit;
+                    (*event).data.mapping_start.style = YAML_BLOCK_MAPPING_STYLE;
+                    return OK;
+                } else if !anchor.is_null() || !tag.is_null() {
+                    let value: *mut yaml_char_t = yaml_malloc(1_u64) as *mut yaml_char_t;
+                    *value = b'\0';
+                    (*parser).state = POP!((*parser).states);
+                    memset(
+                        event as *mut libc::c_void,
+                        0,
+                        size_of::<yaml_event_t>() as libc::c_ulong,
+                    );
+                    (*event).type_ = YAML_SCALAR_EVENT;
+                    (*event).start_mark = start_mark;
+                    (*event).end_mark = end_mark;
+                    let fresh54 = addr_of_mut!((*event).data.scalar.anchor);
+                    *fresh54 = anchor;
+                    let fresh55 = addr_of_mut!((*event).data.scalar.tag);
+                    *fresh55 = tag;
+                    let fresh56 = addr_of_mut!((*event).data.scalar.value);
+                    *fresh56 = value;
+                    (*event).data.scalar.length = 0_u64;
+                    (*event).data.scalar.plain_implicit = implicit;
+                    (*event).data.scalar.quoted_implicit = false;
+                    (*event).data.scalar.style = YAML_PLAIN_SCALAR_STYLE;
+                    return OK;
+                } else {
+                    yaml_parser_set_parser_error_context(
+                        parser,
+                        if block {
+                            b"while parsing a block node\0" as *const u8 as *const libc::c_char
+                        } else {
+                            b"while parsing a flow node\0" as *const u8 as *const libc::c_char
+                        },
+                        start_mark,
+                        b"did not find expected node content\0" as *const u8 as *const libc::c_char,
+                        (*token).start_mark,
+                    );
+                }
+            }
+        }
+        yaml_free(anchor as *mut libc::c_void);
+        yaml_free(tag_handle as *mut libc::c_void);
+        yaml_free(tag_suffix as *mut libc::c_void);
+        yaml_free(tag as *mut libc::c_void);
+        FAIL
+    }
+}
+
+unsafe fn yaml_parser_parse_block_sequence_entry(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    first: bool,
+) -> Success {
+    let mut token: *mut yaml_token_t;
+    if first {
+        token = PEEK_TOKEN(parser);
+        PUSH!((*parser).marks, (*token).start_mark);
+        SKIP_TOKEN(parser);
+    }
+    token = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ == YAML_BLOCK_ENTRY_TOKEN {
+        let mark: yaml_mark_t = (*token).end_mark;
+        SKIP_TOKEN(parser);
+        token = PEEK_TOKEN(parser);
+        if token.is_null() {
+            return FAIL;
+        }
+        if (*token).type_ != YAML_BLOCK_ENTRY_TOKEN && (*token).type_ != YAML_BLOCK_END_TOKEN {
+            PUSH!((*parser).states, YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE);
+            yaml_parser_parse_node(parser, event, true, false)
+        } else {
+            (*parser).state = YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE;
+            yaml_parser_process_empty_scalar(event, mark)
+        }
+    } else if (*token).type_ == YAML_BLOCK_END_TOKEN {
+        (*parser).state = POP!((*parser).states);
+        let _ = POP!((*parser).marks);
+        memset(
+            event as *mut libc::c_void,
+            0,
+            size_of::<yaml_event_t>() as libc::c_ulong,
+        );
+        (*event).type_ = YAML_SEQUENCE_END_EVENT;
+        (*event).start_mark = (*token).start_mark;
+        (*event).end_mark = (*token).end_mark;
+        SKIP_TOKEN(parser);
+        OK
+    } else {
+        yaml_parser_set_parser_error_context(
+            parser,
+            b"while parsing a block collection\0" as *const u8 as *const libc::c_char,
+            POP!((*parser).marks),
+            b"did not find expected '-' indicator\0" as *const u8 as *const libc::c_char,
+            (*token).start_mark,
+        );
+        FAIL
+    }
+}
+
+unsafe fn yaml_parser_parse_indentless_sequence_entry(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let mut token: *mut yaml_token_t;
+    token = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ == YAML_BLOCK_ENTRY_TOKEN {
+        let mark: yaml_mark_t = (*token).end_mark;
+        SKIP_TOKEN(parser);
+        token = PEEK_TOKEN(parser);
+        if token.is_null() {
+            return FAIL;
+        }
+        if (*token).type_ != YAML_BLOCK_ENTRY_TOKEN
+            && (*token).type_ != YAML_KEY_TOKEN
+            && (*token).type_ != YAML_VALUE_TOKEN
+            && (*token).type_ != YAML_BLOCK_END_TOKEN
+        {
+            PUSH!((*parser).states, YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE);
+            yaml_parser_parse_node(parser, event, true, false)
+        } else {
+            (*parser).state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
+            yaml_parser_process_empty_scalar(event, mark)
+        }
+    } else {
+        (*parser).state = POP!((*parser).states);
+        memset(
+            event as *mut libc::c_void,
+            0,
+            size_of::<yaml_event_t>() as libc::c_ulong,
+        );
+        (*event).type_ = YAML_SEQUENCE_END_EVENT;
+        (*event).start_mark = (*token).start_mark;
+        (*event).end_mark = (*token).start_mark;
+        OK
+    }
+}
+
+unsafe fn yaml_parser_parse_block_mapping_key(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    first: bool,
+) -> Success {
+    let mut token: *mut yaml_token_t;
+    if first {
+        token = PEEK_TOKEN(parser);
+        PUSH!((*parser).marks, (*token).start_mark);
+        SKIP_TOKEN(parser);
+    }
+    token = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ == YAML_KEY_TOKEN {
+        let mark: yaml_mark_t = (*token).end_mark;
+        SKIP_TOKEN(parser);
+        token = PEEK_TOKEN(parser);
+        if token.is_null() {
+            return FAIL;
+        }
+        if (*token).type_ != YAML_KEY_TOKEN
+            && (*token).type_ != YAML_VALUE_TOKEN
+            && (*token).type_ != YAML_BLOCK_END_TOKEN
+        {
+            PUSH!((*parser).states, YAML_PARSE_BLOCK_MAPPING_VALUE_STATE);
+            yaml_parser_parse_node(parser, event, true, true)
+        } else {
+            (*parser).state = YAML_PARSE_BLOCK_MAPPING_VALUE_STATE;
+            yaml_parser_process_empty_scalar(event, mark)
+        }
+    } else if (*token).type_ == YAML_BLOCK_END_TOKEN {
+        (*parser).state = POP!((*parser).states);
+        let _ = POP!((*parser).marks);
+        memset(
+            event as *mut libc::c_void,
+            0,
+            size_of::<yaml_event_t>() as libc::c_ulong,
+        );
+        (*event).type_ = YAML_MAPPING_END_EVENT;
+        (*event).start_mark = (*token).start_mark;
+        (*event).end_mark = (*token).end_mark;
+        SKIP_TOKEN(parser);
+        OK
+    } else {
+        yaml_parser_set_parser_error_context(
+            parser,
+            b"while parsing a block mapping\0" as *const u8 as *const libc::c_char,
+            POP!((*parser).marks),
+            b"did not find expected key\0" as *const u8 as *const libc::c_char,
+            (*token).start_mark,
+        );
+        FAIL
+    }
+}
+
+unsafe fn yaml_parser_parse_block_mapping_value(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let mut token: *mut yaml_token_t;
+    token = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ == YAML_VALUE_TOKEN {
+        let mark: yaml_mark_t = (*token).end_mark;
+        SKIP_TOKEN(parser);
+        token = PEEK_TOKEN(parser);
+        if token.is_null() {
+            return FAIL;
+        }
+        if (*token).type_ != YAML_KEY_TOKEN
+            && (*token).type_ != YAML_VALUE_TOKEN
+            && (*token).type_ != YAML_BLOCK_END_TOKEN
+        {
+            PUSH!((*parser).states, YAML_PARSE_BLOCK_MAPPING_KEY_STATE);
+            yaml_parser_parse_node(parser, event, true, true)
+        } else {
+            (*parser).state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
+            yaml_parser_process_empty_scalar(event, mark)
+        }
+    } else {
+        (*parser).state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
+        yaml_parser_process_empty_scalar(event, (*token).start_mark)
+    }
+}
+
+unsafe fn yaml_parser_parse_flow_sequence_entry(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    first: bool,
+) -> Success {
+    let mut token: *mut yaml_token_t;
+    if first {
+        token = PEEK_TOKEN(parser);
+        PUSH!((*parser).marks, (*token).start_mark);
+        SKIP_TOKEN(parser);
+    }
+    token = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ != YAML_FLOW_SEQUENCE_END_TOKEN {
+        if !first {
+            if (*token).type_ == YAML_FLOW_ENTRY_TOKEN {
+                SKIP_TOKEN(parser);
+                token = PEEK_TOKEN(parser);
+                if token.is_null() {
+                    return FAIL;
+                }
+            } else {
+                yaml_parser_set_parser_error_context(
+                    parser,
+                    b"while parsing a flow sequence\0" as *const u8 as *const libc::c_char,
+                    POP!((*parser).marks),
+                    b"did not find expected ',' or ']'\0" as *const u8 as *const libc::c_char,
+                    (*token).start_mark,
+                );
+                return FAIL;
+            }
+        }
+        if (*token).type_ == YAML_KEY_TOKEN {
+            (*parser).state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE;
+            memset(
+                event as *mut libc::c_void,
+                0,
+                size_of::<yaml_event_t>() as libc::c_ulong,
+            );
+            (*event).type_ = YAML_MAPPING_START_EVENT;
+            (*event).start_mark = (*token).start_mark;
+            (*event).end_mark = (*token).end_mark;
+            let fresh99 = addr_of_mut!((*event).data.mapping_start.anchor);
+            *fresh99 = ptr::null_mut::<yaml_char_t>();
+            let fresh100 = addr_of_mut!((*event).data.mapping_start.tag);
+            *fresh100 = ptr::null_mut::<yaml_char_t>();
+            (*event).data.mapping_start.implicit = true;
+            (*event).data.mapping_start.style = YAML_FLOW_MAPPING_STYLE;
+            SKIP_TOKEN(parser);
+            return OK;
+        } else if (*token).type_ != YAML_FLOW_SEQUENCE_END_TOKEN {
+            PUSH!((*parser).states, YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE);
+            return yaml_parser_parse_node(parser, event, false, false);
+        }
+    }
+    (*parser).state = POP!((*parser).states);
+    let _ = POP!((*parser).marks);
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_SEQUENCE_END_EVENT;
+    (*event).start_mark = (*token).start_mark;
+    (*event).end_mark = (*token).end_mark;
+    SKIP_TOKEN(parser);
+    OK
+}
+
+unsafe fn yaml_parser_parse_flow_sequence_entry_mapping_key(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let token: *mut yaml_token_t = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ != YAML_VALUE_TOKEN
+        && (*token).type_ != YAML_FLOW_ENTRY_TOKEN
+        && (*token).type_ != YAML_FLOW_SEQUENCE_END_TOKEN
+    {
+        PUSH!(
+            (*parser).states,
+            YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
+        );
+        yaml_parser_parse_node(parser, event, false, false)
+    } else {
+        let mark: yaml_mark_t = (*token).end_mark;
+        SKIP_TOKEN(parser);
+        (*parser).state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE;
+        yaml_parser_process_empty_scalar(event, mark)
+    }
+}
+
+unsafe fn yaml_parser_parse_flow_sequence_entry_mapping_value(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let mut token: *mut yaml_token_t;
+    token = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ == YAML_VALUE_TOKEN {
+        SKIP_TOKEN(parser);
+        token = PEEK_TOKEN(parser);
+        if token.is_null() {
+            return FAIL;
+        }
+        if (*token).type_ != YAML_FLOW_ENTRY_TOKEN && (*token).type_ != YAML_FLOW_SEQUENCE_END_TOKEN
+        {
+            PUSH!(
+                (*parser).states,
+                YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
+            );
+            return yaml_parser_parse_node(parser, event, false, false);
+        }
+    }
+    (*parser).state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE;
+    yaml_parser_process_empty_scalar(event, (*token).start_mark)
+}
+
+unsafe fn yaml_parser_parse_flow_sequence_entry_mapping_end(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+) -> Success {
+    let token: *mut yaml_token_t = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    (*parser).state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE;
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_MAPPING_END_EVENT;
+    (*event).start_mark = (*token).start_mark;
+    (*event).end_mark = (*token).start_mark;
+    OK
+}
+
+unsafe fn yaml_parser_parse_flow_mapping_key(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    first: bool,
+) -> Success {
+    let mut token: *mut yaml_token_t;
+    if first {
+        token = PEEK_TOKEN(parser);
+        PUSH!((*parser).marks, (*token).start_mark);
+        SKIP_TOKEN(parser);
+    }
+    token = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if (*token).type_ != YAML_FLOW_MAPPING_END_TOKEN {
+        if !first {
+            if (*token).type_ == YAML_FLOW_ENTRY_TOKEN {
+                SKIP_TOKEN(parser);
+                token = PEEK_TOKEN(parser);
+                if token.is_null() {
+                    return FAIL;
+                }
+            } else {
+                yaml_parser_set_parser_error_context(
+                    parser,
+                    b"while parsing a flow mapping\0" as *const u8 as *const libc::c_char,
+                    POP!((*parser).marks),
+                    b"did not find expected ',' or '}'\0" as *const u8 as *const libc::c_char,
+                    (*token).start_mark,
+                );
+                return FAIL;
+            }
+        }
+        if (*token).type_ == YAML_KEY_TOKEN {
+            SKIP_TOKEN(parser);
+            token = PEEK_TOKEN(parser);
+            if token.is_null() {
+                return FAIL;
+            }
+            if (*token).type_ != YAML_VALUE_TOKEN
+                && (*token).type_ != YAML_FLOW_ENTRY_TOKEN
+                && (*token).type_ != YAML_FLOW_MAPPING_END_TOKEN
+            {
+                PUSH!((*parser).states, YAML_PARSE_FLOW_MAPPING_VALUE_STATE);
+                return yaml_parser_parse_node(parser, event, false, false);
+            } else {
+                (*parser).state = YAML_PARSE_FLOW_MAPPING_VALUE_STATE;
+                return yaml_parser_process_empty_scalar(event, (*token).start_mark);
+            }
+        } else if (*token).type_ != YAML_FLOW_MAPPING_END_TOKEN {
+            PUSH!((*parser).states, YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE);
+            return yaml_parser_parse_node(parser, event, false, false);
+        }
+    }
+    (*parser).state = POP!((*parser).states);
+    let _ = POP!((*parser).marks);
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_MAPPING_END_EVENT;
+    (*event).start_mark = (*token).start_mark;
+    (*event).end_mark = (*token).end_mark;
+    SKIP_TOKEN(parser);
+    OK
+}
+
+unsafe fn yaml_parser_parse_flow_mapping_value(
+    parser: *mut yaml_parser_t,
+    event: *mut yaml_event_t,
+    empty: bool,
+) -> Success {
+    let mut token: *mut yaml_token_t;
+    token = PEEK_TOKEN(parser);
+    if token.is_null() {
+        return FAIL;
+    }
+    if empty {
+        (*parser).state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
+        return yaml_parser_process_empty_scalar(event, (*token).start_mark);
+    }
+    if (*token).type_ == YAML_VALUE_TOKEN {
+        SKIP_TOKEN(parser);
+        token = PEEK_TOKEN(parser);
+        if token.is_null() {
+            return FAIL;
+        }
+        if (*token).type_ != YAML_FLOW_ENTRY_TOKEN && (*token).type_ != YAML_FLOW_MAPPING_END_TOKEN
+        {
+            PUSH!((*parser).states, YAML_PARSE_FLOW_MAPPING_KEY_STATE);
+            return yaml_parser_parse_node(parser, event, false, false);
+        }
+    }
+    (*parser).state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
+    yaml_parser_process_empty_scalar(event, (*token).start_mark)
+}
+
+unsafe fn yaml_parser_process_empty_scalar(event: *mut yaml_event_t, mark: yaml_mark_t) -> Success {
+    let value: *mut yaml_char_t = yaml_malloc(1_u64) as *mut yaml_char_t;
+    *value = b'\0';
+    memset(
+        event as *mut libc::c_void,
+        0,
+        size_of::<yaml_event_t>() as libc::c_ulong,
+    );
+    (*event).type_ = YAML_SCALAR_EVENT;
+    (*event).start_mark = mark;
+    (*event).end_mark = mark;
+    let fresh138 = addr_of_mut!((*event).data.scalar.anchor);
+    *fresh138 = ptr::null_mut::<yaml_char_t>();
+    let fresh139 = addr_of_mut!((*event).data.scalar.tag);
+    *fresh139 = ptr::null_mut::<yaml_char_t>();
+    let fresh140 = addr_of_mut!((*event).data.scalar.value);
+    *fresh140 = value;
+    (*event).data.scalar.length = 0_u64;
+    (*event).data.scalar.plain_implicit = true;
+    (*event).data.scalar.quoted_implicit = false;
+    (*event).data.scalar.style = YAML_PLAIN_SCALAR_STYLE;
+    OK
+}
+
+unsafe fn yaml_parser_process_directives(
+    parser: *mut yaml_parser_t,
+    version_directive_ref: *mut *mut yaml_version_directive_t,
+    tag_directives_start_ref: *mut *mut yaml_tag_directive_t,
+    tag_directives_end_ref: *mut *mut yaml_tag_directive_t,
+) -> Success {
+    let mut current_block: u64;
+    let mut default_tag_directives: [yaml_tag_directive_t; 3] = [
+        yaml_tag_directive_t {
+            handle: b"!\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
+            prefix: b"!\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
+        },
+        yaml_tag_directive_t {
+            handle: b"!!\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
+            prefix: b"tag:yaml.org,2002:\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
+        },
+        yaml_tag_directive_t {
+            handle: ptr::null_mut::<yaml_char_t>(),
+            prefix: ptr::null_mut::<yaml_char_t>(),
+        },
+    ];
+    let mut default_tag_directive: *mut yaml_tag_directive_t;
+    let mut version_directive: *mut yaml_version_directive_t =
+        ptr::null_mut::<yaml_version_directive_t>();
+    struct TagDirectives {
+        start: *mut yaml_tag_directive_t,
+        end: *mut yaml_tag_directive_t,
+        top: *mut yaml_tag_directive_t,
+    }
+    let mut tag_directives = TagDirectives {
+        start: ptr::null_mut::<yaml_tag_directive_t>(),
+        end: ptr::null_mut::<yaml_tag_directive_t>(),
+        top: ptr::null_mut::<yaml_tag_directive_t>(),
+    };
+    let mut token: *mut yaml_token_t;
+    STACK_INIT!(tag_directives, yaml_tag_directive_t);
+    token = PEEK_TOKEN(parser);
+    if !token.is_null() {
+        loop {
+            if !((*token).type_ == YAML_VERSION_DIRECTIVE_TOKEN
+                || (*token).type_ == YAML_TAG_DIRECTIVE_TOKEN)
+            {
+                current_block = 16924917904204750491;
+                break;
+            }
+            if (*token).type_ == YAML_VERSION_DIRECTIVE_TOKEN {
+                if !version_directive.is_null() {
+                    yaml_parser_set_parser_error(
+                        parser,
+                        b"found duplicate %YAML directive\0" as *const u8 as *const libc::c_char,
+                        (*token).start_mark,
+                    );
+                    current_block = 17143798186130252483;
+                    break;
+                } else if (*token).data.version_directive.major != 1
+                    || (*token).data.version_directive.minor != 1
+                        && (*token).data.version_directive.minor != 2
+                {
+                    yaml_parser_set_parser_error(
+                        parser,
+                        b"found incompatible YAML document\0" as *const u8 as *const libc::c_char,
+                        (*token).start_mark,
+                    );
+                    current_block = 17143798186130252483;
+                    break;
+                } else {
+                    version_directive =
+                        yaml_malloc(size_of::<yaml_version_directive_t>() as libc::c_ulong)
+                            as *mut yaml_version_directive_t;
+                    (*version_directive).major = (*token).data.version_directive.major;
+                    (*version_directive).minor = (*token).data.version_directive.minor;
+                }
+            } else if (*token).type_ == YAML_TAG_DIRECTIVE_TOKEN {
+                let value = yaml_tag_directive_t {
+                    handle: (*token).data.tag_directive.handle,
+                    prefix: (*token).data.tag_directive.prefix,
+                };
+                if yaml_parser_append_tag_directive(parser, value, false, (*token).start_mark).fail
+                {
+                    current_block = 17143798186130252483;
+                    break;
+                }
+                PUSH!(tag_directives, value);
+            }
+            SKIP_TOKEN(parser);
+            token = PEEK_TOKEN(parser);
+            if token.is_null() {
+                current_block = 17143798186130252483;
+                break;
+            }
+        }
+        if current_block != 17143798186130252483 {
+            default_tag_directive = default_tag_directives.as_mut_ptr();
+            loop {
+                if (*default_tag_directive).handle.is_null() {
+                    current_block = 18377268871191777778;
+                    break;
+                }
+                if yaml_parser_append_tag_directive(
+                    parser,
+                    *default_tag_directive,
+                    true,
+                    (*token).start_mark,
+                )
+                .fail
+                {
+                    current_block = 17143798186130252483;
+                    break;
+                }
+                default_tag_directive = default_tag_directive.wrapping_offset(1);
+            }
+            if current_block != 17143798186130252483 {
+                if !version_directive_ref.is_null() {
+                    *version_directive_ref = version_directive;
+                }
+                if !tag_directives_start_ref.is_null() {
+                    if STACK_EMPTY!(tag_directives) {
+                        *tag_directives_end_ref = ptr::null_mut::<yaml_tag_directive_t>();
+                        *tag_directives_start_ref = *tag_directives_end_ref;
+                        STACK_DEL!(tag_directives);
+                    } else {
+                        *tag_directives_start_ref = tag_directives.start;
+                        *tag_directives_end_ref = tag_directives.top;
+                    }
+                } else {
+                    STACK_DEL!(tag_directives);
+                }
+                if version_directive_ref.is_null() {
+                    yaml_free(version_directive as *mut libc::c_void);
+                }
+                return OK;
+            }
+        }
+    }
+    yaml_free(version_directive as *mut libc::c_void);
+    while !STACK_EMPTY!(tag_directives) {
+        let tag_directive = POP!(tag_directives);
+        yaml_free(tag_directive.handle as *mut libc::c_void);
+        yaml_free(tag_directive.prefix as *mut libc::c_void);
+    }
+    STACK_DEL!(tag_directives);
+    FAIL
+}
+
+unsafe fn yaml_parser_append_tag_directive(
+    parser: *mut yaml_parser_t,
+    value: yaml_tag_directive_t,
+    allow_duplicates: bool,
+    mark: yaml_mark_t,
+) -> Success {
+    let mut tag_directive: *mut yaml_tag_directive_t;
+    let mut copy = yaml_tag_directive_t {
+        handle: ptr::null_mut::<yaml_char_t>(),
+        prefix: ptr::null_mut::<yaml_char_t>(),
+    };
+    tag_directive = (*parser).tag_directives.start;
+    while tag_directive != (*parser).tag_directives.top {
+        if strcmp(
+            value.handle as *mut libc::c_char,
+            (*tag_directive).handle as *mut libc::c_char,
+        ) == 0
+        {
+            if allow_duplicates {
+                return OK;
+            }
+            yaml_parser_set_parser_error(
+                parser,
+                b"found duplicate %TAG directive\0" as *const u8 as *const libc::c_char,
+                mark,
+            );
+            return FAIL;
+        }
+        tag_directive = tag_directive.wrapping_offset(1);
+    }
+    copy.handle = yaml_strdup(value.handle);
+    copy.prefix = yaml_strdup(value.prefix);
+    PUSH!((*parser).tag_directives, copy);
+    OK
+}
diff --git a/src/reader.rs b/src/reader.rs
new file mode 100644
index 0000000..264ad92
--- /dev/null
+++ b/src/reader.rs
@@ -0,0 +1,469 @@
+use crate::externs::{memcmp, memmove};
+use crate::success::{Success, FAIL, OK};
+use crate::yaml::{size_t, yaml_char_t};
+use crate::{
+    libc, yaml_parser_t, PointerExt, YAML_ANY_ENCODING, YAML_READER_ERROR, YAML_UTF16BE_ENCODING,
+    YAML_UTF16LE_ENCODING, YAML_UTF8_ENCODING,
+};
+use core::ptr::addr_of_mut;
+
+unsafe fn yaml_parser_set_reader_error(
+    parser: *mut yaml_parser_t,
+    problem: *const libc::c_char,
+    offset: size_t,
+    value: libc::c_int,
+) -> Success {
+    (*parser).error = YAML_READER_ERROR;
+    let fresh0 = addr_of_mut!((*parser).problem);
+    *fresh0 = problem;
+    (*parser).problem_offset = offset;
+    (*parser).problem_value = value;
+    FAIL
+}
+
+const BOM_UTF8: *const libc::c_char = b"\xEF\xBB\xBF\0" as *const u8 as *const libc::c_char;
+const BOM_UTF16LE: *const libc::c_char = b"\xFF\xFE\0" as *const u8 as *const libc::c_char;
+const BOM_UTF16BE: *const libc::c_char = b"\xFE\xFF\0" as *const u8 as *const libc::c_char;
+
+unsafe fn yaml_parser_determine_encoding(parser: *mut yaml_parser_t) -> Success {
+    while !(*parser).eof
+        && ((*parser)
+            .raw_buffer
+            .last
+            .c_offset_from((*parser).raw_buffer.pointer) as libc::c_long)
+            < 3_i64
+    {
+        if yaml_parser_update_raw_buffer(parser).fail {
+            return FAIL;
+        }
+    }
+    if (*parser)
+        .raw_buffer
+        .last
+        .c_offset_from((*parser).raw_buffer.pointer) as libc::c_long
+        >= 2_i64
+        && memcmp(
+            (*parser).raw_buffer.pointer as *const libc::c_void,
+            BOM_UTF16LE as *const libc::c_void,
+            2_u64,
+        ) == 0
+    {
+        (*parser).encoding = YAML_UTF16LE_ENCODING;
+        let fresh1 = addr_of_mut!((*parser).raw_buffer.pointer);
+        *fresh1 = (*fresh1).wrapping_offset(2_isize);
+        let fresh2 = addr_of_mut!((*parser).offset);
+        *fresh2 = (*fresh2 as libc::c_ulong).wrapping_add(2_u64) as size_t as size_t;
+    } else if (*parser)
+        .raw_buffer
+        .last
+        .c_offset_from((*parser).raw_buffer.pointer) as libc::c_long
+        >= 2_i64
+        && memcmp(
+            (*parser).raw_buffer.pointer as *const libc::c_void,
+            BOM_UTF16BE as *const libc::c_void,
+            2_u64,
+        ) == 0
+    {
+        (*parser).encoding = YAML_UTF16BE_ENCODING;
+        let fresh3 = addr_of_mut!((*parser).raw_buffer.pointer);
+        *fresh3 = (*fresh3).wrapping_offset(2_isize);
+        let fresh4 = addr_of_mut!((*parser).offset);
+        *fresh4 = (*fresh4 as libc::c_ulong).wrapping_add(2_u64) as size_t as size_t;
+    } else if (*parser)
+        .raw_buffer
+        .last
+        .c_offset_from((*parser).raw_buffer.pointer) as libc::c_long
+        >= 3_i64
+        && memcmp(
+            (*parser).raw_buffer.pointer as *const libc::c_void,
+            BOM_UTF8 as *const libc::c_void,
+            3_u64,
+        ) == 0
+    {
+        (*parser).encoding = YAML_UTF8_ENCODING;
+        let fresh5 = addr_of_mut!((*parser).raw_buffer.pointer);
+        *fresh5 = (*fresh5).wrapping_offset(3_isize);
+        let fresh6 = addr_of_mut!((*parser).offset);
+        *fresh6 = (*fresh6 as libc::c_ulong).wrapping_add(3_u64) as size_t as size_t;
+    } else {
+        (*parser).encoding = YAML_UTF8_ENCODING;
+    }
+    OK
+}
+
+unsafe fn yaml_parser_update_raw_buffer(parser: *mut yaml_parser_t) -> Success {
+    let mut size_read: size_t = 0_u64;
+    if (*parser).raw_buffer.start == (*parser).raw_buffer.pointer
+        && (*parser).raw_buffer.last == (*parser).raw_buffer.end
+    {
+        return OK;
+    }
+    if (*parser).eof {
+        return OK;
+    }
+    if (*parser).raw_buffer.start < (*parser).raw_buffer.pointer
+        && (*parser).raw_buffer.pointer < (*parser).raw_buffer.last
+    {
+        memmove(
+            (*parser).raw_buffer.start as *mut libc::c_void,
+            (*parser).raw_buffer.pointer as *const libc::c_void,
+            (*parser)
+                .raw_buffer
+                .last
+                .c_offset_from((*parser).raw_buffer.pointer) as libc::c_long
+                as libc::c_ulong,
+        );
+    }
+    let fresh7 = addr_of_mut!((*parser).raw_buffer.last);
+    *fresh7 = (*fresh7).wrapping_offset(
+        -((*parser)
+            .raw_buffer
+            .pointer
+            .c_offset_from((*parser).raw_buffer.start) as libc::c_long as isize),
+    );
+    let fresh8 = addr_of_mut!((*parser).raw_buffer.pointer);
+    *fresh8 = (*parser).raw_buffer.start;
+    if (*parser).read_handler.expect("non-null function pointer")(
+        (*parser).read_handler_data,
+        (*parser).raw_buffer.last,
+        (*parser)
+            .raw_buffer
+            .end
+            .c_offset_from((*parser).raw_buffer.last) as libc::c_long as size_t,
+        addr_of_mut!(size_read),
+    ) == 0
+    {
+        return yaml_parser_set_reader_error(
+            parser,
+            b"input error\0" as *const u8 as *const libc::c_char,
+            (*parser).offset,
+            -1,
+        );
+    }
+    let fresh9 = addr_of_mut!((*parser).raw_buffer.last);
+    *fresh9 = (*fresh9).wrapping_offset(size_read as isize);
+    if size_read == 0 {
+        (*parser).eof = true;
+    }
+    OK
+}
+
+pub(crate) unsafe fn yaml_parser_update_buffer(
+    parser: *mut yaml_parser_t,
+    length: size_t,
+) -> Success {
+    let mut first = true;
+    __assert!(((*parser).read_handler).is_some());
+    if (*parser).eof && (*parser).raw_buffer.pointer == (*parser).raw_buffer.last {
+        return OK;
+    }
+    if (*parser).unread >= length {
+        return OK;
+    }
+    if (*parser).encoding == YAML_ANY_ENCODING {
+        if yaml_parser_determine_encoding(parser).fail {
+            return FAIL;
+        }
+    }
+    if (*parser).buffer.start < (*parser).buffer.pointer
+        && (*parser).buffer.pointer < (*parser).buffer.last
+    {
+        let size: size_t = (*parser)
+            .buffer
+            .last
+            .c_offset_from((*parser).buffer.pointer) as libc::c_long
+            as size_t;
+        memmove(
+            (*parser).buffer.start as *mut libc::c_void,
+            (*parser).buffer.pointer as *const libc::c_void,
+            size,
+        );
+        let fresh10 = addr_of_mut!((*parser).buffer.pointer);
+        *fresh10 = (*parser).buffer.start;
+        let fresh11 = addr_of_mut!((*parser).buffer.last);
+        *fresh11 = (*parser).buffer.start.wrapping_offset(size as isize);
+    } else if (*parser).buffer.pointer == (*parser).buffer.last {
+        let fresh12 = addr_of_mut!((*parser).buffer.pointer);
+        *fresh12 = (*parser).buffer.start;
+        let fresh13 = addr_of_mut!((*parser).buffer.last);
+        *fresh13 = (*parser).buffer.start;
+    }
+    while (*parser).unread < length {
+        if !first || (*parser).raw_buffer.pointer == (*parser).raw_buffer.last {
+            if yaml_parser_update_raw_buffer(parser).fail {
+                return FAIL;
+            }
+        }
+        first = false;
+        while (*parser).raw_buffer.pointer != (*parser).raw_buffer.last {
+            let mut value: libc::c_uint = 0;
+            let value2: libc::c_uint;
+            let mut incomplete = false;
+            let mut octet: libc::c_uchar;
+            let mut width: libc::c_uint = 0;
+            let low: libc::c_int;
+            let high: libc::c_int;
+            let mut k: size_t;
+            let raw_unread: size_t = (*parser)
+                .raw_buffer
+                .last
+                .c_offset_from((*parser).raw_buffer.pointer)
+                as libc::c_long as size_t;
+            match (*parser).encoding {
+                YAML_UTF8_ENCODING => {
+                    octet = *(*parser).raw_buffer.pointer;
+                    width = if octet & 0x80 == 0 {
+                        1
+                    } else if octet & 0xE0 == 0xC0 {
+                        2
+                    } else if octet & 0xF0 == 0xE0 {
+                        3
+                    } else if octet & 0xF8 == 0xF0 {
+                        4
+                    } else {
+                        0
+                    } as libc::c_uint;
+                    if width == 0 {
+                        return yaml_parser_set_reader_error(
+                            parser,
+                            b"invalid leading UTF-8 octet\0" as *const u8 as *const libc::c_char,
+                            (*parser).offset,
+                            octet as libc::c_int,
+                        );
+                    }
+                    if width as libc::c_ulong > raw_unread {
+                        if (*parser).eof {
+                            return yaml_parser_set_reader_error(
+                                parser,
+                                b"incomplete UTF-8 octet sequence\0" as *const u8
+                                    as *const libc::c_char,
+                                (*parser).offset,
+                                -1,
+                            );
+                        }
+                        incomplete = true;
+                    } else {
+                        value = if octet & 0x80 == 0 {
+                            octet & 0x7F
+                        } else if octet & 0xE0 == 0xC0 {
+                            octet & 0x1F
+                        } else if octet & 0xF0 == 0xE0 {
+                            octet & 0xF
+                        } else if octet & 0xF8 == 0xF0 {
+                            octet & 0x7
+                        } else {
+                            0
+                        } as libc::c_uint;
+                        k = 1_u64;
+                        while k < width as libc::c_ulong {
+                            octet = *(*parser).raw_buffer.pointer.wrapping_offset(k as isize);
+                            if octet & 0xC0 != 0x80 {
+                                return yaml_parser_set_reader_error(
+                                    parser,
+                                    b"invalid trailing UTF-8 octet\0" as *const u8
+                                        as *const libc::c_char,
+                                    (*parser).offset.wrapping_add(k),
+                                    octet as libc::c_int,
+                                );
+                            }
+                            value = (value << 6).wrapping_add((octet & 0x3F) as libc::c_uint);
+                            k = k.wrapping_add(1);
+                        }
+                        if !(width == 1
+                            || width == 2 && value >= 0x80
+                            || width == 3 && value >= 0x800
+                            || width == 4 && value >= 0x10000)
+                        {
+                            return yaml_parser_set_reader_error(
+                                parser,
+                                b"invalid length of a UTF-8 sequence\0" as *const u8
+                                    as *const libc::c_char,
+                                (*parser).offset,
+                                -1,
+                            );
+                        }
+                        if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
+                            return yaml_parser_set_reader_error(
+                                parser,
+                                b"invalid Unicode character\0" as *const u8 as *const libc::c_char,
+                                (*parser).offset,
+                                value as libc::c_int,
+                            );
+                        }
+                    }
+                }
+                YAML_UTF16LE_ENCODING | YAML_UTF16BE_ENCODING => {
+                    low = if (*parser).encoding == YAML_UTF16LE_ENCODING {
+                        0
+                    } else {
+                        1
+                    };
+                    high = if (*parser).encoding == YAML_UTF16LE_ENCODING {
+                        1
+                    } else {
+                        0
+                    };
+                    if raw_unread < 2_u64 {
+                        if (*parser).eof {
+                            return yaml_parser_set_reader_error(
+                                parser,
+                                b"incomplete UTF-16 character\0" as *const u8
+                                    as *const libc::c_char,
+                                (*parser).offset,
+                                -1,
+                            );
+                        }
+                        incomplete = true;
+                    } else {
+                        value = (*(*parser).raw_buffer.pointer.wrapping_offset(low as isize)
+                            as libc::c_int
+                            + ((*(*parser).raw_buffer.pointer.wrapping_offset(high as isize)
+                                as libc::c_int)
+                                << 8)) as libc::c_uint;
+                        if value & 0xFC00 == 0xDC00 {
+                            return yaml_parser_set_reader_error(
+                                parser,
+                                b"unexpected low surrogate area\0" as *const u8
+                                    as *const libc::c_char,
+                                (*parser).offset,
+                                value as libc::c_int,
+                            );
+                        }
+                        if value & 0xFC00 == 0xD800 {
+                            width = 4;
+                            if raw_unread < 4_u64 {
+                                if (*parser).eof {
+                                    return yaml_parser_set_reader_error(
+                                        parser,
+                                        b"incomplete UTF-16 surrogate pair\0" as *const u8
+                                            as *const libc::c_char,
+                                        (*parser).offset,
+                                        -1,
+                                    );
+                                }
+                                incomplete = true;
+                            } else {
+                                value2 = (*(*parser)
+                                    .raw_buffer
+                                    .pointer
+                                    .wrapping_offset((low + 2) as isize)
+                                    as libc::c_int
+                                    + ((*(*parser)
+                                        .raw_buffer
+                                        .pointer
+                                        .wrapping_offset((high + 2) as isize)
+                                        as libc::c_int)
+                                        << 8))
+                                    as libc::c_uint;
+                                if value2 & 0xFC00 != 0xDC00 {
+                                    return yaml_parser_set_reader_error(
+                                        parser,
+                                        b"expected low surrogate area\0" as *const u8
+                                            as *const libc::c_char,
+                                        (*parser).offset.wrapping_add(2_u64),
+                                        value2 as libc::c_int,
+                                    );
+                                }
+                                value = 0x10000_u32
+                                    .wrapping_add((value & 0x3FF) << 10)
+                                    .wrapping_add(value2 & 0x3FF);
+                            }
+                        } else {
+                            width = 2;
+                        }
+                    }
+                }
+                _ => {}
+            }
+            if incomplete {
+                break;
+            }
+            if !(value == 0x9
+                || value == 0xA
+                || value == 0xD
+                || value >= 0x20 && value <= 0x7E
+                || value == 0x85
+                || value >= 0xA0 && value <= 0xD7FF
+                || value >= 0xE000 && value <= 0xFFFD
+                || value >= 0x10000 && value <= 0x10FFFF)
+            {
+                return yaml_parser_set_reader_error(
+                    parser,
+                    b"control characters are not allowed\0" as *const u8 as *const libc::c_char,
+                    (*parser).offset,
+                    value as libc::c_int,
+                );
+            }
+            let fresh14 = addr_of_mut!((*parser).raw_buffer.pointer);
+            *fresh14 = (*fresh14).wrapping_offset(width as isize);
+            let fresh15 = addr_of_mut!((*parser).offset);
+            *fresh15 = (*fresh15 as libc::c_ulong).wrapping_add(width as libc::c_ulong) as size_t
+                as size_t;
+            if value <= 0x7F {
+                let fresh16 = addr_of_mut!((*parser).buffer.last);
+                let fresh17 = *fresh16;
+                *fresh16 = (*fresh16).wrapping_offset(1);
+                *fresh17 = value as yaml_char_t;
+            } else if value <= 0x7FF {
+                let fresh18 = addr_of_mut!((*parser).buffer.last);
+                let fresh19 = *fresh18;
+                *fresh18 = (*fresh18).wrapping_offset(1);
+                *fresh19 = 0xC0_u32.wrapping_add(value >> 6) as yaml_char_t;
+                let fresh20 = addr_of_mut!((*parser).buffer.last);
+                let fresh21 = *fresh20;
+                *fresh20 = (*fresh20).wrapping_offset(1);
+                *fresh21 = 0x80_u32.wrapping_add(value & 0x3F) as yaml_char_t;
+            } else if value <= 0xFFFF {
+                let fresh22 = addr_of_mut!((*parser).buffer.last);
+                let fresh23 = *fresh22;
+                *fresh22 = (*fresh22).wrapping_offset(1);
+                *fresh23 = 0xE0_u32.wrapping_add(value >> 12) as yaml_char_t;
+                let fresh24 = addr_of_mut!((*parser).buffer.last);
+                let fresh25 = *fresh24;
+                *fresh24 = (*fresh24).wrapping_offset(1);
+                *fresh25 = 0x80_u32.wrapping_add(value >> 6 & 0x3F) as yaml_char_t;
+                let fresh26 = addr_of_mut!((*parser).buffer.last);
+                let fresh27 = *fresh26;
+                *fresh26 = (*fresh26).wrapping_offset(1);
+                *fresh27 = 0x80_u32.wrapping_add(value & 0x3F) as yaml_char_t;
+            } else {
+                let fresh28 = addr_of_mut!((*parser).buffer.last);
+                let fresh29 = *fresh28;
+                *fresh28 = (*fresh28).wrapping_offset(1);
+                *fresh29 = 0xF0_u32.wrapping_add(value >> 18) as yaml_char_t;
+                let fresh30 = addr_of_mut!((*parser).buffer.last);
+                let fresh31 = *fresh30;
+                *fresh30 = (*fresh30).wrapping_offset(1);
+                *fresh31 = 0x80_u32.wrapping_add(value >> 12 & 0x3F) as yaml_char_t;
+                let fresh32 = addr_of_mut!((*parser).buffer.last);
+                let fresh33 = *fresh32;
+                *fresh32 = (*fresh32).wrapping_offset(1);
+                *fresh33 = 0x80_u32.wrapping_add(value >> 6 & 0x3F) as yaml_char_t;
+                let fresh34 = addr_of_mut!((*parser).buffer.last);
+                let fresh35 = *fresh34;
+                *fresh34 = (*fresh34).wrapping_offset(1);
+                *fresh35 = 0x80_u32.wrapping_add(value & 0x3F) as yaml_char_t;
+            }
+            let fresh36 = addr_of_mut!((*parser).unread);
+            *fresh36 = (*fresh36).wrapping_add(1);
+        }
+        if (*parser).eof {
+            let fresh37 = addr_of_mut!((*parser).buffer.last);
+            let fresh38 = *fresh37;
+            *fresh37 = (*fresh37).wrapping_offset(1);
+            *fresh38 = b'\0';
+            let fresh39 = addr_of_mut!((*parser).unread);
+            *fresh39 = (*fresh39).wrapping_add(1);
+            return OK;
+        }
+    }
+    if (*parser).offset >= (!0_u64).wrapping_div(2_u64) {
+        return yaml_parser_set_reader_error(
+            parser,
+            b"input is too long\0" as *const u8 as *const libc::c_char,
+            (*parser).offset,
+            -1,
+        );
+    }
+    OK
+}
diff --git a/src/scanner.rs b/src/scanner.rs
new file mode 100644
index 0000000..175719c
--- /dev/null
+++ b/src/scanner.rs
@@ -0,0 +1,2663 @@
+use crate::api::{
+    yaml_free, yaml_malloc, yaml_queue_extend, yaml_stack_extend, yaml_string_extend,
+    yaml_string_join,
+};
+use crate::externs::{memcpy, memmove, memset, strcmp, strlen};
+use crate::reader::yaml_parser_update_buffer;
+use crate::success::{Success, FAIL, OK};
+use crate::yaml::{ptrdiff_t, size_t, yaml_char_t, yaml_string_t, NULL_STRING};
+use crate::{
+    libc, yaml_mark_t, yaml_parser_t, yaml_simple_key_t, yaml_token_t, yaml_token_type_t,
+    PointerExt, YAML_ALIAS_TOKEN, YAML_ANCHOR_TOKEN, YAML_BLOCK_END_TOKEN, YAML_BLOCK_ENTRY_TOKEN,
+    YAML_BLOCK_MAPPING_START_TOKEN, YAML_BLOCK_SEQUENCE_START_TOKEN, YAML_DOCUMENT_END_TOKEN,
+    YAML_DOCUMENT_START_TOKEN, YAML_DOUBLE_QUOTED_SCALAR_STYLE, YAML_FLOW_ENTRY_TOKEN,
+    YAML_FLOW_MAPPING_END_TOKEN, YAML_FLOW_MAPPING_START_TOKEN, YAML_FLOW_SEQUENCE_END_TOKEN,
+    YAML_FLOW_SEQUENCE_START_TOKEN, YAML_FOLDED_SCALAR_STYLE, YAML_KEY_TOKEN,
+    YAML_LITERAL_SCALAR_STYLE, YAML_MEMORY_ERROR, YAML_NO_ERROR, YAML_PLAIN_SCALAR_STYLE,
+    YAML_SCALAR_TOKEN, YAML_SCANNER_ERROR, YAML_SINGLE_QUOTED_SCALAR_STYLE, YAML_STREAM_END_TOKEN,
+    YAML_STREAM_START_TOKEN, YAML_TAG_DIRECTIVE_TOKEN, YAML_TAG_TOKEN, YAML_VALUE_TOKEN,
+    YAML_VERSION_DIRECTIVE_TOKEN,
+};
+use core::mem::{size_of, MaybeUninit};
+use core::ptr::{self, addr_of_mut};
+
+unsafe fn CACHE(parser: *mut yaml_parser_t, length: size_t) -> Success {
+    if (*parser).unread >= length {
+        OK
+    } else {
+        yaml_parser_update_buffer(parser, length)
+    }
+}
+
+unsafe fn SKIP(parser: *mut yaml_parser_t) {
+    let width = WIDTH!((*parser).buffer);
+    (*parser).mark.index = (*parser).mark.index.wrapping_add(width as u64);
+    (*parser).mark.column = (*parser).mark.column.wrapping_add(1);
+    (*parser).unread = (*parser).unread.wrapping_sub(1);
+    (*parser).buffer.pointer = (*parser).buffer.pointer.wrapping_offset(width as isize);
+}
+
+unsafe fn SKIP_LINE(parser: *mut yaml_parser_t) {
+    if IS_CRLF!((*parser).buffer) {
+        (*parser).mark.index = (*parser).mark.index.wrapping_add(2);
+        (*parser).mark.column = 0;
+        (*parser).mark.line = (*parser).mark.line.wrapping_add(1);
+        (*parser).unread = (*parser).unread.wrapping_sub(2);
+        (*parser).buffer.pointer = (*parser).buffer.pointer.wrapping_offset(2);
+    } else if IS_BREAK!((*parser).buffer) {
+        let width = WIDTH!((*parser).buffer);
+        (*parser).mark.index = (*parser).mark.index.wrapping_add(width as u64);
+        (*parser).mark.column = 0;
+        (*parser).mark.line = (*parser).mark.line.wrapping_add(1);
+        (*parser).unread = (*parser).unread.wrapping_sub(1);
+        (*parser).buffer.pointer = (*parser).buffer.pointer.wrapping_offset(width as isize);
+    };
+}
+
+unsafe fn READ(parser: *mut yaml_parser_t, string: *mut yaml_string_t) {
+    STRING_EXTEND!(*string);
+    let width = WIDTH!((*parser).buffer);
+    COPY!(*string, (*parser).buffer);
+    (*parser).mark.index = (*parser).mark.index.wrapping_add(width as u64);
+    (*parser).mark.column = (*parser).mark.column.wrapping_add(1);
+    (*parser).unread = (*parser).unread.wrapping_sub(1);
+}
+
+unsafe fn READ_LINE(parser: *mut yaml_parser_t, string: *mut yaml_string_t) {
+    STRING_EXTEND!(*string);
+    if CHECK_AT!((*parser).buffer, b'\r', 0) && CHECK_AT!((*parser).buffer, b'\n', 1) {
+        *(*string).pointer = b'\n';
+        (*string).pointer = (*string).pointer.wrapping_offset(1);
+        (*parser).buffer.pointer = (*parser).buffer.pointer.wrapping_offset(2);
+        (*parser).mark.index = (*parser).mark.index.wrapping_add(2);
+        (*parser).mark.column = 0;
+        (*parser).mark.line = (*parser).mark.line.wrapping_add(1);
+        (*parser).unread = (*parser).unread.wrapping_sub(2);
+    } else if CHECK_AT!((*parser).buffer, b'\r', 0) || CHECK_AT!((*parser).buffer, b'\n', 0) {
+        *(*string).pointer = b'\n';
+        (*string).pointer = (*string).pointer.wrapping_offset(1);
+        (*parser).buffer.pointer = (*parser).buffer.pointer.wrapping_offset(1);
+        (*parser).mark.index = (*parser).mark.index.wrapping_add(1);
+        (*parser).mark.column = 0;
+        (*parser).mark.line = (*parser).mark.line.wrapping_add(1);
+        (*parser).unread = (*parser).unread.wrapping_sub(1);
+    } else if CHECK_AT!((*parser).buffer, b'\xC2', 0) && CHECK_AT!((*parser).buffer, b'\x85', 1) {
+        *(*string).pointer = b'\n';
+        (*string).pointer = (*string).pointer.wrapping_offset(1);
+        (*parser).buffer.pointer = (*parser).buffer.pointer.wrapping_offset(2);
+        (*parser).mark.index = (*parser).mark.index.wrapping_add(2);
+        (*parser).mark.column = 0;
+        (*parser).mark.line = (*parser).mark.line.wrapping_add(1);
+        (*parser).unread = (*parser).unread.wrapping_sub(1);
+    } else if CHECK_AT!((*parser).buffer, b'\xE2', 0)
+        && CHECK_AT!((*parser).buffer, b'\x80', 1)
+        && (CHECK_AT!((*parser).buffer, b'\xA8', 2) || CHECK_AT!((*parser).buffer, b'\xA9', 2))
+    {
+        *(*string).pointer = *(*parser).buffer.pointer;
+        (*string).pointer = (*string).pointer.wrapping_offset(1);
+        (*parser).buffer.pointer = (*parser).buffer.pointer.wrapping_offset(1);
+        *(*string).pointer = *(*parser).buffer.pointer;
+        (*string).pointer = (*string).pointer.wrapping_offset(1);
+        (*parser).buffer.pointer = (*parser).buffer.pointer.wrapping_offset(1);
+        *(*string).pointer = *(*parser).buffer.pointer;
+        (*string).pointer = (*string).pointer.wrapping_offset(1);
+        (*parser).buffer.pointer = (*parser).buffer.pointer.wrapping_offset(1);
+        (*parser).mark.index = (*parser).mark.index.wrapping_add(3);
+        (*parser).mark.column = 0;
+        (*parser).mark.line = (*parser).mark.line.wrapping_add(1);
+        (*parser).unread = (*parser).unread.wrapping_sub(1);
+    };
+}
+
+macro_rules! READ {
+    ($parser:expr, $string:expr) => {
+        READ($parser, addr_of_mut!($string))
+    };
+}
+
+macro_rules! READ_LINE {
+    ($parser:expr, $string:expr) => {
+        READ_LINE($parser, addr_of_mut!($string))
+    };
+}
+
+/// Scan the input stream and produce the next token.
+///
+/// Call the function subsequently to produce a sequence of tokens corresponding
+/// to the input stream. The initial token has the type YAML_STREAM_START_TOKEN
+/// while the ending token has the type YAML_STREAM_END_TOKEN.
+///
+/// An application is responsible for freeing any buffers associated with the
+/// produced token object using the yaml_token_delete function.
+///
+/// An application must not alternate the calls of yaml_parser_scan() with the
+/// calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break
+/// the parser.
+pub unsafe fn yaml_parser_scan(parser: *mut yaml_parser_t, token: *mut yaml_token_t) -> Success {
+    __assert!(!parser.is_null());
+    __assert!(!token.is_null());
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+    if (*parser).stream_end_produced || (*parser).error != YAML_NO_ERROR {
+        return OK;
+    }
+    if !(*parser).token_available {
+        if yaml_parser_fetch_more_tokens(parser).fail {
+            return FAIL;
+        }
+    }
+    *token = DEQUEUE!((*parser).tokens);
+    (*parser).token_available = false;
+    let fresh2 = addr_of_mut!((*parser).tokens_parsed);
+    *fresh2 = (*fresh2).wrapping_add(1);
+    if (*token).type_ == YAML_STREAM_END_TOKEN {
+        (*parser).stream_end_produced = true;
+    }
+    OK
+}
+
+unsafe fn yaml_parser_set_scanner_error(
+    parser: *mut yaml_parser_t,
+    context: *const libc::c_char,
+    context_mark: yaml_mark_t,
+    problem: *const libc::c_char,
+) {
+    (*parser).error = YAML_SCANNER_ERROR;
+    let fresh3 = addr_of_mut!((*parser).context);
+    *fresh3 = context;
+    (*parser).context_mark = context_mark;
+    let fresh4 = addr_of_mut!((*parser).problem);
+    *fresh4 = problem;
+    (*parser).problem_mark = (*parser).mark;
+}
+
+pub(crate) unsafe fn yaml_parser_fetch_more_tokens(parser: *mut yaml_parser_t) -> Success {
+    let mut need_more_tokens;
+    loop {
+        need_more_tokens = false;
+        if (*parser).tokens.head == (*parser).tokens.tail {
+            need_more_tokens = true;
+        } else {
+            let mut simple_key: *mut yaml_simple_key_t;
+            if yaml_parser_stale_simple_keys(parser).fail {
+                return FAIL;
+            }
+            simple_key = (*parser).simple_keys.start;
+            while simple_key != (*parser).simple_keys.top {
+                if (*simple_key).possible && (*simple_key).token_number == (*parser).tokens_parsed {
+                    need_more_tokens = true;
+                    break;
+                } else {
+                    simple_key = simple_key.wrapping_offset(1);
+                }
+            }
+        }
+        if !need_more_tokens {
+            break;
+        }
+        if yaml_parser_fetch_next_token(parser).fail {
+            return FAIL;
+        }
+    }
+    (*parser).token_available = true;
+    OK
+}
+
+unsafe fn yaml_parser_fetch_next_token(parser: *mut yaml_parser_t) -> Success {
+    if CACHE(parser, 1_u64).fail {
+        return FAIL;
+    }
+    if !(*parser).stream_start_produced {
+        yaml_parser_fetch_stream_start(parser);
+        return OK;
+    }
+    if yaml_parser_scan_to_next_token(parser).fail {
+        return FAIL;
+    }
+    if yaml_parser_stale_simple_keys(parser).fail {
+        return FAIL;
+    }
+    yaml_parser_unroll_indent(parser, (*parser).mark.column as ptrdiff_t);
+    if CACHE(parser, 4_u64).fail {
+        return FAIL;
+    }
+    if IS_Z!((*parser).buffer) {
+        return yaml_parser_fetch_stream_end(parser);
+    }
+    if (*parser).mark.column == 0_u64 && CHECK!((*parser).buffer, b'%') {
+        return yaml_parser_fetch_directive(parser);
+    }
+    if (*parser).mark.column == 0_u64
+        && CHECK_AT!((*parser).buffer, b'-', 0)
+        && CHECK_AT!((*parser).buffer, b'-', 1)
+        && CHECK_AT!((*parser).buffer, b'-', 2)
+        && IS_BLANKZ_AT!((*parser).buffer, 3)
+    {
+        return yaml_parser_fetch_document_indicator(parser, YAML_DOCUMENT_START_TOKEN);
+    }
+    if (*parser).mark.column == 0_u64
+        && CHECK_AT!((*parser).buffer, b'.', 0)
+        && CHECK_AT!((*parser).buffer, b'.', 1)
+        && CHECK_AT!((*parser).buffer, b'.', 2)
+        && IS_BLANKZ_AT!((*parser).buffer, 3)
+    {
+        return yaml_parser_fetch_document_indicator(parser, YAML_DOCUMENT_END_TOKEN);
+    }
+    if CHECK!((*parser).buffer, b'[') {
+        return yaml_parser_fetch_flow_collection_start(parser, YAML_FLOW_SEQUENCE_START_TOKEN);
+    }
+    if CHECK!((*parser).buffer, b'{') {
+        return yaml_parser_fetch_flow_collection_start(parser, YAML_FLOW_MAPPING_START_TOKEN);
+    }
+    if CHECK!((*parser).buffer, b']') {
+        return yaml_parser_fetch_flow_collection_end(parser, YAML_FLOW_SEQUENCE_END_TOKEN);
+    }
+    if CHECK!((*parser).buffer, b'}') {
+        return yaml_parser_fetch_flow_collection_end(parser, YAML_FLOW_MAPPING_END_TOKEN);
+    }
+    if CHECK!((*parser).buffer, b',') {
+        return yaml_parser_fetch_flow_entry(parser);
+    }
+    if CHECK!((*parser).buffer, b'-') && IS_BLANKZ_AT!((*parser).buffer, 1) {
+        return yaml_parser_fetch_block_entry(parser);
+    }
+    if CHECK!((*parser).buffer, b'?')
+        && ((*parser).flow_level != 0 || IS_BLANKZ_AT!((*parser).buffer, 1))
+    {
+        return yaml_parser_fetch_key(parser);
+    }
+    if CHECK!((*parser).buffer, b':')
+        && ((*parser).flow_level != 0 || IS_BLANKZ_AT!((*parser).buffer, 1))
+    {
+        return yaml_parser_fetch_value(parser);
+    }
+    if CHECK!((*parser).buffer, b'*') {
+        return yaml_parser_fetch_anchor(parser, YAML_ALIAS_TOKEN);
+    }
+    if CHECK!((*parser).buffer, b'&') {
+        return yaml_parser_fetch_anchor(parser, YAML_ANCHOR_TOKEN);
+    }
+    if CHECK!((*parser).buffer, b'!') {
+        return yaml_parser_fetch_tag(parser);
+    }
+    if CHECK!((*parser).buffer, b'|') && (*parser).flow_level == 0 {
+        return yaml_parser_fetch_block_scalar(parser, true);
+    }
+    if CHECK!((*parser).buffer, b'>') && (*parser).flow_level == 0 {
+        return yaml_parser_fetch_block_scalar(parser, false);
+    }
+    if CHECK!((*parser).buffer, b'\'') {
+        return yaml_parser_fetch_flow_scalar(parser, true);
+    }
+    if CHECK!((*parser).buffer, b'"') {
+        return yaml_parser_fetch_flow_scalar(parser, false);
+    }
+    if !(IS_BLANKZ!((*parser).buffer)
+        || CHECK!((*parser).buffer, b'-')
+        || CHECK!((*parser).buffer, b'?')
+        || CHECK!((*parser).buffer, b':')
+        || CHECK!((*parser).buffer, b',')
+        || CHECK!((*parser).buffer, b'[')
+        || CHECK!((*parser).buffer, b']')
+        || CHECK!((*parser).buffer, b'{')
+        || CHECK!((*parser).buffer, b'}')
+        || CHECK!((*parser).buffer, b'#')
+        || CHECK!((*parser).buffer, b'&')
+        || CHECK!((*parser).buffer, b'*')
+        || CHECK!((*parser).buffer, b'!')
+        || CHECK!((*parser).buffer, b'|')
+        || CHECK!((*parser).buffer, b'>')
+        || CHECK!((*parser).buffer, b'\'')
+        || CHECK!((*parser).buffer, b'"')
+        || CHECK!((*parser).buffer, b'%')
+        || CHECK!((*parser).buffer, b'@')
+        || CHECK!((*parser).buffer, b'`'))
+        || CHECK!((*parser).buffer, b'-') && !IS_BLANK_AT!((*parser).buffer, 1)
+        || (*parser).flow_level == 0
+            && (CHECK!((*parser).buffer, b'?') || CHECK!((*parser).buffer, b':'))
+            && !IS_BLANKZ_AT!((*parser).buffer, 1)
+    {
+        return yaml_parser_fetch_plain_scalar(parser);
+    }
+    yaml_parser_set_scanner_error(
+        parser,
+        b"while scanning for the next token\0" as *const u8 as *const libc::c_char,
+        (*parser).mark,
+        b"found character that cannot start any token\0" as *const u8 as *const libc::c_char,
+    );
+    FAIL
+}
+
+unsafe fn yaml_parser_stale_simple_keys(parser: *mut yaml_parser_t) -> Success {
+    let mut simple_key: *mut yaml_simple_key_t;
+    simple_key = (*parser).simple_keys.start;
+    while simple_key != (*parser).simple_keys.top {
+        if (*simple_key).possible
+            && ((*simple_key).mark.line < (*parser).mark.line
+                || (*simple_key).mark.index.wrapping_add(1024_u64) < (*parser).mark.index)
+        {
+            if (*simple_key).required {
+                yaml_parser_set_scanner_error(
+                    parser,
+                    b"while scanning a simple key\0" as *const u8 as *const libc::c_char,
+                    (*simple_key).mark,
+                    b"could not find expected ':'\0" as *const u8 as *const libc::c_char,
+                );
+                return FAIL;
+            }
+            (*simple_key).possible = false;
+        }
+        simple_key = simple_key.wrapping_offset(1);
+    }
+    OK
+}
+
+unsafe fn yaml_parser_save_simple_key(parser: *mut yaml_parser_t) -> Success {
+    let required = (*parser).flow_level == 0
+        && (*parser).indent as libc::c_long == (*parser).mark.column as ptrdiff_t;
+    if (*parser).simple_key_allowed {
+        let simple_key = yaml_simple_key_t {
+            possible: true,
+            required,
+            token_number: (*parser)
+                .tokens_parsed
+                .wrapping_add((*parser).tokens.tail.c_offset_from((*parser).tokens.head)
+                    as libc::c_long as libc::c_ulong),
+            mark: (*parser).mark,
+        };
+        if yaml_parser_remove_simple_key(parser).fail {
+            return FAIL;
+        }
+        *(*parser).simple_keys.top.wrapping_offset(-1_isize) = simple_key;
+    }
+    OK
+}
+
+unsafe fn yaml_parser_remove_simple_key(parser: *mut yaml_parser_t) -> Success {
+    let simple_key: *mut yaml_simple_key_t = (*parser).simple_keys.top.wrapping_offset(-1_isize);
+    if (*simple_key).possible {
+        if (*simple_key).required {
+            yaml_parser_set_scanner_error(
+                parser,
+                b"while scanning a simple key\0" as *const u8 as *const libc::c_char,
+                (*simple_key).mark,
+                b"could not find expected ':'\0" as *const u8 as *const libc::c_char,
+            );
+            return FAIL;
+        }
+    }
+    (*simple_key).possible = false;
+    OK
+}
+
+unsafe fn yaml_parser_increase_flow_level(parser: *mut yaml_parser_t) -> Success {
+    let empty_simple_key = yaml_simple_key_t {
+        possible: false,
+        required: false,
+        token_number: 0_u64,
+        mark: yaml_mark_t {
+            index: 0_u64,
+            line: 0_u64,
+            column: 0_u64,
+        },
+    };
+    PUSH!((*parser).simple_keys, empty_simple_key);
+    if (*parser).flow_level == libc::c_int::MAX {
+        (*parser).error = YAML_MEMORY_ERROR;
+        return FAIL;
+    }
+    let fresh7 = addr_of_mut!((*parser).flow_level);
+    *fresh7 += 1;
+    OK
+}
+
+unsafe fn yaml_parser_decrease_flow_level(parser: *mut yaml_parser_t) {
+    if (*parser).flow_level != 0 {
+        let fresh8 = addr_of_mut!((*parser).flow_level);
+        *fresh8 -= 1;
+        let _ = POP!((*parser).simple_keys);
+    }
+}
+
+unsafe fn yaml_parser_roll_indent(
+    parser: *mut yaml_parser_t,
+    column: ptrdiff_t,
+    number: ptrdiff_t,
+    type_: yaml_token_type_t,
+    mark: yaml_mark_t,
+) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if (*parser).flow_level != 0 {
+        return OK;
+    }
+    if ((*parser).indent as libc::c_long) < column {
+        PUSH!((*parser).indents, (*parser).indent);
+        if column > ptrdiff_t::from(libc::c_int::MAX) {
+            (*parser).error = YAML_MEMORY_ERROR;
+            return FAIL;
+        }
+        (*parser).indent = column as libc::c_int;
+        memset(
+            token as *mut libc::c_void,
+            0,
+            size_of::<yaml_token_t>() as libc::c_ulong,
+        );
+        (*token).type_ = type_;
+        (*token).start_mark = mark;
+        (*token).end_mark = mark;
+        if number == -1_i64 {
+            ENQUEUE!((*parser).tokens, *token);
+        } else {
+            QUEUE_INSERT!(
+                (*parser).tokens,
+                (number as libc::c_ulong).wrapping_sub((*parser).tokens_parsed),
+                *token
+            );
+        }
+    }
+    OK
+}
+
+unsafe fn yaml_parser_unroll_indent(parser: *mut yaml_parser_t, column: ptrdiff_t) {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if (*parser).flow_level != 0 {
+        return;
+    }
+    while (*parser).indent as libc::c_long > column {
+        memset(
+            token as *mut libc::c_void,
+            0,
+            size_of::<yaml_token_t>() as libc::c_ulong,
+        );
+        (*token).type_ = YAML_BLOCK_END_TOKEN;
+        (*token).start_mark = (*parser).mark;
+        (*token).end_mark = (*parser).mark;
+        ENQUEUE!((*parser).tokens, *token);
+        (*parser).indent = POP!((*parser).indents);
+    }
+}
+
+unsafe fn yaml_parser_fetch_stream_start(parser: *mut yaml_parser_t) {
+    let simple_key = yaml_simple_key_t {
+        possible: false,
+        required: false,
+        token_number: 0_u64,
+        mark: yaml_mark_t {
+            index: 0_u64,
+            line: 0_u64,
+            column: 0_u64,
+        },
+    };
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    (*parser).indent = -1;
+    PUSH!((*parser).simple_keys, simple_key);
+    (*parser).simple_key_allowed = true;
+    (*parser).stream_start_produced = true;
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+    (*token).type_ = YAML_STREAM_START_TOKEN;
+    (*token).start_mark = (*parser).mark;
+    (*token).end_mark = (*parser).mark;
+    (*token).data.stream_start.encoding = (*parser).encoding;
+    ENQUEUE!((*parser).tokens, *token);
+}
+
+unsafe fn yaml_parser_fetch_stream_end(parser: *mut yaml_parser_t) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if (*parser).mark.column != 0_u64 {
+        (*parser).mark.column = 0_u64;
+        let fresh22 = addr_of_mut!((*parser).mark.line);
+        *fresh22 = (*fresh22).wrapping_add(1);
+    }
+    yaml_parser_unroll_indent(parser, -1_i64);
+    if yaml_parser_remove_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = false;
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+    (*token).type_ = YAML_STREAM_END_TOKEN;
+    (*token).start_mark = (*parser).mark;
+    (*token).end_mark = (*parser).mark;
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_directive(parser: *mut yaml_parser_t) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    yaml_parser_unroll_indent(parser, -1_i64);
+    if yaml_parser_remove_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = false;
+    if yaml_parser_scan_directive(parser, token).fail {
+        return FAIL;
+    }
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_document_indicator(
+    parser: *mut yaml_parser_t,
+    type_: yaml_token_type_t,
+) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    yaml_parser_unroll_indent(parser, -1_i64);
+    if yaml_parser_remove_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = false;
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    SKIP(parser);
+    SKIP(parser);
+    let end_mark: yaml_mark_t = (*parser).mark;
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+    (*token).type_ = type_;
+    (*token).start_mark = start_mark;
+    (*token).end_mark = end_mark;
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_flow_collection_start(
+    parser: *mut yaml_parser_t,
+    type_: yaml_token_type_t,
+) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if yaml_parser_save_simple_key(parser).fail {
+        return FAIL;
+    }
+    if yaml_parser_increase_flow_level(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = true;
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    let end_mark: yaml_mark_t = (*parser).mark;
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+    (*token).type_ = type_;
+    (*token).start_mark = start_mark;
+    (*token).end_mark = end_mark;
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_flow_collection_end(
+    parser: *mut yaml_parser_t,
+    type_: yaml_token_type_t,
+) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if yaml_parser_remove_simple_key(parser).fail {
+        return FAIL;
+    }
+    yaml_parser_decrease_flow_level(parser);
+    (*parser).simple_key_allowed = false;
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    let end_mark: yaml_mark_t = (*parser).mark;
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+    (*token).type_ = type_;
+    (*token).start_mark = start_mark;
+    (*token).end_mark = end_mark;
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_flow_entry(parser: *mut yaml_parser_t) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if yaml_parser_remove_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = true;
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    let end_mark: yaml_mark_t = (*parser).mark;
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+    (*token).type_ = YAML_FLOW_ENTRY_TOKEN;
+    (*token).start_mark = start_mark;
+    (*token).end_mark = end_mark;
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_block_entry(parser: *mut yaml_parser_t) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if (*parser).flow_level == 0 {
+        if !(*parser).simple_key_allowed {
+            yaml_parser_set_scanner_error(
+                parser,
+                ptr::null::<libc::c_char>(),
+                (*parser).mark,
+                b"block sequence entries are not allowed in this context\0" as *const u8
+                    as *const libc::c_char,
+            );
+            return FAIL;
+        }
+        if yaml_parser_roll_indent(
+            parser,
+            (*parser).mark.column as ptrdiff_t,
+            -1_i64,
+            YAML_BLOCK_SEQUENCE_START_TOKEN,
+            (*parser).mark,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+    }
+    if yaml_parser_remove_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = true;
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    let end_mark: yaml_mark_t = (*parser).mark;
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+    (*token).type_ = YAML_BLOCK_ENTRY_TOKEN;
+    (*token).start_mark = start_mark;
+    (*token).end_mark = end_mark;
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_key(parser: *mut yaml_parser_t) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if (*parser).flow_level == 0 {
+        if !(*parser).simple_key_allowed {
+            yaml_parser_set_scanner_error(
+                parser,
+                ptr::null::<libc::c_char>(),
+                (*parser).mark,
+                b"mapping keys are not allowed in this context\0" as *const u8
+                    as *const libc::c_char,
+            );
+            return FAIL;
+        }
+        if yaml_parser_roll_indent(
+            parser,
+            (*parser).mark.column as ptrdiff_t,
+            -1_i64,
+            YAML_BLOCK_MAPPING_START_TOKEN,
+            (*parser).mark,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+    }
+    if yaml_parser_remove_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = (*parser).flow_level == 0;
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    let end_mark: yaml_mark_t = (*parser).mark;
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+    (*token).type_ = YAML_KEY_TOKEN;
+    (*token).start_mark = start_mark;
+    (*token).end_mark = end_mark;
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_value(parser: *mut yaml_parser_t) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    let simple_key: *mut yaml_simple_key_t = (*parser).simple_keys.top.wrapping_offset(-1_isize);
+    if (*simple_key).possible {
+        memset(
+            token as *mut libc::c_void,
+            0,
+            size_of::<yaml_token_t>() as libc::c_ulong,
+        );
+        (*token).type_ = YAML_KEY_TOKEN;
+        (*token).start_mark = (*simple_key).mark;
+        (*token).end_mark = (*simple_key).mark;
+        QUEUE_INSERT!(
+            (*parser).tokens,
+            ((*simple_key).token_number).wrapping_sub((*parser).tokens_parsed),
+            *token
+        );
+        if yaml_parser_roll_indent(
+            parser,
+            (*simple_key).mark.column as ptrdiff_t,
+            (*simple_key).token_number as ptrdiff_t,
+            YAML_BLOCK_MAPPING_START_TOKEN,
+            (*simple_key).mark,
+        )
+        .fail
+        {
+            return FAIL;
+        }
+        (*simple_key).possible = false;
+        (*parser).simple_key_allowed = false;
+    } else {
+        if (*parser).flow_level == 0 {
+            if !(*parser).simple_key_allowed {
+                yaml_parser_set_scanner_error(
+                    parser,
+                    ptr::null::<libc::c_char>(),
+                    (*parser).mark,
+                    b"mapping values are not allowed in this context\0" as *const u8
+                        as *const libc::c_char,
+                );
+                return FAIL;
+            }
+            if yaml_parser_roll_indent(
+                parser,
+                (*parser).mark.column as ptrdiff_t,
+                -1_i64,
+                YAML_BLOCK_MAPPING_START_TOKEN,
+                (*parser).mark,
+            )
+            .fail
+            {
+                return FAIL;
+            }
+        }
+        (*parser).simple_key_allowed = (*parser).flow_level == 0;
+    }
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    let end_mark: yaml_mark_t = (*parser).mark;
+    memset(
+        token as *mut libc::c_void,
+        0,
+        size_of::<yaml_token_t>() as libc::c_ulong,
+    );
+    (*token).type_ = YAML_VALUE_TOKEN;
+    (*token).start_mark = start_mark;
+    (*token).end_mark = end_mark;
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_anchor(
+    parser: *mut yaml_parser_t,
+    type_: yaml_token_type_t,
+) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if yaml_parser_save_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = false;
+    if yaml_parser_scan_anchor(parser, token, type_).fail {
+        return FAIL;
+    }
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_tag(parser: *mut yaml_parser_t) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if yaml_parser_save_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = false;
+    if yaml_parser_scan_tag(parser, token).fail {
+        return FAIL;
+    }
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_block_scalar(parser: *mut yaml_parser_t, literal: bool) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if yaml_parser_remove_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = true;
+    if yaml_parser_scan_block_scalar(parser, token, literal).fail {
+        return FAIL;
+    }
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_flow_scalar(parser: *mut yaml_parser_t, single: bool) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if yaml_parser_save_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = false;
+    if yaml_parser_scan_flow_scalar(parser, token, single).fail {
+        return FAIL;
+    }
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_fetch_plain_scalar(parser: *mut yaml_parser_t) -> Success {
+    let mut token = MaybeUninit::<yaml_token_t>::uninit();
+    let token = token.as_mut_ptr();
+    if yaml_parser_save_simple_key(parser).fail {
+        return FAIL;
+    }
+    (*parser).simple_key_allowed = false;
+    if yaml_parser_scan_plain_scalar(parser, token).fail {
+        return FAIL;
+    }
+    ENQUEUE!((*parser).tokens, *token);
+    OK
+}
+
+unsafe fn yaml_parser_scan_to_next_token(parser: *mut yaml_parser_t) -> Success {
+    loop {
+        if CACHE(parser, 1_u64).fail {
+            return FAIL;
+        }
+        if (*parser).mark.column == 0_u64 && IS_BOM!((*parser).buffer) {
+            SKIP(parser);
+        }
+        if CACHE(parser, 1_u64).fail {
+            return FAIL;
+        }
+        while CHECK!((*parser).buffer, b' ')
+            || ((*parser).flow_level != 0 || !(*parser).simple_key_allowed)
+                && CHECK!((*parser).buffer, b'\t')
+        {
+            SKIP(parser);
+            if CACHE(parser, 1_u64).fail {
+                return FAIL;
+            }
+        }
+        if CHECK!((*parser).buffer, b'#') {
+            while !IS_BREAKZ!((*parser).buffer) {
+                SKIP(parser);
+                if CACHE(parser, 1_u64).fail {
+                    return FAIL;
+                }
+            }
+        }
+        if !IS_BREAK!((*parser).buffer) {
+            break;
+        }
+        if CACHE(parser, 2_u64).fail {
+            return FAIL;
+        }
+        SKIP_LINE(parser);
+        if (*parser).flow_level == 0 {
+            (*parser).simple_key_allowed = true;
+        }
+    }
+    OK
+}
+
+unsafe fn yaml_parser_scan_directive(
+    parser: *mut yaml_parser_t,
+    token: *mut yaml_token_t,
+) -> Success {
+    let mut current_block: u64;
+    let end_mark: yaml_mark_t;
+    let mut name: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut major: libc::c_int = 0;
+    let mut minor: libc::c_int = 0;
+    let mut handle: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut prefix: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    if yaml_parser_scan_directive_name(parser, start_mark, addr_of_mut!(name)).ok {
+        if strcmp(
+            name as *mut libc::c_char,
+            b"YAML\0" as *const u8 as *const libc::c_char,
+        ) == 0
+        {
+            if yaml_parser_scan_version_directive_value(
+                parser,
+                start_mark,
+                addr_of_mut!(major),
+                addr_of_mut!(minor),
+            )
+            .fail
+            {
+                current_block = 11397968426844348457;
+            } else {
+                end_mark = (*parser).mark;
+                memset(
+                    token as *mut libc::c_void,
+                    0,
+                    size_of::<yaml_token_t>() as libc::c_ulong,
+                );
+                (*token).type_ = YAML_VERSION_DIRECTIVE_TOKEN;
+                (*token).start_mark = start_mark;
+                (*token).end_mark = end_mark;
+                (*token).data.version_directive.major = major;
+                (*token).data.version_directive.minor = minor;
+                current_block = 17407779659766490442;
+            }
+        } else if strcmp(
+            name as *mut libc::c_char,
+            b"TAG\0" as *const u8 as *const libc::c_char,
+        ) == 0
+        {
+            if yaml_parser_scan_tag_directive_value(
+                parser,
+                start_mark,
+                addr_of_mut!(handle),
+                addr_of_mut!(prefix),
+            )
+            .fail
+            {
+                current_block = 11397968426844348457;
+            } else {
+                end_mark = (*parser).mark;
+                memset(
+                    token as *mut libc::c_void,
+                    0,
+                    size_of::<yaml_token_t>() as libc::c_ulong,
+                );
+                (*token).type_ = YAML_TAG_DIRECTIVE_TOKEN;
+                (*token).start_mark = start_mark;
+                (*token).end_mark = end_mark;
+                let fresh112 = addr_of_mut!((*token).data.tag_directive.handle);
+                *fresh112 = handle;
+                let fresh113 = addr_of_mut!((*token).data.tag_directive.prefix);
+                *fresh113 = prefix;
+                current_block = 17407779659766490442;
+            }
+        } else {
+            yaml_parser_set_scanner_error(
+                parser,
+                b"while scanning a directive\0" as *const u8 as *const libc::c_char,
+                start_mark,
+                b"found unknown directive name\0" as *const u8 as *const libc::c_char,
+            );
+            current_block = 11397968426844348457;
+        }
+        if current_block != 11397968426844348457 {
+            if CACHE(parser, 1_u64).ok {
+                loop {
+                    if !IS_BLANK!((*parser).buffer) {
+                        current_block = 11584701595673473500;
+                        break;
+                    }
+                    SKIP(parser);
+                    if CACHE(parser, 1_u64).fail {
+                        current_block = 11397968426844348457;
+                        break;
+                    }
+                }
+                if current_block != 11397968426844348457 {
+                    if CHECK!((*parser).buffer, b'#') {
+                        loop {
+                            if IS_BREAKZ!((*parser).buffer) {
+                                current_block = 6669252993407410313;
+                                break;
+                            }
+                            SKIP(parser);
+                            if CACHE(parser, 1_u64).fail {
+                                current_block = 11397968426844348457;
+                                break;
+                            }
+                        }
+                    } else {
+                        current_block = 6669252993407410313;
+                    }
+                    if current_block != 11397968426844348457 {
+                        if !IS_BREAKZ!((*parser).buffer) {
+                            yaml_parser_set_scanner_error(
+                                parser,
+                                b"while scanning a directive\0" as *const u8 as *const libc::c_char,
+                                start_mark,
+                                b"did not find expected comment or line break\0" as *const u8
+                                    as *const libc::c_char,
+                            );
+                        } else {
+                            if IS_BREAK!((*parser).buffer) {
+                                if CACHE(parser, 2_u64).fail {
+                                    current_block = 11397968426844348457;
+                                } else {
+                                    SKIP_LINE(parser);
+                                    current_block = 652864300344834934;
+                                }
+                            } else {
+                                current_block = 652864300344834934;
+                            }
+                            if current_block != 11397968426844348457 {
+                                yaml_free(name as *mut libc::c_void);
+                                return OK;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    yaml_free(prefix as *mut libc::c_void);
+    yaml_free(handle as *mut libc::c_void);
+    yaml_free(name as *mut libc::c_void);
+    FAIL
+}
+
+unsafe fn yaml_parser_scan_directive_name(
+    parser: *mut yaml_parser_t,
+    start_mark: yaml_mark_t,
+    name: *mut *mut yaml_char_t,
+) -> Success {
+    let current_block: u64;
+    let mut string = NULL_STRING;
+    STRING_INIT!(string);
+    if CACHE(parser, 1_u64).ok {
+        loop {
+            if !IS_ALPHA!((*parser).buffer) {
+                current_block = 10879442775620481940;
+                break;
+            }
+            READ!(parser, string);
+            if CACHE(parser, 1_u64).fail {
+                current_block = 8318012024179131575;
+                break;
+            }
+        }
+        if current_block != 8318012024179131575 {
+            if string.start == string.pointer {
+                yaml_parser_set_scanner_error(
+                    parser,
+                    b"while scanning a directive\0" as *const u8 as *const libc::c_char,
+                    start_mark,
+                    b"could not find expected directive name\0" as *const u8 as *const libc::c_char,
+                );
+            } else if !IS_BLANKZ!((*parser).buffer) {
+                yaml_parser_set_scanner_error(
+                    parser,
+                    b"while scanning a directive\0" as *const u8 as *const libc::c_char,
+                    start_mark,
+                    b"found unexpected non-alphabetical character\0" as *const u8
+                        as *const libc::c_char,
+                );
+            } else {
+                *name = string.start;
+                return OK;
+            }
+        }
+    }
+    STRING_DEL!(string);
+    FAIL
+}
+
+unsafe fn yaml_parser_scan_version_directive_value(
+    parser: *mut yaml_parser_t,
+    start_mark: yaml_mark_t,
+    major: *mut libc::c_int,
+    minor: *mut libc::c_int,
+) -> Success {
+    if CACHE(parser, 1_u64).fail {
+        return FAIL;
+    }
+    while IS_BLANK!((*parser).buffer) {
+        SKIP(parser);
+        if CACHE(parser, 1_u64).fail {
+            return FAIL;
+        }
+    }
+    if yaml_parser_scan_version_directive_number(parser, start_mark, major).fail {
+        return FAIL;
+    }
+    if !CHECK!((*parser).buffer, b'.') {
+        yaml_parser_set_scanner_error(
+            parser,
+            b"while scanning a %YAML directive\0" as *const u8 as *const libc::c_char,
+            start_mark,
+            b"did not find expected digit or '.' character\0" as *const u8 as *const libc::c_char,
+        );
+        return FAIL;
+    }
+    SKIP(parser);
+    yaml_parser_scan_version_directive_number(parser, start_mark, minor)
+}
+
+const MAX_NUMBER_LENGTH: u64 = 9_u64;
+
+unsafe fn yaml_parser_scan_version_directive_number(
+    parser: *mut yaml_parser_t,
+    start_mark: yaml_mark_t,
+    number: *mut libc::c_int,
+) -> Success {
+    let mut value: libc::c_int = 0;
+    let mut length: size_t = 0_u64;
+    if CACHE(parser, 1_u64).fail {
+        return FAIL;
+    }
+    while IS_DIGIT!((*parser).buffer) {
+        length = length.wrapping_add(1);
+        if length > MAX_NUMBER_LENGTH {
+            yaml_parser_set_scanner_error(
+                parser,
+                b"while scanning a %YAML directive\0" as *const u8 as *const libc::c_char,
+                start_mark,
+                b"found extremely long version number\0" as *const u8 as *const libc::c_char,
+            );
+            return FAIL;
+        }
+        value = value * 10 + AS_DIGIT!((*parser).buffer);
+        SKIP(parser);
+        if CACHE(parser, 1_u64).fail {
+            return FAIL;
+        }
+    }
+    if length == 0 {
+        yaml_parser_set_scanner_error(
+            parser,
+            b"while scanning a %YAML directive\0" as *const u8 as *const libc::c_char,
+            start_mark,
+            b"did not find expected version number\0" as *const u8 as *const libc::c_char,
+        );
+        return FAIL;
+    }
+    *number = value;
+    OK
+}
+
+unsafe fn yaml_parser_scan_tag_directive_value(
+    parser: *mut yaml_parser_t,
+    start_mark: yaml_mark_t,
+    handle: *mut *mut yaml_char_t,
+    prefix: *mut *mut yaml_char_t,
+) -> Success {
+    let mut current_block: u64;
+    let mut handle_value: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut prefix_value: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    if CACHE(parser, 1_u64).fail {
+        current_block = 5231181710497607163;
+    } else {
+        current_block = 14916268686031723178;
+    }
+    'c_34337: loop {
+        match current_block {
+            5231181710497607163 => {
+                yaml_free(handle_value as *mut libc::c_void);
+                yaml_free(prefix_value as *mut libc::c_void);
+                return FAIL;
+            }
+            _ => {
+                if IS_BLANK!((*parser).buffer) {
+                    SKIP(parser);
+                    if CACHE(parser, 1_u64).fail {
+                        current_block = 5231181710497607163;
+                    } else {
+                        current_block = 14916268686031723178;
+                    }
+                } else {
+                    if yaml_parser_scan_tag_handle(
+                        parser,
+                        true,
+                        start_mark,
+                        addr_of_mut!(handle_value),
+                    )
+                    .fail
+                    {
+                        current_block = 5231181710497607163;
+                        continue;
+                    }
+                    if CACHE(parser, 1_u64).fail {
+                        current_block = 5231181710497607163;
+                        continue;
+                    }
+                    if !IS_BLANK!((*parser).buffer) {
+                        yaml_parser_set_scanner_error(
+                            parser,
+                            b"while scanning a %TAG directive\0" as *const u8
+                                as *const libc::c_char,
+                            start_mark,
+                            b"did not find expected whitespace\0" as *const u8
+                                as *const libc::c_char,
+                        );
+                        current_block = 5231181710497607163;
+                    } else {
+                        while IS_BLANK!((*parser).buffer) {
+                            SKIP(parser);
+                            if CACHE(parser, 1_u64).fail {
+                                current_block = 5231181710497607163;
+                                continue 'c_34337;
+                            }
+                        }
+                        if yaml_parser_scan_tag_uri(
+                            parser,
+                            true,
+                            true,
+                            ptr::null_mut::<yaml_char_t>(),
+                            start_mark,
+                            addr_of_mut!(prefix_value),
+                        )
+                        .fail
+                        {
+                            current_block = 5231181710497607163;
+                            continue;
+                        }
+                        if CACHE(parser, 1_u64).fail {
+                            current_block = 5231181710497607163;
+                            continue;
+                        }
+                        if !IS_BLANKZ!((*parser).buffer) {
+                            yaml_parser_set_scanner_error(
+                                parser,
+                                b"while scanning a %TAG directive\0" as *const u8
+                                    as *const libc::c_char,
+                                start_mark,
+                                b"did not find expected whitespace or line break\0" as *const u8
+                                    as *const libc::c_char,
+                            );
+                            current_block = 5231181710497607163;
+                        } else {
+                            *handle = handle_value;
+                            *prefix = prefix_value;
+                            return OK;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+unsafe fn yaml_parser_scan_anchor(
+    parser: *mut yaml_parser_t,
+    token: *mut yaml_token_t,
+    type_: yaml_token_type_t,
+) -> Success {
+    let current_block: u64;
+    let mut length: libc::c_int = 0;
+    let end_mark: yaml_mark_t;
+    let mut string = NULL_STRING;
+    STRING_INIT!(string);
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    if CACHE(parser, 1_u64).ok {
+        loop {
+            if !IS_ALPHA!((*parser).buffer) {
+                current_block = 2868539653012386629;
+                break;
+            }
+            READ!(parser, string);
+            if CACHE(parser, 1_u64).fail {
+                current_block = 5883759901342942623;
+                break;
+            }
+            length += 1;
+        }
+        if current_block != 5883759901342942623 {
+            end_mark = (*parser).mark;
+            if length == 0
+                || !(IS_BLANKZ!((*parser).buffer)
+                    || CHECK!((*parser).buffer, b'?')
+                    || CHECK!((*parser).buffer, b':')
+                    || CHECK!((*parser).buffer, b',')
+                    || CHECK!((*parser).buffer, b']')
+                    || CHECK!((*parser).buffer, b'}')
+                    || CHECK!((*parser).buffer, b'%')
+                    || CHECK!((*parser).buffer, b'@')
+                    || CHECK!((*parser).buffer, b'`'))
+            {
+                yaml_parser_set_scanner_error(
+                    parser,
+                    if type_ == YAML_ANCHOR_TOKEN {
+                        b"while scanning an anchor\0" as *const u8 as *const libc::c_char
+                    } else {
+                        b"while scanning an alias\0" as *const u8 as *const libc::c_char
+                    },
+                    start_mark,
+                    b"did not find expected alphabetic or numeric character\0" as *const u8
+                        as *const libc::c_char,
+                );
+            } else {
+                if type_ == YAML_ANCHOR_TOKEN {
+                    memset(
+                        token as *mut libc::c_void,
+                        0,
+                        size_of::<yaml_token_t>() as libc::c_ulong,
+                    );
+                    (*token).type_ = YAML_ANCHOR_TOKEN;
+                    (*token).start_mark = start_mark;
+                    (*token).end_mark = end_mark;
+                    let fresh220 = addr_of_mut!((*token).data.anchor.value);
+                    *fresh220 = string.start;
+                } else {
+                    memset(
+                        token as *mut libc::c_void,
+                        0,
+                        size_of::<yaml_token_t>() as libc::c_ulong,
+                    );
+                    (*token).type_ = YAML_ALIAS_TOKEN;
+                    (*token).start_mark = start_mark;
+                    (*token).end_mark = end_mark;
+                    let fresh221 = addr_of_mut!((*token).data.alias.value);
+                    *fresh221 = string.start;
+                }
+                return OK;
+            }
+        }
+    }
+    STRING_DEL!(string);
+    FAIL
+}
+
+unsafe fn yaml_parser_scan_tag(parser: *mut yaml_parser_t, token: *mut yaml_token_t) -> Success {
+    let mut current_block: u64;
+    let mut handle: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let mut suffix: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
+    let end_mark: yaml_mark_t;
+    let start_mark: yaml_mark_t = (*parser).mark;
+    if CACHE(parser, 2_u64).ok {
+        if CHECK_AT!((*parser).buffer, b'<', 1) {
+            handle = yaml_malloc(1_u64) as *mut yaml_char_t;
+            *handle = b'\0';
+            SKIP(parser);
+            SKIP(parser);
+            if yaml_parser_scan_tag_uri(
+                parser,
+                true,
+                false,
+                ptr::null_mut::<yaml_char_t>(),
+                start_mark,
+                addr_of_mut!(suffix),
+            )
+            .fail
+            {
+                current_block = 17708497480799081542;
+            } else if !CHECK!((*parser).buffer, b'>') {
+                yaml_parser_set_scanner_error(
+                    parser,
+                    b"while scanning a tag\0" as *const u8 as *const libc::c_char,
+                    start_mark,
+                    b"did not find the expected '>'\0" as *const u8 as *const libc::c_char,
+                );
+                current_block = 17708497480799081542;
+            } else {
+                SKIP(parser);
+                current_block = 4488286894823169796;
+            }
+        } else if yaml_parser_scan_tag_handle(parser, false, start_mark, addr_of_mut!(handle)).fail
+        {
+            current_block = 17708497480799081542;
+        } else if *handle == b'!'
+            && *handle.wrapping_offset(1_isize) != b'\0'
+            && *handle
+                .wrapping_offset(strlen(handle as *mut libc::c_char).wrapping_sub(1_u64) as isize)
+                == b'!'
+        {
+            if yaml_parser_scan_tag_uri(
+                parser,
+                false,
+                false,
+                ptr::null_mut::<yaml_char_t>(),
+                start_mark,
+                addr_of_mut!(suffix),
+            )
+            .fail
+            {
+                current_block = 17708497480799081542;
+            } else {
+                current_block = 4488286894823169796;
+            }
+        } else if yaml_parser_scan_tag_uri(
+            parser,
+            false,
+            false,
+            handle,
+            start_mark,
+            addr_of_mut!(suffix),
+        )
+        .fail
+        {
+            current_block = 17708497480799081542;
+        } else {
+            yaml_free(handle as *mut libc::c_void);
+            handle = yaml_malloc(2_u64) as *mut yaml_char_t;
+            *handle = b'!';
+            *handle.wrapping_offset(1_isize) = b'\0';
+            if *suffix == b'\0' {
+                let tmp: *mut yaml_char_t = handle;
+                handle = suffix;
+                suffix = tmp;
+            }
+            current_block = 4488286894823169796;
+        }
+        if current_block != 17708497480799081542 {
+            if CACHE(parser, 1_u64).ok {
+                if !IS_BLANKZ!((*parser).buffer) {
+                    if (*parser).flow_level == 0 || !CHECK!((*parser).buffer, b',') {
+                        yaml_parser_set_scanner_error(
+                            parser,
+                            b"while scanning a tag\0" as *const u8 as *const libc::c_char,
+                            start_mark,
+                            b"did not find expected whitespace or line break\0" as *const u8
+                                as *const libc::c_char,
+                        );
+                        current_block = 17708497480799081542;
+                    } else {
+                        current_block = 7333393191927787629;
+                    }
+                } else {
+                    current_block = 7333393191927787629;
+                }
+                if current_block != 17708497480799081542 {
+                    end_mark = (*parser).mark;
+                    memset(
+                        token as *mut libc::c_void,
+                        0,
+                        size_of::<yaml_token_t>() as libc::c_ulong,
+                    );
+                    (*token).type_ = YAML_TAG_TOKEN;
+                    (*token).start_mark = start_mark;
+                    (*token).end_mark = end_mark;
+                    let fresh234 = addr_of_mut!((*token).data.tag.handle);
+                    *fresh234 = handle;
+                    let fresh235 = addr_of_mut!((*token).data.tag.suffix);
+                    *fresh235 = suffix;
+                    return OK;
+                }
+            }
+        }
+    }
+    yaml_free(handle as *mut libc::c_void);
+    yaml_free(suffix as *mut libc::c_void);
+    FAIL
+}
+
+unsafe fn yaml_parser_scan_tag_handle(
+    parser: *mut yaml_parser_t,
+    directive: bool,
+    start_mark: yaml_mark_t,
+    handle: *mut *mut yaml_char_t,
+) -> Success {
+    let mut current_block: u64;
+    let mut string = NULL_STRING;
+    STRING_INIT!(string);
+    if CACHE(parser, 1_u64).ok {
+        if !CHECK!((*parser).buffer, b'!') {
+            yaml_parser_set_scanner_error(
+                parser,
+                if directive {
+                    b"while scanning a tag directive\0" as *const u8 as *const libc::c_char
+                } else {
+                    b"while scanning a tag\0" as *const u8 as *const libc::c_char
+                },
+                start_mark,
+                b"did not find expected '!'\0" as *const u8 as *const libc::c_char,
+            );
+        } else {
+            READ!(parser, string);
+            if CACHE(parser, 1_u64).ok {
+                loop {
+                    if !IS_ALPHA!((*parser).buffer) {
+                        current_block = 7651349459974463963;
+                        break;
+                    }
+                    READ!(parser, string);
+                    if CACHE(parser, 1_u64).fail {
+                        current_block = 1771849829115608806;
+                        break;
+                    }
+                }
+                if current_block != 1771849829115608806 {
+                    if CHECK!((*parser).buffer, b'!') {
+                        READ!(parser, string);
+                        current_block = 5689001924483802034;
+                    } else if directive
+                        && !(*string.start == b'!'
+                            && *string.start.wrapping_offset(1_isize) == b'\0')
+                    {
+                        yaml_parser_set_scanner_error(
+                            parser,
+                            b"while parsing a tag directive\0" as *const u8 as *const libc::c_char,
+                            start_mark,
+                            b"did not find expected '!'\0" as *const u8 as *const libc::c_char,
+                        );
+                        current_block = 1771849829115608806;
+                    } else {
+                        current_block = 5689001924483802034;
+                    }
+                    if current_block != 1771849829115608806 {
+                        *handle = string.start;
+                        return OK;
+                    }
+                }
+            }
+        }
+    }
+    STRING_DEL!(string);
+    FAIL
+}
+
+unsafe fn yaml_parser_scan_tag_uri(
+    parser: *mut yaml_parser_t,
+    uri_char: bool,
+    directive: bool,
+    head: *mut yaml_char_t,
+    start_mark: yaml_mark_t,
+    uri: *mut *mut yaml_char_t,
+) -> Success {
+    let mut current_block: u64;
+    let mut length: size_t = if !head.is_null() {
+        strlen(head as *mut libc::c_char)
+    } else {
+        0_u64
+    };
+    let mut string = NULL_STRING;
+    STRING_INIT!(string);
+    current_block = 14916268686031723178;
+    'c_21953: loop {
+        match current_block {
+            15265153392498847348 => {
+                STRING_DEL!(string);
+                return FAIL;
+            }
+            _ => {
+                if string.end.c_offset_from(string.start) as libc::c_long as size_t <= length {
+                    yaml_string_extend(
+                        addr_of_mut!(string.start),
+                        addr_of_mut!(string.pointer),
+                        addr_of_mut!(string.end),
+                    );
+                    current_block = 14916268686031723178;
+                    continue;
+                } else {
+                    if length > 1_u64 {
+                        memcpy(
+                            string.start as *mut libc::c_void,
+                            head.wrapping_offset(1_isize) as *const libc::c_void,
+                            length.wrapping_sub(1_u64),
+                        );
+                        string.pointer = string
+                            .pointer
+                            .wrapping_offset(length.wrapping_sub(1_u64) as isize);
+                    }
+                    if CACHE(parser, 1_u64).fail {
+                        current_block = 15265153392498847348;
+                        continue;
+                    }
+                    while IS_ALPHA!((*parser).buffer)
+                        || CHECK!((*parser).buffer, b';')
+                        || CHECK!((*parser).buffer, b'/')
+                        || CHECK!((*parser).buffer, b'?')
+                        || CHECK!((*parser).buffer, b':')
+                        || CHECK!((*parser).buffer, b'@')
+                        || CHECK!((*parser).buffer, b'&')
+                        || CHECK!((*parser).buffer, b'=')
+                        || CHECK!((*parser).buffer, b'+')
+                        || CHECK!((*parser).buffer, b'$')
+                        || CHECK!((*parser).buffer, b'.')
+                        || CHECK!((*parser).buffer, b'%')
+                        || CHECK!((*parser).buffer, b'!')
+                        || CHECK!((*parser).buffer, b'~')
+                        || CHECK!((*parser).buffer, b'*')
+                        || CHECK!((*parser).buffer, b'\'')
+                        || CHECK!((*parser).buffer, b'(')
+                        || CHECK!((*parser).buffer, b')')
+                        || uri_char
+                            && (CHECK!((*parser).buffer, b',')
+                                || CHECK!((*parser).buffer, b'[')
+                                || CHECK!((*parser).buffer, b']'))
+                    {
+                        if CHECK!((*parser).buffer, b'%') {
+                            STRING_EXTEND!(string);
+                            if yaml_parser_scan_uri_escapes(
+                                parser,
+                                directive,
+                                start_mark,
+                                addr_of_mut!(string),
+                            )
+                            .fail
+                            {
+                                current_block = 15265153392498847348;
+                                continue 'c_21953;
+                            }
+                        } else {
+                            READ!(parser, string);
+                        }
+                        length = length.wrapping_add(1);
+                        if CACHE(parser, 1_u64).fail {
+                            current_block = 15265153392498847348;
+                            continue 'c_21953;
+                        }
+                    }
+                    if length == 0 {
+                        STRING_EXTEND!(string);
+                        yaml_parser_set_scanner_error(
+                            parser,
+                            if directive {
+                                b"while parsing a %TAG directive\0" as *const u8
+                                    as *const libc::c_char
+                            } else {
+                                b"while parsing a tag\0" as *const u8 as *const libc::c_char
+                            },
+                            start_mark,
+                            b"did not find expected tag URI\0" as *const u8 as *const libc::c_char,
+                        );
+                        current_block = 15265153392498847348;
+                    } else {
+                        *uri = string.start;
+                        return OK;
+                    }
+                }
+            }
+        }
+    }
+}
+
+unsafe fn yaml_parser_scan_uri_escapes(
+    parser: *mut yaml_parser_t,
+    directive: bool,
+    start_mark: yaml_mark_t,
+    string: *mut yaml_string_t,
+) -> Success {
+    let mut width: libc::c_int = 0;
+    loop {
+        if CACHE(parser, 3_u64).fail {
+            return FAIL;
+        }
+        if !(CHECK!((*parser).buffer, b'%')
+            && IS_HEX_AT!((*parser).buffer, 1)
+            && IS_HEX_AT!((*parser).buffer, 2))
+        {
+            yaml_parser_set_scanner_error(
+                parser,
+                if directive {
+                    b"while parsing a %TAG directive\0" as *const u8 as *const libc::c_char
+                } else {
+                    b"while parsing a tag\0" as *const u8 as *const libc::c_char
+                },
+                start_mark,
+                b"did not find URI escaped octet\0" as *const u8 as *const libc::c_char,
+            );
+            return FAIL;
+        }
+        let octet: libc::c_uchar = ((AS_HEX_AT!((*parser).buffer, 1) << 4)
+            + AS_HEX_AT!((*parser).buffer, 2)) as libc::c_uchar;
+        if width == 0 {
+            width = if octet & 0x80 == 0 {
+                1
+            } else if octet & 0xE0 == 0xC0 {
+                2
+            } else if octet & 0xF0 == 0xE0 {
+                3
+            } else if octet & 0xF8 == 0xF0 {
+                4
+            } else {
+                0
+            };
+            if width == 0 {
+                yaml_parser_set_scanner_error(
+                    parser,
+                    if directive {
+                        b"while parsing a %TAG directive\0" as *const u8 as *const libc::c_char
+                    } else {
+                        b"while parsing a tag\0" as *const u8 as *const libc::c_char
+                    },
+                    start_mark,
+                    b"found an incorrect leading UTF-8 octet\0" as *const u8 as *const libc::c_char,
+                );
+                return FAIL;
+            }
+        } else if octet & 0xC0 != 0x80 {
+            yaml_parser_set_scanner_error(
+                parser,
+                if directive {
+                    b"while parsing a %TAG directive\0" as *const u8 as *const libc::c_char
+                } else {
+                    b"while parsing a tag\0" as *const u8 as *const libc::c_char
+                },
+                start_mark,
+                b"found an incorrect trailing UTF-8 octet\0" as *const u8 as *const libc::c_char,
+            );
+            return FAIL;
+        }
+        let fresh368 = addr_of_mut!((*string).pointer);
+        let fresh369 = *fresh368;
+        *fresh368 = (*fresh368).wrapping_offset(1);
+        *fresh369 = octet;
+        SKIP(parser);
+        SKIP(parser);
+        SKIP(parser);
+        width -= 1;
+        if !(width != 0) {
+            break;
+        }
+    }
+    OK
+}
+
+unsafe fn yaml_parser_scan_block_scalar(
+    parser: *mut yaml_parser_t,
+    token: *mut yaml_token_t,
+    literal: bool,
+) -> Success {
+    let mut current_block: u64;
+    let mut end_mark: yaml_mark_t;
+    let mut string = NULL_STRING;
+    let mut leading_break = NULL_STRING;
+    let mut trailing_breaks = NULL_STRING;
+    let mut chomping: libc::c_int = 0;
+    let mut increment: libc::c_int = 0;
+    let mut indent: libc::c_int = 0;
+    let mut leading_blank: libc::c_int = 0;
+    let mut trailing_blank: libc::c_int;
+    STRING_INIT!(string);
+    STRING_INIT!(leading_break);
+    STRING_INIT!(trailing_breaks);
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    if CACHE(parser, 1_u64).ok {
+        if CHECK!((*parser).buffer, b'+') || CHECK!((*parser).buffer, b'-') {
+            chomping = if CHECK!((*parser).buffer, b'+') {
+                1
+            } else {
+                -1
+            };
+            SKIP(parser);
+            if CACHE(parser, 1_u64).fail {
+                current_block = 14984465786483313892;
+            } else if IS_DIGIT!((*parser).buffer) {
+                if CHECK!((*parser).buffer, b'0') {
+                    yaml_parser_set_scanner_error(
+                        parser,
+                        b"while scanning a block scalar\0" as *const u8 as *const libc::c_char,
+                        start_mark,
+                        b"found an indentation indicator equal to 0\0" as *const u8
+                            as *const libc::c_char,
+                    );
+                    current_block = 14984465786483313892;
+                } else {
+                    increment = AS_DIGIT!((*parser).buffer);
+                    SKIP(parser);
+                    current_block = 11913429853522160501;
+                }
+            } else {
+                current_block = 11913429853522160501;
+            }
+        } else if IS_DIGIT!((*parser).buffer) {
+            if CHECK!((*parser).buffer, b'0') {
+                yaml_parser_set_scanner_error(
+                    parser,
+                    b"while scanning a block scalar\0" as *const u8 as *const libc::c_char,
+                    start_mark,
+                    b"found an indentation indicator equal to 0\0" as *const u8
+                        as *const libc::c_char,
+                );
+                current_block = 14984465786483313892;
+            } else {
+                increment = AS_DIGIT!((*parser).buffer);
+                SKIP(parser);
+                if CACHE(parser, 1_u64).fail {
+                    current_block = 14984465786483313892;
+                } else {
+                    if CHECK!((*parser).buffer, b'+') || CHECK!((*parser).buffer, b'-') {
+                        chomping = if CHECK!((*parser).buffer, b'+') {
+                            1
+                        } else {
+                            -1
+                        };
+                        SKIP(parser);
+                    }
+                    current_block = 11913429853522160501;
+                }
+            }
+        } else {
+            current_block = 11913429853522160501;
+        }
+        if current_block != 14984465786483313892 {
+            if CACHE(parser, 1_u64).ok {
+                loop {
+                    if !IS_BLANK!((*parser).buffer) {
+                        current_block = 4090602189656566074;
+                        break;
+                    }
+                    SKIP(parser);
+                    if CACHE(parser, 1_u64).fail {
+                        current_block = 14984465786483313892;
+                        break;
+                    }
+                }
+                if current_block != 14984465786483313892 {
+                    if CHECK!((*parser).buffer, b'#') {
+                        loop {
+                            if IS_BREAKZ!((*parser).buffer) {
+                                current_block = 12997042908615822766;
+                                break;
+                            }
+                            SKIP(parser);
+                            if CACHE(parser, 1_u64).fail {
+                                current_block = 14984465786483313892;
+                                break;
+                            }
+                        }
+                    } else {
+                        current_block = 12997042908615822766;
+                    }
+                    if current_block != 14984465786483313892 {
+                        if !IS_BREAKZ!((*parser).buffer) {
+                            yaml_parser_set_scanner_error(
+                                parser,
+                                b"while scanning a block scalar\0" as *const u8
+                                    as *const libc::c_char,
+                                start_mark,
+                                b"did not find expected comment or line break\0" as *const u8
+                                    as *const libc::c_char,
+                            );
+                        } else {
+                            if IS_BREAK!((*parser).buffer) {
+                                if CACHE(parser, 2_u64).fail {
+                                    current_block = 14984465786483313892;
+                                } else {
+                                    SKIP_LINE(parser);
+                                    current_block = 13619784596304402172;
+                                }
+                            } else {
+                                current_block = 13619784596304402172;
+                            }
+                            if current_block != 14984465786483313892 {
+                                end_mark = (*parser).mark;
+                                if increment != 0 {
+                                    indent = if (*parser).indent >= 0 {
+                                        (*parser).indent + increment
+                                    } else {
+                                        increment
+                                    };
+                                }
+                                if yaml_parser_scan_block_scalar_breaks(
+                                    parser,
+                                    addr_of_mut!(indent),
+                                    addr_of_mut!(trailing_breaks),
+                                    start_mark,
+                                    addr_of_mut!(end_mark),
+                                )
+                                .ok
+                                {
+                                    if CACHE(parser, 1_u64).ok {
+                                        's_281: loop {
+                                            if !((*parser).mark.column as libc::c_int == indent
+                                                && !IS_Z!((*parser).buffer))
+                                            {
+                                                current_block = 5793491756164225964;
+                                                break;
+                                            }
+                                            trailing_blank =
+                                                IS_BLANK!((*parser).buffer) as libc::c_int;
+                                            if !literal
+                                                && *leading_break.start == b'\n'
+                                                && leading_blank == 0
+                                                && trailing_blank == 0
+                                            {
+                                                if *trailing_breaks.start == b'\0' {
+                                                    STRING_EXTEND!(string);
+                                                    let fresh418 = string.pointer;
+                                                    string.pointer =
+                                                        string.pointer.wrapping_offset(1);
+                                                    *fresh418 = b' ';
+                                                }
+                                                CLEAR!(leading_break);
+                                            } else {
+                                                JOIN!(string, leading_break);
+                                                CLEAR!(leading_break);
+                                            }
+                                            JOIN!(string, trailing_breaks);
+                                            CLEAR!(trailing_breaks);
+                                            leading_blank =
+                                                IS_BLANK!((*parser).buffer) as libc::c_int;
+                                            while !IS_BREAKZ!((*parser).buffer) {
+                                                READ!(parser, string);
+                                                if CACHE(parser, 1_u64).fail {
+                                                    current_block = 14984465786483313892;
+                                                    break 's_281;
+                                                }
+                                            }
+                                            if CACHE(parser, 2_u64).fail {
+                                                current_block = 14984465786483313892;
+                                                break;
+                                            }
+                                            READ_LINE!(parser, leading_break);
+                                            if yaml_parser_scan_block_scalar_breaks(
+                                                parser,
+                                                addr_of_mut!(indent),
+                                                addr_of_mut!(trailing_breaks),
+                                                start_mark,
+                                                addr_of_mut!(end_mark),
+                                            )
+                                            .fail
+                                            {
+                                                current_block = 14984465786483313892;
+                                                break;
+                                            }
+                                        }
+                                        if current_block != 14984465786483313892 {
+                                            if chomping != -1 {
+                                                JOIN!(string, leading_break);
+                                                current_block = 17787701279558130514;
+                                            } else {
+                                                current_block = 17787701279558130514;
+                                            }
+                                            if current_block != 14984465786483313892 {
+                                                if chomping == 1 {
+                                                    JOIN!(string, trailing_breaks);
+                                                }
+                                                memset(
+                                                    token as *mut libc::c_void,
+                                                    0,
+                                                    size_of::<yaml_token_t>() as libc::c_ulong,
+                                                );
+                                                (*token).type_ = YAML_SCALAR_TOKEN;
+                                                (*token).start_mark = start_mark;
+                                                (*token).end_mark = end_mark;
+                                                let fresh479 =
+                                                    addr_of_mut!((*token).data.scalar.value);
+                                                *fresh479 = string.start;
+                                                (*token).data.scalar.length =
+                                                    string.pointer.c_offset_from(string.start)
+                                                        as libc::c_long
+                                                        as size_t;
+                                                (*token).data.scalar.style = if literal {
+                                                    YAML_LITERAL_SCALAR_STYLE
+                                                } else {
+                                                    YAML_FOLDED_SCALAR_STYLE
+                                                };
+                                                STRING_DEL!(leading_break);
+                                                STRING_DEL!(trailing_breaks);
+                                                return OK;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    STRING_DEL!(string);
+    STRING_DEL!(leading_break);
+    STRING_DEL!(trailing_breaks);
+    FAIL
+}
+
+unsafe fn yaml_parser_scan_block_scalar_breaks(
+    parser: *mut yaml_parser_t,
+    indent: *mut libc::c_int,
+    breaks: *mut yaml_string_t,
+    start_mark: yaml_mark_t,
+    end_mark: *mut yaml_mark_t,
+) -> Success {
+    let mut max_indent: libc::c_int = 0;
+    *end_mark = (*parser).mark;
+    loop {
+        if CACHE(parser, 1_u64).fail {
+            return FAIL;
+        }
+        while (*indent == 0 || ((*parser).mark.column as libc::c_int) < *indent)
+            && IS_SPACE!((*parser).buffer)
+        {
+            SKIP(parser);
+            if CACHE(parser, 1_u64).fail {
+                return FAIL;
+            }
+        }
+        if (*parser).mark.column as libc::c_int > max_indent {
+            max_indent = (*parser).mark.column as libc::c_int;
+        }
+        if (*indent == 0 || ((*parser).mark.column as libc::c_int) < *indent)
+            && IS_TAB!((*parser).buffer)
+        {
+            yaml_parser_set_scanner_error(
+                parser,
+                b"while scanning a block scalar\0" as *const u8 as *const libc::c_char,
+                start_mark,
+                b"found a tab character where an indentation space is expected\0" as *const u8
+                    as *const libc::c_char,
+            );
+            return FAIL;
+        }
+        if !IS_BREAK!((*parser).buffer) {
+            break;
+        }
+        if CACHE(parser, 2_u64).fail {
+            return FAIL;
+        }
+        READ_LINE!(parser, *breaks);
+        *end_mark = (*parser).mark;
+    }
+    if *indent == 0 {
+        *indent = max_indent;
+        if *indent < (*parser).indent + 1 {
+            *indent = (*parser).indent + 1;
+        }
+        if *indent < 1 {
+            *indent = 1;
+        }
+    }
+    OK
+}
+
+unsafe fn yaml_parser_scan_flow_scalar(
+    parser: *mut yaml_parser_t,
+    token: *mut yaml_token_t,
+    single: bool,
+) -> Success {
+    let current_block: u64;
+    let end_mark: yaml_mark_t;
+    let mut string = NULL_STRING;
+    let mut leading_break = NULL_STRING;
+    let mut trailing_breaks = NULL_STRING;
+    let mut whitespaces = NULL_STRING;
+    let mut leading_blanks;
+    STRING_INIT!(string);
+    STRING_INIT!(leading_break);
+    STRING_INIT!(trailing_breaks);
+    STRING_INIT!(whitespaces);
+    let start_mark: yaml_mark_t = (*parser).mark;
+    SKIP(parser);
+    's_58: loop {
+        if CACHE(parser, 4_u64).fail {
+            current_block = 8114179180390253173;
+            break;
+        }
+        if (*parser).mark.column == 0_u64
+            && (CHECK_AT!((*parser).buffer, b'-', 0)
+                && CHECK_AT!((*parser).buffer, b'-', 1)
+                && CHECK_AT!((*parser).buffer, b'-', 2)
+                || CHECK_AT!((*parser).buffer, b'.', 0)
+                    && CHECK_AT!((*parser).buffer, b'.', 1)
+                    && CHECK_AT!((*parser).buffer, b'.', 2))
+            && IS_BLANKZ_AT!((*parser).buffer, 3)
+        {
+            yaml_parser_set_scanner_error(
+                parser,
+                b"while scanning a quoted scalar\0" as *const u8 as *const libc::c_char,
+                start_mark,
+                b"found unexpected document indicator\0" as *const u8 as *const libc::c_char,
+            );
+            current_block = 8114179180390253173;
+            break;
+        } else if IS_Z!((*parser).buffer) {
+            yaml_parser_set_scanner_error(
+                parser,
+                b"while scanning a quoted scalar\0" as *const u8 as *const libc::c_char,
+                start_mark,
+                b"found unexpected end of stream\0" as *const u8 as *const libc::c_char,
+            );
+            current_block = 8114179180390253173;
+            break;
+        } else {
+            if CACHE(parser, 2_u64).fail {
+                current_block = 8114179180390253173;
+                break;
+            }
+            leading_blanks = false;
+            while !IS_BLANKZ!((*parser).buffer) {
+                if single
+                    && CHECK_AT!((*parser).buffer, b'\'', 0)
+                    && CHECK_AT!((*parser).buffer, b'\'', 1)
+                {
+                    STRING_EXTEND!(string);
+                    let fresh521 = string.pointer;
+                    string.pointer = string.pointer.wrapping_offset(1);
+                    *fresh521 = b'\'';
+                    SKIP(parser);
+                    SKIP(parser);
+                } else {
+                    if CHECK!((*parser).buffer, if single { b'\'' } else { b'"' }) {
+                        break;
+                    }
+                    if !single
+                        && CHECK!((*parser).buffer, b'\\')
+                        && IS_BREAK_AT!((*parser).buffer, 1)
+                    {
+                        if CACHE(parser, 3_u64).fail {
+                            current_block = 8114179180390253173;
+                            break 's_58;
+                        }
+                        SKIP(parser);
+                        SKIP_LINE(parser);
+                        leading_blanks = true;
+                        break;
+                    } else if !single && CHECK!((*parser).buffer, b'\\') {
+                        let mut code_length: size_t = 0_u64;
+                        STRING_EXTEND!(string);
+                        match *(*parser).buffer.pointer.wrapping_offset(1_isize) {
+                            b'0' => {
+                                let fresh542 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh542 = b'\0';
+                            }
+                            b'a' => {
+                                let fresh543 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh543 = b'\x07';
+                            }
+                            b'b' => {
+                                let fresh544 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh544 = b'\x08';
+                            }
+                            b't' | b'\t' => {
+                                let fresh545 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh545 = b'\t';
+                            }
+                            b'n' => {
+                                let fresh546 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh546 = b'\n';
+                            }
+                            b'v' => {
+                                let fresh547 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh547 = b'\x0B';
+                            }
+                            b'f' => {
+                                let fresh548 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh548 = b'\x0C';
+                            }
+                            b'r' => {
+                                let fresh549 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh549 = b'\r';
+                            }
+                            b'e' => {
+                                let fresh550 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh550 = b'\x1B';
+                            }
+                            b' ' => {
+                                let fresh551 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh551 = b' ';
+                            }
+                            b'"' => {
+                                let fresh552 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh552 = b'"';
+                            }
+                            b'/' => {
+                                let fresh553 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh553 = b'/';
+                            }
+                            b'\\' => {
+                                let fresh554 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh554 = b'\\';
+                            }
+                            // NEL (#x85)
+                            b'N' => {
+                                let fresh555 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh555 = b'\xC2';
+                                let fresh556 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh556 = b'\x85';
+                            }
+                            // #xA0
+                            b'_' => {
+                                let fresh557 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh557 = b'\xC2';
+                                let fresh558 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh558 = b'\xA0';
+                            }
+                            // LS (#x2028)
+                            b'L' => {
+                                let fresh559 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh559 = b'\xE2';
+                                let fresh560 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh560 = b'\x80';
+                                let fresh561 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh561 = b'\xA8';
+                            }
+                            // PS (#x2029)
+                            b'P' => {
+                                let fresh562 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh562 = b'\xE2';
+                                let fresh563 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh563 = b'\x80';
+                                let fresh564 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh564 = b'\xA9';
+                            }
+                            b'x' => {
+                                code_length = 2_u64;
+                            }
+                            b'u' => {
+                                code_length = 4_u64;
+                            }
+                            b'U' => {
+                                code_length = 8_u64;
+                            }
+                            _ => {
+                                yaml_parser_set_scanner_error(
+                                    parser,
+                                    b"while parsing a quoted scalar\0" as *const u8
+                                        as *const libc::c_char,
+                                    start_mark,
+                                    b"found unknown escape character\0" as *const u8
+                                        as *const libc::c_char,
+                                );
+                                current_block = 8114179180390253173;
+                                break 's_58;
+                            }
+                        }
+                        SKIP(parser);
+                        SKIP(parser);
+                        if code_length != 0 {
+                            let mut value: libc::c_uint = 0;
+                            let mut k: size_t;
+                            if CACHE(parser, code_length).fail {
+                                current_block = 8114179180390253173;
+                                break 's_58;
+                            }
+                            k = 0_u64;
+                            while k < code_length {
+                                if !IS_HEX_AT!((*parser).buffer, k as isize) {
+                                    yaml_parser_set_scanner_error(
+                                        parser,
+                                        b"while parsing a quoted scalar\0" as *const u8
+                                            as *const libc::c_char,
+                                        start_mark,
+                                        b"did not find expected hexdecimal number\0" as *const u8
+                                            as *const libc::c_char,
+                                    );
+                                    current_block = 8114179180390253173;
+                                    break 's_58;
+                                } else {
+                                    value = (value << 4).wrapping_add(AS_HEX_AT!(
+                                        (*parser).buffer,
+                                        k as isize
+                                    )
+                                        as libc::c_uint);
+                                    k = k.wrapping_add(1);
+                                }
+                            }
+                            if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
+                                yaml_parser_set_scanner_error(
+                                    parser,
+                                    b"while parsing a quoted scalar\0" as *const u8
+                                        as *const libc::c_char,
+                                    start_mark,
+                                    b"found invalid Unicode character escape code\0" as *const u8
+                                        as *const libc::c_char,
+                                );
+                                current_block = 8114179180390253173;
+                                break 's_58;
+                            } else {
+                                if value <= 0x7F {
+                                    let fresh573 = string.pointer;
+                                    string.pointer = string.pointer.wrapping_offset(1);
+                                    *fresh573 = value as yaml_char_t;
+                                } else if value <= 0x7FF {
+                                    let fresh574 = string.pointer;
+                                    string.pointer = string.pointer.wrapping_offset(1);
+                                    *fresh574 = 0xC0_u32.wrapping_add(value >> 6) as yaml_char_t;
+                                    let fresh575 = string.pointer;
+                                    string.pointer = string.pointer.wrapping_offset(1);
+                                    *fresh575 = 0x80_u32.wrapping_add(value & 0x3F) as yaml_char_t;
+                                } else if value <= 0xFFFF {
+                                    let fresh576 = string.pointer;
+                                    string.pointer = string.pointer.wrapping_offset(1);
+                                    *fresh576 = 0xE0_u32.wrapping_add(value >> 12) as yaml_char_t;
+                                    let fresh577 = string.pointer;
+                                    string.pointer = string.pointer.wrapping_offset(1);
+                                    *fresh577 =
+                                        0x80_u32.wrapping_add(value >> 6 & 0x3F) as yaml_char_t;
+                                    let fresh578 = string.pointer;
+                                    string.pointer = string.pointer.wrapping_offset(1);
+                                    *fresh578 = 0x80_u32.wrapping_add(value & 0x3F) as yaml_char_t;
+                                } else {
+                                    let fresh579 = string.pointer;
+                                    string.pointer = string.pointer.wrapping_offset(1);
+                                    *fresh579 = 0xF0_u32.wrapping_add(value >> 18) as yaml_char_t;
+                                    let fresh580 = string.pointer;
+                                    string.pointer = string.pointer.wrapping_offset(1);
+                                    *fresh580 =
+                                        0x80_u32.wrapping_add(value >> 12 & 0x3F) as yaml_char_t;
+                                    let fresh581 = string.pointer;
+                                    string.pointer = string.pointer.wrapping_offset(1);
+                                    *fresh581 =
+                                        0x80_u32.wrapping_add(value >> 6 & 0x3F) as yaml_char_t;
+                                    let fresh582 = string.pointer;
+                                    string.pointer = string.pointer.wrapping_offset(1);
+                                    *fresh582 = 0x80_u32.wrapping_add(value & 0x3F) as yaml_char_t;
+                                }
+                                k = 0_u64;
+                                while k < code_length {
+                                    SKIP(parser);
+                                    k = k.wrapping_add(1);
+                                }
+                            }
+                        }
+                    } else {
+                        READ!(parser, string);
+                    }
+                }
+                if CACHE(parser, 2_u64).fail {
+                    current_block = 8114179180390253173;
+                    break 's_58;
+                }
+            }
+            if CACHE(parser, 1_u64).fail {
+                current_block = 8114179180390253173;
+                break;
+            }
+            if CHECK!((*parser).buffer, if single { b'\'' } else { b'"' }) {
+                current_block = 7468767852762055642;
+                break;
+            }
+            if CACHE(parser, 1_u64).fail {
+                current_block = 8114179180390253173;
+                break;
+            }
+            while IS_BLANK!((*parser).buffer) || IS_BREAK!((*parser).buffer) {
+                if IS_BLANK!((*parser).buffer) {
+                    if !leading_blanks {
+                        READ!(parser, whitespaces);
+                    } else {
+                        SKIP(parser);
+                    }
+                } else {
+                    if CACHE(parser, 2_u64).fail {
+                        current_block = 8114179180390253173;
+                        break 's_58;
+                    }
+                    if !leading_blanks {
+                        CLEAR!(whitespaces);
+                        READ_LINE!(parser, leading_break);
+                        leading_blanks = true;
+                    } else {
+                        READ_LINE!(parser, trailing_breaks);
+                    }
+                }
+                if CACHE(parser, 1_u64).fail {
+                    current_block = 8114179180390253173;
+                    break 's_58;
+                }
+            }
+            if leading_blanks {
+                if *leading_break.start == b'\n' {
+                    if *trailing_breaks.start == b'\0' {
+                        STRING_EXTEND!(string);
+                        let fresh711 = string.pointer;
+                        string.pointer = string.pointer.wrapping_offset(1);
+                        *fresh711 = b' ';
+                    } else {
+                        JOIN!(string, trailing_breaks);
+                        CLEAR!(trailing_breaks);
+                    }
+                    CLEAR!(leading_break);
+                } else {
+                    JOIN!(string, leading_break);
+                    JOIN!(string, trailing_breaks);
+                    CLEAR!(leading_break);
+                    CLEAR!(trailing_breaks);
+                }
+            } else {
+                JOIN!(string, whitespaces);
+                CLEAR!(whitespaces);
+            }
+        }
+    }
+    if current_block != 8114179180390253173 {
+        SKIP(parser);
+        end_mark = (*parser).mark;
+        memset(
+            token as *mut libc::c_void,
+            0,
+            size_of::<yaml_token_t>() as libc::c_ulong,
+        );
+        (*token).type_ = YAML_SCALAR_TOKEN;
+        (*token).start_mark = start_mark;
+        (*token).end_mark = end_mark;
+        let fresh716 = addr_of_mut!((*token).data.scalar.value);
+        *fresh716 = string.start;
+        (*token).data.scalar.length =
+            string.pointer.c_offset_from(string.start) as libc::c_long as size_t;
+        (*token).data.scalar.style = if single {
+            YAML_SINGLE_QUOTED_SCALAR_STYLE
+        } else {
+            YAML_DOUBLE_QUOTED_SCALAR_STYLE
+        };
+        STRING_DEL!(leading_break);
+        STRING_DEL!(trailing_breaks);
+        STRING_DEL!(whitespaces);
+        return OK;
+    }
+    STRING_DEL!(string);
+    STRING_DEL!(leading_break);
+    STRING_DEL!(trailing_breaks);
+    STRING_DEL!(whitespaces);
+    FAIL
+}
+
+unsafe fn yaml_parser_scan_plain_scalar(
+    parser: *mut yaml_parser_t,
+    token: *mut yaml_token_t,
+) -> Success {
+    let current_block: u64;
+    let mut end_mark: yaml_mark_t;
+    let mut string = NULL_STRING;
+    let mut leading_break = NULL_STRING;
+    let mut trailing_breaks = NULL_STRING;
+    let mut whitespaces = NULL_STRING;
+    let mut leading_blanks = false;
+    let indent: libc::c_int = (*parser).indent + 1;
+    STRING_INIT!(string);
+    STRING_INIT!(leading_break);
+    STRING_INIT!(trailing_breaks);
+    STRING_INIT!(whitespaces);
+    end_mark = (*parser).mark;
+    let start_mark: yaml_mark_t = end_mark;
+    's_57: loop {
+        if CACHE(parser, 4_u64).fail {
+            current_block = 16642808987012640029;
+            break;
+        }
+        if (*parser).mark.column == 0_u64
+            && (CHECK_AT!((*parser).buffer, b'-', 0)
+                && CHECK_AT!((*parser).buffer, b'-', 1)
+                && CHECK_AT!((*parser).buffer, b'-', 2)
+                || CHECK_AT!((*parser).buffer, b'.', 0)
+                    && CHECK_AT!((*parser).buffer, b'.', 1)
+                    && CHECK_AT!((*parser).buffer, b'.', 2))
+            && IS_BLANKZ_AT!((*parser).buffer, 3)
+        {
+            current_block = 6281126495347172768;
+            break;
+        }
+        if CHECK!((*parser).buffer, b'#') {
+            current_block = 6281126495347172768;
+            break;
+        }
+        while !IS_BLANKZ!((*parser).buffer) {
+            if (*parser).flow_level != 0
+                && CHECK!((*parser).buffer, b':')
+                && (CHECK_AT!((*parser).buffer, b',', 1)
+                    || CHECK_AT!((*parser).buffer, b'?', 1)
+                    || CHECK_AT!((*parser).buffer, b'[', 1)
+                    || CHECK_AT!((*parser).buffer, b']', 1)
+                    || CHECK_AT!((*parser).buffer, b'{', 1)
+                    || CHECK_AT!((*parser).buffer, b'}', 1))
+            {
+                yaml_parser_set_scanner_error(
+                    parser,
+                    b"while scanning a plain scalar\0" as *const u8 as *const libc::c_char,
+                    start_mark,
+                    b"found unexpected ':'\0" as *const u8 as *const libc::c_char,
+                );
+                current_block = 16642808987012640029;
+                break 's_57;
+            } else {
+                if CHECK!((*parser).buffer, b':') && IS_BLANKZ_AT!((*parser).buffer, 1)
+                    || (*parser).flow_level != 0
+                        && (CHECK!((*parser).buffer, b',')
+                            || CHECK!((*parser).buffer, b'[')
+                            || CHECK!((*parser).buffer, b']')
+                            || CHECK!((*parser).buffer, b'{')
+                            || CHECK!((*parser).buffer, b'}'))
+                {
+                    break;
+                }
+                if leading_blanks || whitespaces.start != whitespaces.pointer {
+                    if leading_blanks {
+                        if *leading_break.start == b'\n' {
+                            if *trailing_breaks.start == b'\0' {
+                                STRING_EXTEND!(string);
+                                let fresh717 = string.pointer;
+                                string.pointer = string.pointer.wrapping_offset(1);
+                                *fresh717 = b' ';
+                            } else {
+                                JOIN!(string, trailing_breaks);
+                                CLEAR!(trailing_breaks);
+                            }
+                            CLEAR!(leading_break);
+                        } else {
+                            JOIN!(string, leading_break);
+                            JOIN!(string, trailing_breaks);
+                            CLEAR!(leading_break);
+                            CLEAR!(trailing_breaks);
+                        }
+                        leading_blanks = false;
+                    } else {
+                        JOIN!(string, whitespaces);
+                        CLEAR!(whitespaces);
+                    }
+                }
+                READ!(parser, string);
+                end_mark = (*parser).mark;
+                if CACHE(parser, 2_u64).fail {
+                    current_block = 16642808987012640029;
+                    break 's_57;
+                }
+            }
+        }
+        if !(IS_BLANK!((*parser).buffer) || IS_BREAK!((*parser).buffer)) {
+            current_block = 6281126495347172768;
+            break;
+        }
+        if CACHE(parser, 1_u64).fail {
+            current_block = 16642808987012640029;
+            break;
+        }
+        while IS_BLANK!((*parser).buffer) || IS_BREAK!((*parser).buffer) {
+            if IS_BLANK!((*parser).buffer) {
+                if leading_blanks
+                    && ((*parser).mark.column as libc::c_int) < indent
+                    && IS_TAB!((*parser).buffer)
+                {
+                    yaml_parser_set_scanner_error(
+                        parser,
+                        b"while scanning a plain scalar\0" as *const u8 as *const libc::c_char,
+                        start_mark,
+                        b"found a tab character that violates indentation\0" as *const u8
+                            as *const libc::c_char,
+                    );
+                    current_block = 16642808987012640029;
+                    break 's_57;
+                } else if !leading_blanks {
+                    READ!(parser, whitespaces);
+                } else {
+                    SKIP(parser);
+                }
+            } else {
+                if CACHE(parser, 2_u64).fail {
+                    current_block = 16642808987012640029;
+                    break 's_57;
+                }
+                if !leading_blanks {
+                    CLEAR!(whitespaces);
+                    READ_LINE!(parser, leading_break);
+                    leading_blanks = true;
+                } else {
+                    READ_LINE!(parser, trailing_breaks);
+                }
+            }
+            if CACHE(parser, 1_u64).fail {
+                current_block = 16642808987012640029;
+                break 's_57;
+            }
+        }
+        if (*parser).flow_level == 0 && ((*parser).mark.column as libc::c_int) < indent {
+            current_block = 6281126495347172768;
+            break;
+        }
+    }
+    if current_block != 16642808987012640029 {
+        memset(
+            token as *mut libc::c_void,
+            0,
+            size_of::<yaml_token_t>() as libc::c_ulong,
+        );
+        (*token).type_ = YAML_SCALAR_TOKEN;
+        (*token).start_mark = start_mark;
+        (*token).end_mark = end_mark;
+        let fresh842 = addr_of_mut!((*token).data.scalar.value);
+        *fresh842 = string.start;
+        (*token).data.scalar.length =
+            string.pointer.c_offset_from(string.start) as libc::c_long as size_t;
+        (*token).data.scalar.style = YAML_PLAIN_SCALAR_STYLE;
+        if leading_blanks {
+            (*parser).simple_key_allowed = true;
+        }
+        STRING_DEL!(leading_break);
+        STRING_DEL!(trailing_breaks);
+        STRING_DEL!(whitespaces);
+        return OK;
+    }
+    STRING_DEL!(string);
+    STRING_DEL!(leading_break);
+    STRING_DEL!(trailing_breaks);
+    STRING_DEL!(whitespaces);
+    FAIL
+}
diff --git a/src/success.rs b/src/success.rs
new file mode 100644
index 0000000..c004d17
--- /dev/null
+++ b/src/success.rs
@@ -0,0 +1,25 @@
+use core::ops::Deref;
+
+pub const OK: Success = Success { ok: true };
+pub const FAIL: Success = Success { ok: false };
+
+#[must_use]
+pub struct Success {
+    pub ok: bool,
+}
+
+pub struct Failure {
+    pub fail: bool,
+}
+
+impl Deref for Success {
+    type Target = Failure;
+
+    fn deref(&self) -> &Self::Target {
+        if self.ok {
+            &Failure { fail: false }
+        } else {
+            &Failure { fail: true }
+        }
+    }
+}
diff --git a/src/writer.rs b/src/writer.rs
new file mode 100644
index 0000000..11405bc
--- /dev/null
+++ b/src/writer.rs
@@ -0,0 +1,148 @@
+use crate::success::{Success, FAIL, OK};
+use crate::yaml::size_t;
+use crate::{
+    libc, yaml_emitter_t, PointerExt, YAML_ANY_ENCODING, YAML_UTF16LE_ENCODING, YAML_UTF8_ENCODING,
+    YAML_WRITER_ERROR,
+};
+use core::ptr::addr_of_mut;
+
+unsafe fn yaml_emitter_set_writer_error(
+    emitter: *mut yaml_emitter_t,
+    problem: *const libc::c_char,
+) -> Success {
+    (*emitter).error = YAML_WRITER_ERROR;
+    let fresh0 = addr_of_mut!((*emitter).problem);
+    *fresh0 = problem;
+    FAIL
+}
+
+/// Flush the accumulated characters to the output.
+pub unsafe fn yaml_emitter_flush(emitter: *mut yaml_emitter_t) -> Success {
+    __assert!(!emitter.is_null());
+    __assert!(((*emitter).write_handler).is_some());
+    __assert!((*emitter).encoding != YAML_ANY_ENCODING);
+    let fresh1 = addr_of_mut!((*emitter).buffer.last);
+    *fresh1 = (*emitter).buffer.pointer;
+    let fresh2 = addr_of_mut!((*emitter).buffer.pointer);
+    *fresh2 = (*emitter).buffer.start;
+    if (*emitter).buffer.start == (*emitter).buffer.last {
+        return OK;
+    }
+    if (*emitter).encoding == YAML_UTF8_ENCODING {
+        if (*emitter).write_handler.expect("non-null function pointer")(
+            (*emitter).write_handler_data,
+            (*emitter).buffer.start,
+            (*emitter)
+                .buffer
+                .last
+                .c_offset_from((*emitter).buffer.start) as libc::c_long as size_t,
+        ) != 0
+        {
+            let fresh3 = addr_of_mut!((*emitter).buffer.last);
+            *fresh3 = (*emitter).buffer.start;
+            let fresh4 = addr_of_mut!((*emitter).buffer.pointer);
+            *fresh4 = (*emitter).buffer.start;
+            return OK;
+        } else {
+            return yaml_emitter_set_writer_error(
+                emitter,
+                b"write error\0" as *const u8 as *const libc::c_char,
+            );
+        }
+    }
+    let low: libc::c_int = if (*emitter).encoding == YAML_UTF16LE_ENCODING {
+        0
+    } else {
+        1
+    };
+    let high: libc::c_int = if (*emitter).encoding == YAML_UTF16LE_ENCODING {
+        1
+    } else {
+        0
+    };
+    while (*emitter).buffer.pointer != (*emitter).buffer.last {
+        let mut octet: libc::c_uchar;
+        let mut value: libc::c_uint;
+        let mut k: size_t;
+        octet = *(*emitter).buffer.pointer;
+        let width: libc::c_uint = if octet & 0x80 == 0 {
+            1
+        } else if octet & 0xE0 == 0xC0 {
+            2
+        } else if octet & 0xF0 == 0xE0 {
+            3
+        } else if octet & 0xF8 == 0xF0 {
+            4
+        } else {
+            0
+        } as libc::c_uint;
+        value = if octet & 0x80 == 0 {
+            octet & 0x7F
+        } else if octet & 0xE0 == 0xC0 {
+            octet & 0x1F
+        } else if octet & 0xF0 == 0xE0 {
+            octet & 0xF
+        } else if octet & 0xF8 == 0xF0 {
+            octet & 0x7
+        } else {
+            0
+        } as libc::c_uint;
+        k = 1_u64;
+        while k < width as libc::c_ulong {
+            octet = *(*emitter).buffer.pointer.wrapping_offset(k as isize);
+            value = (value << 6).wrapping_add((octet & 0x3F) as libc::c_uint);
+            k = k.wrapping_add(1);
+        }
+        let fresh5 = addr_of_mut!((*emitter).buffer.pointer);
+        *fresh5 = (*fresh5).wrapping_offset(width as isize);
+        if value < 0x10000 {
+            *(*emitter).raw_buffer.last.wrapping_offset(high as isize) =
+                (value >> 8) as libc::c_uchar;
+            *(*emitter).raw_buffer.last.wrapping_offset(low as isize) =
+                (value & 0xFF) as libc::c_uchar;
+            let fresh6 = addr_of_mut!((*emitter).raw_buffer.last);
+            *fresh6 = (*fresh6).wrapping_offset(2_isize);
+        } else {
+            value = value.wrapping_sub(0x10000);
+            *(*emitter).raw_buffer.last.wrapping_offset(high as isize) =
+                0xD8_u32.wrapping_add(value >> 18) as libc::c_uchar;
+            *(*emitter).raw_buffer.last.wrapping_offset(low as isize) =
+                (value >> 10 & 0xFF) as libc::c_uchar;
+            *(*emitter)
+                .raw_buffer
+                .last
+                .wrapping_offset((high + 2) as isize) =
+                0xDC_u32.wrapping_add(value >> 8 & 0xFF) as libc::c_uchar;
+            *(*emitter)
+                .raw_buffer
+                .last
+                .wrapping_offset((low + 2) as isize) = (value & 0xFF) as libc::c_uchar;
+            let fresh7 = addr_of_mut!((*emitter).raw_buffer.last);
+            *fresh7 = (*fresh7).wrapping_offset(4_isize);
+        }
+    }
+    if (*emitter).write_handler.expect("non-null function pointer")(
+        (*emitter).write_handler_data,
+        (*emitter).raw_buffer.start,
+        (*emitter)
+            .raw_buffer
+            .last
+            .c_offset_from((*emitter).raw_buffer.start) as libc::c_long as size_t,
+    ) != 0
+    {
+        let fresh8 = addr_of_mut!((*emitter).buffer.last);
+        *fresh8 = (*emitter).buffer.start;
+        let fresh9 = addr_of_mut!((*emitter).buffer.pointer);
+        *fresh9 = (*emitter).buffer.start;
+        let fresh10 = addr_of_mut!((*emitter).raw_buffer.last);
+        *fresh10 = (*emitter).raw_buffer.start;
+        let fresh11 = addr_of_mut!((*emitter).raw_buffer.pointer);
+        *fresh11 = (*emitter).raw_buffer.start;
+        OK
+    } else {
+        yaml_emitter_set_writer_error(
+            emitter,
+            b"write error\0" as *const u8 as *const libc::c_char,
+        )
+    }
+}
diff --git a/src/yaml.rs b/src/yaml.rs
new file mode 100644
index 0000000..dfffe9c
--- /dev/null
+++ b/src/yaml.rs
@@ -0,0 +1,1284 @@
+use crate::libc;
+use core::ops::Deref;
+use core::ptr::{self, addr_of};
+
+pub use self::{
+    yaml_break_t::*, yaml_emitter_state_t::*, yaml_encoding_t::*, yaml_error_type_t::*,
+    yaml_event_type_t::*, yaml_mapping_style_t::*, yaml_node_type_t::*, yaml_parser_state_t::*,
+    yaml_scalar_style_t::*, yaml_sequence_style_t::*, yaml_token_type_t::*,
+};
+pub use core::primitive::{i64 as ptrdiff_t, u64 as size_t, u8 as yaml_char_t};
+
+/// The version directive data.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_version_directive_t {
+    /// The major version number.
+    pub major: libc::c_int,
+    /// The minor version number.
+    pub minor: libc::c_int,
+}
+
+/// The tag directive data.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_tag_directive_t {
+    /// The tag handle.
+    pub handle: *mut yaml_char_t,
+    /// The tag prefix.
+    pub prefix: *mut yaml_char_t,
+}
+
+/// The stream encoding.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_encoding_t {
+    /// Let the parser choose the encoding.
+    YAML_ANY_ENCODING = 0,
+    /// The default UTF-8 encoding.
+    YAML_UTF8_ENCODING = 1,
+    /// The UTF-16-LE encoding with BOM.
+    YAML_UTF16LE_ENCODING = 2,
+    /// The UTF-16-BE encoding with BOM.
+    YAML_UTF16BE_ENCODING = 3,
+}
+
+/// Line break type.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_break_t {
+    /// Let the parser choose the break type.
+    YAML_ANY_BREAK = 0,
+    /// Use CR for line breaks (Mac style).
+    YAML_CR_BREAK = 1,
+    /// Use LN for line breaks (Unix style).
+    YAML_LN_BREAK = 2,
+    /// Use CR LN for line breaks (DOS style).
+    YAML_CRLN_BREAK = 3,
+}
+
+/// Many bad things could happen with the parser and emitter.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_error_type_t {
+    /// No error is produced.
+    YAML_NO_ERROR = 0,
+    /// Cannot allocate or reallocate a block of memory.
+    YAML_MEMORY_ERROR = 1,
+    /// Cannot read or decode the input stream.
+    YAML_READER_ERROR = 2,
+    /// Cannot scan the input stream.
+    YAML_SCANNER_ERROR = 3,
+    /// Cannot parse the input stream.
+    YAML_PARSER_ERROR = 4,
+    /// Cannot compose a YAML document.
+    YAML_COMPOSER_ERROR = 5,
+    /// Cannot write to the output stream.
+    YAML_WRITER_ERROR = 6,
+    /// Cannot emit a YAML stream.
+    YAML_EMITTER_ERROR = 7,
+}
+
+/// The pointer position.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_mark_t {
+    /// The position index.
+    pub index: size_t,
+    /// The position line.
+    pub line: size_t,
+    /// The position column.
+    pub column: size_t,
+}
+
+/// Scalar styles.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_scalar_style_t {
+    /// Let the emitter choose the style.
+    YAML_ANY_SCALAR_STYLE = 0,
+    /// The plain scalar style.
+    YAML_PLAIN_SCALAR_STYLE = 1,
+    /// The single-quoted scalar style.
+    YAML_SINGLE_QUOTED_SCALAR_STYLE = 2,
+    /// The double-quoted scalar style.
+    YAML_DOUBLE_QUOTED_SCALAR_STYLE = 3,
+    /// The literal scalar style.
+    YAML_LITERAL_SCALAR_STYLE = 4,
+    /// The folded scalar style.
+    YAML_FOLDED_SCALAR_STYLE = 5,
+}
+
+/// Sequence styles.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_sequence_style_t {
+    /// Let the emitter choose the style.
+    YAML_ANY_SEQUENCE_STYLE = 0,
+    /// The block sequence style.
+    YAML_BLOCK_SEQUENCE_STYLE = 1,
+    /// The flow sequence style.
+    YAML_FLOW_SEQUENCE_STYLE = 2,
+}
+
+/// Mapping styles.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_mapping_style_t {
+    /// Let the emitter choose the style.
+    YAML_ANY_MAPPING_STYLE = 0,
+    /// The block mapping style.
+    YAML_BLOCK_MAPPING_STYLE = 1,
+    /// The flow mapping style.
+    YAML_FLOW_MAPPING_STYLE = 2,
+}
+
+/// Token types.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_token_type_t {
+    /// An empty token.
+    YAML_NO_TOKEN = 0,
+    /// A STREAM-START token.
+    YAML_STREAM_START_TOKEN = 1,
+    /// A STREAM-END token.
+    YAML_STREAM_END_TOKEN = 2,
+    /// A VERSION-DIRECTIVE token.
+    YAML_VERSION_DIRECTIVE_TOKEN = 3,
+    /// A TAG-DIRECTIVE token.
+    YAML_TAG_DIRECTIVE_TOKEN = 4,
+    /// A DOCUMENT-START token.
+    YAML_DOCUMENT_START_TOKEN = 5,
+    /// A DOCUMENT-END token.
+    YAML_DOCUMENT_END_TOKEN = 6,
+    /// A BLOCK-SEQUENCE-START token.
+    YAML_BLOCK_SEQUENCE_START_TOKEN = 7,
+    /// A BLOCK-MAPPING-START token.
+    YAML_BLOCK_MAPPING_START_TOKEN = 8,
+    /// A BLOCK-END token.
+    YAML_BLOCK_END_TOKEN = 9,
+    /// A FLOW-SEQUENCE-START token.
+    YAML_FLOW_SEQUENCE_START_TOKEN = 10,
+    /// A FLOW-SEQUENCE-END token.
+    YAML_FLOW_SEQUENCE_END_TOKEN = 11,
+    /// A FLOW-MAPPING-START token.
+    YAML_FLOW_MAPPING_START_TOKEN = 12,
+    /// A FLOW-MAPPING-END token.
+    YAML_FLOW_MAPPING_END_TOKEN = 13,
+    /// A BLOCK-ENTRY token.
+    YAML_BLOCK_ENTRY_TOKEN = 14,
+    /// A FLOW-ENTRY token.
+    YAML_FLOW_ENTRY_TOKEN = 15,
+    /// A KEY token.
+    YAML_KEY_TOKEN = 16,
+    /// A VALUE token.
+    YAML_VALUE_TOKEN = 17,
+    /// An ALIAS token.
+    YAML_ALIAS_TOKEN = 18,
+    /// An ANCHOR token.
+    YAML_ANCHOR_TOKEN = 19,
+    /// A TAG token.
+    YAML_TAG_TOKEN = 20,
+    /// A SCALAR token.
+    YAML_SCALAR_TOKEN = 21,
+}
+
+/// The token structure.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_token_t {
+    /// The token type.
+    pub type_: yaml_token_type_t,
+    /// The token data.
+    ///
+    /// ```
+    /// # const _: &str = stringify! {
+    /// union {
+    ///     /// The stream start (for YAML_STREAM_START_TOKEN).
+    ///     stream_start: struct {
+    ///         /// The stream encoding.
+    ///         encoding: yaml_encoding_t,
+    ///     },
+    ///     /// The alias (for YAML_ALIAS_TOKEN).
+    ///     alias: struct {
+    ///         /// The alias value.
+    ///         value: *mut u8,
+    ///     },
+    ///     /// The anchor (for YAML_ANCHOR_TOKEN).
+    ///     anchor: struct {
+    ///         /// The anchor value.
+    ///         value: *mut u8,
+    ///     },
+    ///     /// The tag (for YAML_TAG_TOKEN).
+    ///     tag: struct {
+    ///         /// The tag handle.
+    ///         handle: *mut u8,
+    ///         /// The tag suffix.
+    ///         suffix: *mut u8,
+    ///     },
+    ///     /// The scalar value (for YAML_SCALAR_TOKEN).
+    ///     scalar: struct {
+    ///         /// The scalar value.
+    ///         value: *mut u8,
+    ///         /// The length of the scalar value.
+    ///         length: u64,
+    ///         /// The scalar style.
+    ///         style: yaml_scalar_style_t,
+    ///     },
+    ///     /// The version directive (for YAML_VERSION_DIRECTIVE_TOKEN).
+    ///     version_directive: struct {
+    ///         /// The major version number.
+    ///         major: i32,
+    ///         /// The minor version number.
+    ///         minor: i32,
+    ///     },
+    ///     /// The tag directive (for YAML_TAG_DIRECTIVE_TOKEN).
+    ///     tag_directive: struct {
+    ///         /// The tag handle.
+    ///         handle: *mut u8,
+    ///         /// The tag prefix.
+    ///         prefix: *mut u8,
+    ///     },
+    /// }
+    /// # };
+    /// ```
+    pub data: unnamed_yaml_token_t_data,
+    /// The beginning of the token.
+    pub start_mark: yaml_mark_t,
+    /// The end of the token.
+    pub end_mark: yaml_mark_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub union unnamed_yaml_token_t_data {
+    /// The stream start (for YAML_STREAM_START_TOKEN).
+    pub stream_start: unnamed_yaml_token_t_data_stream_start,
+    /// The alias (for YAML_ALIAS_TOKEN).
+    pub alias: unnamed_yaml_token_t_data_alias,
+    /// The anchor (for YAML_ANCHOR_TOKEN).
+    pub anchor: unnamed_yaml_token_t_data_anchor,
+    /// The tag (for YAML_TAG_TOKEN).
+    pub tag: unnamed_yaml_token_t_data_tag,
+    /// The scalar value (for YAML_SCALAR_TOKEN).
+    pub scalar: unnamed_yaml_token_t_data_scalar,
+    /// The version directive (for YAML_VERSION_DIRECTIVE_TOKEN).
+    pub version_directive: unnamed_yaml_token_t_data_version_directive,
+    /// The tag directive (for YAML_TAG_DIRECTIVE_TOKEN).
+    pub tag_directive: unnamed_yaml_token_t_data_tag_directive,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_token_t_data_stream_start {
+    /// The stream encoding.
+    pub encoding: yaml_encoding_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_token_t_data_alias {
+    /// The alias value.
+    pub value: *mut yaml_char_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_token_t_data_anchor {
+    /// The anchor value.
+    pub value: *mut yaml_char_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_token_t_data_tag {
+    /// The tag handle.
+    pub handle: *mut yaml_char_t,
+    /// The tag suffix.
+    pub suffix: *mut yaml_char_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_token_t_data_scalar {
+    /// The scalar value.
+    pub value: *mut yaml_char_t,
+    /// The length of the scalar value.
+    pub length: size_t,
+    /// The scalar style.
+    pub style: yaml_scalar_style_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_token_t_data_version_directive {
+    /// The major version number.
+    pub major: libc::c_int,
+    /// The minor version number.
+    pub minor: libc::c_int,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_token_t_data_tag_directive {
+    /// The tag handle.
+    pub handle: *mut yaml_char_t,
+    /// The tag prefix.
+    pub prefix: *mut yaml_char_t,
+}
+
+/// Event types.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_event_type_t {
+    /// An empty event.
+    YAML_NO_EVENT = 0,
+    /// A STREAM-START event.
+    YAML_STREAM_START_EVENT = 1,
+    /// A STREAM-END event.
+    YAML_STREAM_END_EVENT = 2,
+    /// A DOCUMENT-START event.
+    YAML_DOCUMENT_START_EVENT = 3,
+    /// A DOCUMENT-END event.
+    YAML_DOCUMENT_END_EVENT = 4,
+    /// An ALIAS event.
+    YAML_ALIAS_EVENT = 5,
+    /// A SCALAR event.
+    YAML_SCALAR_EVENT = 6,
+    /// A SEQUENCE-START event.
+    YAML_SEQUENCE_START_EVENT = 7,
+    /// A SEQUENCE-END event.
+    YAML_SEQUENCE_END_EVENT = 8,
+    /// A MAPPING-START event.
+    YAML_MAPPING_START_EVENT = 9,
+    /// A MAPPING-END event.
+    YAML_MAPPING_END_EVENT = 10,
+}
+
+/// The event structure.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_event_t {
+    /// The event type.
+    pub type_: yaml_event_type_t,
+    /// The event data.
+    ///
+    /// ```
+    /// # const _: &str = stringify! {
+    /// union {
+    ///     /// The stream parameters (for YAML_STREAM_START_EVENT).
+    ///     stream_start: struct {
+    ///         /// The document encoding.
+    ///         encoding: yaml_encoding_t,
+    ///     },
+    ///     /// The document parameters (for YAML_DOCUMENT_START_EVENT).
+    ///     document_start: struct {
+    ///         /// The version directive.
+    ///         version_directive: *mut yaml_version_directive_t,
+    ///         /// The list of tag directives.
+    ///         tag_directives: struct {
+    ///             /// The beginning of the tag directives list.
+    ///             start: *mut yaml_tag_directive_t,
+    ///             /// The end of the tag directives list.
+    ///             end: *mut yaml_tag_directive_t,
+    ///         },
+    ///         /// Is the document indicator implicit?
+    ///         implicit: i32,
+    ///     },
+    ///     /// The document end parameters (for YAML_DOCUMENT_END_EVENT).
+    ///     document_end: struct {
+    ///         /// Is the document end indicator implicit?
+    ///         implicit: i32,
+    ///     },
+    ///     /// The alias parameters (for YAML_ALIAS_EVENT).
+    ///     alias: struct {
+    ///         /// The anchor.
+    ///         anchor: *mut u8,
+    ///     },
+    ///     /// The scalar parameters (for YAML_SCALAR_EVENT).
+    ///     scalar: struct {
+    ///         /// The anchor.
+    ///         anchor: *mut u8,
+    ///         /// The tag.
+    ///         tag: *mut u8,
+    ///         /// The scalar value.
+    ///         value: *mut u8,
+    ///         /// The length of the scalar value.
+    ///         length: u64,
+    ///         /// Is the tag optional for the plain style?
+    ///         plain_implicit: i32,
+    ///         /// Is the tag optional for any non-plain style?
+    ///         quoted_implicit: i32,
+    ///         /// The scalar style.
+    ///         style: yaml_scalar_style_t,
+    ///     },
+    ///     /// The sequence parameters (for YAML_SEQUENCE_START_EVENT).
+    ///     sequence_start: struct {
+    ///         /// The anchor.
+    ///         anchor: *mut u8,
+    ///         /// The tag.
+    ///         tag: *mut u8,
+    ///         /// Is the tag optional?
+    ///         implicit: i32,
+    ///         /// The sequence style.
+    ///         style: yaml_sequence_style_t,
+    ///     },
+    ///     /// The mapping parameters (for YAML_MAPPING_START_EVENT).
+    ///     mapping_start: struct {
+    ///         /// The anchor.
+    ///         anchor: *mut u8,
+    ///         /// The tag.
+    ///         tag: *mut u8,
+    ///         /// Is the tag optional?
+    ///         implicit: i32,
+    ///         /// The mapping style.
+    ///         style: yaml_mapping_style_t,
+    ///     },
+    /// }
+    /// # };
+    /// ```
+    pub data: unnamed_yaml_event_t_data,
+    /// The beginning of the event.
+    pub start_mark: yaml_mark_t,
+    /// The end of the event.
+    pub end_mark: yaml_mark_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub union unnamed_yaml_event_t_data {
+    /// The stream parameters (for YAML_STREAM_START_EVENT).
+    pub stream_start: unnamed_yaml_event_t_data_stream_start,
+    /// The document parameters (for YAML_DOCUMENT_START_EVENT).
+    pub document_start: unnamed_yaml_event_t_data_document_start,
+    /// The document end parameters (for YAML_DOCUMENT_END_EVENT).
+    pub document_end: unnamed_yaml_event_t_data_document_end,
+    /// The alias parameters (for YAML_ALIAS_EVENT).
+    pub alias: unnamed_yaml_event_t_data_alias,
+    /// The scalar parameters (for YAML_SCALAR_EVENT).
+    pub scalar: unnamed_yaml_event_t_data_scalar,
+    /// The sequence parameters (for YAML_SEQUENCE_START_EVENT).
+    pub sequence_start: unnamed_yaml_event_t_data_sequence_start,
+    /// The mapping parameters (for YAML_MAPPING_START_EVENT).
+    pub mapping_start: unnamed_yaml_event_t_data_mapping_start,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_event_t_data_stream_start {
+    /// The document encoding.
+    pub encoding: yaml_encoding_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_event_t_data_document_start {
+    /// The version directive.
+    pub version_directive: *mut yaml_version_directive_t,
+    /// The list of tag directives.
+    pub tag_directives: unnamed_yaml_event_t_data_document_start_tag_directives,
+    /// Is the document indicator implicit?
+    pub implicit: bool,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_event_t_data_document_start_tag_directives {
+    /// The beginning of the tag directives list.
+    pub start: *mut yaml_tag_directive_t,
+    /// The end of the tag directives list.
+    pub end: *mut yaml_tag_directive_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_event_t_data_document_end {
+    /// Is the document end indicator implicit?
+    pub implicit: bool,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_event_t_data_alias {
+    /// The anchor.
+    pub anchor: *mut yaml_char_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_event_t_data_scalar {
+    /// The anchor.
+    pub anchor: *mut yaml_char_t,
+    /// The tag.
+    pub tag: *mut yaml_char_t,
+    /// The scalar value.
+    pub value: *mut yaml_char_t,
+    /// The length of the scalar value.
+    pub length: size_t,
+    /// Is the tag optional for the plain style?
+    pub plain_implicit: bool,
+    /// Is the tag optional for any non-plain style?
+    pub quoted_implicit: bool,
+    /// The scalar style.
+    pub style: yaml_scalar_style_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_event_t_data_sequence_start {
+    /// The anchor.
+    pub anchor: *mut yaml_char_t,
+    /// The tag.
+    pub tag: *mut yaml_char_t,
+    /// Is the tag optional?
+    pub implicit: bool,
+    /// The sequence style.
+    pub style: yaml_sequence_style_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_event_t_data_mapping_start {
+    /// The anchor.
+    pub anchor: *mut yaml_char_t,
+    /// The tag.
+    pub tag: *mut yaml_char_t,
+    /// Is the tag optional?
+    pub implicit: bool,
+    /// The mapping style.
+    pub style: yaml_mapping_style_t,
+}
+
+/// Node types.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_node_type_t {
+    /// An empty node.
+    YAML_NO_NODE = 0,
+    /// A scalar node.
+    YAML_SCALAR_NODE = 1,
+    /// A sequence node.
+    YAML_SEQUENCE_NODE = 2,
+    /// A mapping node.
+    YAML_MAPPING_NODE = 3,
+}
+
+/// The node structure.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_node_t {
+    /// The node type.
+    pub type_: yaml_node_type_t,
+    /// The node tag.
+    pub tag: *mut yaml_char_t,
+    /// The node data.
+    ///
+    /// ```
+    /// # const _: &str = stringify! {
+    /// union {
+    ///     /// The scalar parameters (for YAML_SCALAR_NODE).
+    ///     scalar: struct {
+    ///         /// The scalar value.
+    ///         value: *mut u8,
+    ///         /// The length of the scalar value.
+    ///         length: u64,
+    ///         /// The scalar style.
+    ///         style: yaml_scalar_style_t,
+    ///     },
+    ///     /// The sequence parameters (for YAML_SEQUENCE_NODE).
+    ///     sequence: struct {
+    ///         /// The stack of sequence items.
+    ///         items: yaml_stack_t<yaml_node_item_t>,
+    ///         /// The sequence style.
+    ///         style: yaml_sequence_style_t,
+    ///     },
+    ///     /// The mapping parameters (for YAML_MAPPING_NODE).
+    ///     mapping: struct {
+    ///         /// The stack of mapping pairs (key, value).
+    ///         pairs: yaml_stack_t<yaml_node_pair_t>,
+    ///         /// The mapping style.
+    ///         style: yaml_mapping_style_t,
+    ///     },
+    /// }
+    /// # };
+    /// ```
+    pub data: unnamed_yaml_node_t_data,
+    /// The beginning of the node.
+    pub start_mark: yaml_mark_t,
+    /// The end of the node.
+    pub end_mark: yaml_mark_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub union unnamed_yaml_node_t_data {
+    /// The scalar parameters (for YAML_SCALAR_NODE).
+    pub scalar: unnamed_yaml_node_t_data_scalar,
+    /// The sequence parameters (for YAML_SEQUENCE_NODE).
+    pub sequence: unnamed_yaml_node_t_data_sequence,
+    /// The mapping parameters (for YAML_MAPPING_NODE).
+    pub mapping: unnamed_yaml_node_t_data_mapping,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_node_t_data_scalar {
+    /// The scalar value.
+    pub value: *mut yaml_char_t,
+    /// The length of the scalar value.
+    pub length: size_t,
+    /// The scalar style.
+    pub style: yaml_scalar_style_t,
+}
+
+/// An element of a sequence node.
+pub type yaml_node_item_t = libc::c_int;
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_node_t_data_sequence {
+    /// The stack of sequence items.
+    pub items: yaml_stack_t<yaml_node_item_t>,
+    /// The sequence style.
+    pub style: yaml_sequence_style_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_node_t_data_mapping {
+    /// The stack of mapping pairs (key, value).
+    pub pairs: yaml_stack_t<yaml_node_pair_t>,
+    /// The mapping style.
+    pub style: yaml_mapping_style_t,
+}
+
+/// An element of a mapping node.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_node_pair_t {
+    /// The key of the element.
+    pub key: libc::c_int,
+    /// The value of the element.
+    pub value: libc::c_int,
+}
+
+/// The document structure.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_document_t {
+    /// The document nodes.
+    pub nodes: yaml_stack_t<yaml_node_t>,
+    /// The version directive.
+    pub version_directive: *mut yaml_version_directive_t,
+    /// The list of tag directives.
+    ///
+    /// ```
+    /// # const _: &str = stringify! {
+    /// struct {
+    ///     /// The beginning of the tag directives list.
+    ///     start: *mut yaml_tag_directive_t,
+    ///     /// The end of the tag directives list.
+    ///     end: *mut yaml_tag_directive_t,
+    /// }
+    /// # };
+    /// ```
+    pub tag_directives: unnamed_yaml_document_t_tag_directives,
+    /// Is the document start indicator implicit?
+    pub start_implicit: bool,
+    /// Is the document end indicator implicit?
+    pub end_implicit: bool,
+    /// The beginning of the document.
+    pub start_mark: yaml_mark_t,
+    /// The end of the document.
+    pub end_mark: yaml_mark_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct unnamed_yaml_document_t_tag_directives {
+    /// The beginning of the tag directives list.
+    pub start: *mut yaml_tag_directive_t,
+    /// The end of the tag directives list.
+    pub end: *mut yaml_tag_directive_t,
+}
+
+/// The prototype of a read handler.
+///
+/// The read handler is called when the parser needs to read more bytes from the
+/// source. The handler should write not more than `size` bytes to the `buffer`.
+/// The number of written bytes should be set to the `length` variable.
+///
+/// On success, the handler should return 1. If the handler failed, the returned
+/// value should be 0. On EOF, the handler should set the `size_read` to 0 and
+/// return 1.
+pub type yaml_read_handler_t = unsafe fn(
+    data: *mut libc::c_void,
+    buffer: *mut libc::c_uchar,
+    size: size_t,
+    size_read: *mut size_t,
+) -> libc::c_int;
+
+/// This structure holds information about a potential simple key.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_simple_key_t {
+    /// Is a simple key possible?
+    pub possible: bool,
+    /// Is a simple key required?
+    pub required: bool,
+    /// The number of the token.
+    pub token_number: size_t,
+    /// The position mark.
+    pub mark: yaml_mark_t,
+}
+
+/// The states of the parser.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_parser_state_t {
+    /// Expect STREAM-START.
+    YAML_PARSE_STREAM_START_STATE = 0,
+    /// Expect the beginning of an implicit document.
+    YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE = 1,
+    /// Expect DOCUMENT-START.
+    YAML_PARSE_DOCUMENT_START_STATE = 2,
+    /// Expect the content of a document.
+    YAML_PARSE_DOCUMENT_CONTENT_STATE = 3,
+    /// Expect DOCUMENT-END.
+    YAML_PARSE_DOCUMENT_END_STATE = 4,
+    /// Expect a block node.
+    YAML_PARSE_BLOCK_NODE_STATE = 5,
+    /// Expect a block node or indentless sequence.
+    YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE = 6,
+    /// Expect a flow node.
+    YAML_PARSE_FLOW_NODE_STATE = 7,
+    /// Expect the first entry of a block sequence.
+    YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE = 8,
+    /// Expect an entry of a block sequence.
+    YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE = 9,
+    /// Expect an entry of an indentless sequence.
+    YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE = 10,
+    /// Expect the first key of a block mapping.
+    YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE = 11,
+    /// Expect a block mapping key.
+    YAML_PARSE_BLOCK_MAPPING_KEY_STATE = 12,
+    /// Expect a block mapping value.
+    YAML_PARSE_BLOCK_MAPPING_VALUE_STATE = 13,
+    /// Expect the first entry of a flow sequence.
+    YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE = 14,
+    /// Expect an entry of a flow sequence.
+    YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE = 15,
+    /// Expect a key of an ordered mapping.
+    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE = 16,
+    /// Expect a value of an ordered mapping.
+    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE = 17,
+    /// Expect the and of an ordered mapping entry.
+    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE = 18,
+    /// Expect the first key of a flow mapping.
+    YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE = 19,
+    /// Expect a key of a flow mapping.
+    YAML_PARSE_FLOW_MAPPING_KEY_STATE = 20,
+    /// Expect a value of a flow mapping.
+    YAML_PARSE_FLOW_MAPPING_VALUE_STATE = 21,
+    /// Expect an empty value of a flow mapping.
+    YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE = 22,
+    /// Expect nothing.
+    YAML_PARSE_END_STATE = 23,
+}
+
+/// This structure holds aliases data.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_alias_data_t {
+    /// The anchor.
+    pub anchor: *mut yaml_char_t,
+    /// The node id.
+    pub index: libc::c_int,
+    /// The anchor mark.
+    pub mark: yaml_mark_t,
+}
+
+/// The parser structure.
+///
+/// All members are internal. Manage the structure using the `yaml_parser_`
+/// family of functions.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_parser_t {
+    /// Error type.
+    #[cfg(doc)]
+    pub error: yaml_error_type_t,
+    #[cfg(not(doc))]
+    pub(crate) error: yaml_error_type_t,
+    /// Error description.
+    #[cfg(doc)]
+    pub problem: *const libc::c_char,
+    #[cfg(not(doc))]
+    pub(crate) problem: *const libc::c_char,
+    /// The byte about which the problem occured.
+    #[cfg(doc)]
+    pub problem_offset: size_t,
+    #[cfg(not(doc))]
+    pub(crate) problem_offset: size_t,
+    /// The problematic value (-1 is none).
+    #[cfg(doc)]
+    pub problem_value: libc::c_int,
+    #[cfg(not(doc))]
+    pub(crate) problem_value: libc::c_int,
+    /// The problem position.
+    #[cfg(doc)]
+    pub problem_mark: yaml_mark_t,
+    #[cfg(not(doc))]
+    pub(crate) problem_mark: yaml_mark_t,
+    /// The error context.
+    #[cfg(doc)]
+    pub context: *const libc::c_char,
+    #[cfg(not(doc))]
+    pub(crate) context: *const libc::c_char,
+    /// The context position.
+    #[cfg(doc)]
+    pub context_mark: yaml_mark_t,
+    #[cfg(not(doc))]
+    pub(crate) context_mark: yaml_mark_t,
+    /// Read handler.
+    pub(crate) read_handler: Option<yaml_read_handler_t>,
+    /// A pointer for passing to the read handler.
+    pub(crate) read_handler_data: *mut libc::c_void,
+    /// Standard (string or file) input data.
+    pub(crate) input: unnamed_yaml_parser_t_input,
+    /// EOF flag
+    pub(crate) eof: bool,
+    /// The working buffer.
+    pub(crate) buffer: yaml_buffer_t<yaml_char_t>,
+    /// The number of unread characters in the buffer.
+    pub(crate) unread: size_t,
+    /// The raw buffer.
+    pub(crate) raw_buffer: yaml_buffer_t<libc::c_uchar>,
+    /// The input encoding.
+    pub(crate) encoding: yaml_encoding_t,
+    /// The offset of the current position (in bytes).
+    pub(crate) offset: size_t,
+    /// The mark of the current position.
+    pub(crate) mark: yaml_mark_t,
+    /// Have we started to scan the input stream?
+    pub(crate) stream_start_produced: bool,
+    /// Have we reached the end of the input stream?
+    pub(crate) stream_end_produced: bool,
+    /// The number of unclosed '[' and '{' indicators.
+    pub(crate) flow_level: libc::c_int,
+    /// The tokens queue.
+    pub(crate) tokens: yaml_queue_t<yaml_token_t>,
+    /// The number of tokens fetched from the queue.
+    pub(crate) tokens_parsed: size_t,
+    /// Does the tokens queue contain a token ready for dequeueing.
+    pub(crate) token_available: bool,
+    /// The indentation levels stack.
+    pub(crate) indents: yaml_stack_t<libc::c_int>,
+    /// The current indentation level.
+    pub(crate) indent: libc::c_int,
+    /// May a simple key occur at the current position?
+    pub(crate) simple_key_allowed: bool,
+    /// The stack of simple keys.
+    pub(crate) simple_keys: yaml_stack_t<yaml_simple_key_t>,
+    /// The parser states stack.
+    pub(crate) states: yaml_stack_t<yaml_parser_state_t>,
+    /// The current parser state.
+    pub(crate) state: yaml_parser_state_t,
+    /// The stack of marks.
+    pub(crate) marks: yaml_stack_t<yaml_mark_t>,
+    /// The list of TAG directives.
+    pub(crate) tag_directives: yaml_stack_t<yaml_tag_directive_t>,
+    /// The alias data.
+    pub(crate) aliases: yaml_stack_t<yaml_alias_data_t>,
+    /// The currently parsed document.
+    pub(crate) document: *mut yaml_document_t,
+}
+
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_parser_t_prefix {
+    /// Error type.
+    pub error: yaml_error_type_t,
+    /// Error description.
+    pub problem: *const libc::c_char,
+    /// The byte about which the problem occured.
+    pub problem_offset: size_t,
+    /// The problematic value (-1 is none).
+    pub problem_value: libc::c_int,
+    /// The problem position.
+    pub problem_mark: yaml_mark_t,
+    /// The error context.
+    pub context: *const libc::c_char,
+    /// The context position.
+    pub context_mark: yaml_mark_t,
+}
+
+#[doc(hidden)]
+impl Deref for yaml_parser_t {
+    type Target = yaml_parser_t_prefix;
+    fn deref(&self) -> &Self::Target {
+        unsafe { &*addr_of!(*self).cast() }
+    }
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub(crate) union unnamed_yaml_parser_t_input {
+    /// String input data.
+    pub string: unnamed_yaml_parser_t_input_string,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub(crate) struct unnamed_yaml_parser_t_input_string {
+    /// The string start pointer.
+    pub start: *const libc::c_uchar,
+    /// The string end pointer.
+    pub end: *const libc::c_uchar,
+    /// The string current position.
+    pub current: *const libc::c_uchar,
+}
+
+/// The prototype of a write handler.
+///
+/// The write handler is called when the emitter needs to flush the accumulated
+/// characters to the output. The handler should write `size` bytes of the
+/// `buffer` to the output.
+///
+/// On success, the handler should return 1. If the handler failed, the returned
+/// value should be 0.
+pub type yaml_write_handler_t =
+    unsafe fn(data: *mut libc::c_void, buffer: *mut libc::c_uchar, size: size_t) -> libc::c_int;
+
+/// The emitter states.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum yaml_emitter_state_t {
+    /// Expect STREAM-START.
+    YAML_EMIT_STREAM_START_STATE = 0,
+    /// Expect the first DOCUMENT-START or STREAM-END.
+    YAML_EMIT_FIRST_DOCUMENT_START_STATE = 1,
+    /// Expect DOCUMENT-START or STREAM-END.
+    YAML_EMIT_DOCUMENT_START_STATE = 2,
+    /// Expect the content of a document.
+    YAML_EMIT_DOCUMENT_CONTENT_STATE = 3,
+    /// Expect DOCUMENT-END.
+    YAML_EMIT_DOCUMENT_END_STATE = 4,
+    /// Expect the first item of a flow sequence.
+    YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE = 5,
+    /// Expect an item of a flow sequence.
+    YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE = 6,
+    /// Expect the first key of a flow mapping.
+    YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE = 7,
+    /// Expect a key of a flow mapping.
+    YAML_EMIT_FLOW_MAPPING_KEY_STATE = 8,
+    /// Expect a value for a simple key of a flow mapping.
+    YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE = 9,
+    /// Expect a value of a flow mapping.
+    YAML_EMIT_FLOW_MAPPING_VALUE_STATE = 10,
+    /// Expect the first item of a block sequence.
+    YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE = 11,
+    /// Expect an item of a block sequence.
+    YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE = 12,
+    /// Expect the first key of a block mapping.
+    YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE = 13,
+    /// Expect the key of a block mapping.
+    YAML_EMIT_BLOCK_MAPPING_KEY_STATE = 14,
+    /// Expect a value for a simple key of a block mapping.
+    YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE = 15,
+    /// Expect a value of a block mapping.
+    YAML_EMIT_BLOCK_MAPPING_VALUE_STATE = 16,
+    /// Expect nothing.
+    YAML_EMIT_END_STATE = 17,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub(crate) struct yaml_anchors_t {
+    /// The number of references.
+    pub references: libc::c_int,
+    /// The anchor id.
+    pub anchor: libc::c_int,
+    /// If the node has been emitted?
+    pub serialized: bool,
+}
+
+/// The emitter structure.
+///
+/// All members are internal. Manage the structure using the `yaml_emitter_`
+/// family of functions.
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_emitter_t {
+    /// Error type.
+    #[cfg(doc)]
+    pub error: yaml_error_type_t,
+    #[cfg(not(doc))]
+    pub(crate) error: yaml_error_type_t,
+    /// Error description.
+    #[cfg(doc)]
+    pub problem: *const libc::c_char,
+    #[cfg(not(doc))]
+    pub(crate) problem: *const libc::c_char,
+    /// Write handler.
+    pub(crate) write_handler: Option<yaml_write_handler_t>,
+    /// A pointer for passing to the write handler.
+    pub(crate) write_handler_data: *mut libc::c_void,
+    /// Standard (string or file) output data.
+    pub(crate) output: unnamed_yaml_emitter_t_output,
+    /// The working buffer.
+    pub(crate) buffer: yaml_buffer_t<yaml_char_t>,
+    /// The raw buffer.
+    pub(crate) raw_buffer: yaml_buffer_t<libc::c_uchar>,
+    /// The stream encoding.
+    pub(crate) encoding: yaml_encoding_t,
+    /// If the output is in the canonical style?
+    pub(crate) canonical: bool,
+    /// The number of indentation spaces.
+    pub(crate) best_indent: libc::c_int,
+    /// The preferred width of the output lines.
+    pub(crate) best_width: libc::c_int,
+    /// Allow unescaped non-ASCII characters?
+    pub(crate) unicode: bool,
+    /// The preferred line break.
+    pub(crate) line_break: yaml_break_t,
+    /// The stack of states.
+    pub(crate) states: yaml_stack_t<yaml_emitter_state_t>,
+    /// The current emitter state.
+    pub(crate) state: yaml_emitter_state_t,
+    /// The event queue.
+    pub(crate) events: yaml_queue_t<yaml_event_t>,
+    /// The stack of indentation levels.
+    pub(crate) indents: yaml_stack_t<libc::c_int>,
+    /// The list of tag directives.
+    pub(crate) tag_directives: yaml_stack_t<yaml_tag_directive_t>,
+    /// The current indentation level.
+    pub(crate) indent: libc::c_int,
+    /// The current flow level.
+    pub(crate) flow_level: libc::c_int,
+    /// Is it the document root context?
+    pub(crate) root_context: bool,
+    /// Is it a sequence context?
+    pub(crate) sequence_context: bool,
+    /// Is it a mapping context?
+    pub(crate) mapping_context: bool,
+    /// Is it a simple mapping key context?
+    pub(crate) simple_key_context: bool,
+    /// The current line.
+    pub(crate) line: libc::c_int,
+    /// The current column.
+    pub(crate) column: libc::c_int,
+    /// If the last character was a whitespace?
+    pub(crate) whitespace: bool,
+    /// If the last character was an indentation character (' ', '-', '?', ':')?
+    pub(crate) indention: bool,
+    /// If an explicit document end is required?
+    pub(crate) open_ended: libc::c_int,
+    /// Anchor analysis.
+    pub(crate) anchor_data: unnamed_yaml_emitter_t_anchor_data,
+    /// Tag analysis.
+    pub(crate) tag_data: unnamed_yaml_emitter_t_tag_data,
+    /// Scalar analysis.
+    pub(crate) scalar_data: unnamed_yaml_emitter_t_scalar_data,
+    /// If the stream was already opened?
+    pub(crate) opened: bool,
+    /// If the stream was already closed?
+    pub(crate) closed: bool,
+    /// The information associated with the document nodes.
+    pub(crate) anchors: *mut yaml_anchors_t,
+    /// The last assigned anchor id.
+    pub(crate) last_anchor_id: libc::c_int,
+    /// The currently emitted document.
+    pub(crate) document: *mut yaml_document_t,
+}
+
+#[repr(C)]
+#[non_exhaustive]
+pub struct yaml_emitter_t_prefix {
+    /// Error type.
+    pub error: yaml_error_type_t,
+    /// Error description.
+    pub problem: *const libc::c_char,
+}
+
+#[doc(hidden)]
+impl Deref for yaml_emitter_t {
+    type Target = yaml_emitter_t_prefix;
+    fn deref(&self) -> &Self::Target {
+        unsafe { &*addr_of!(*self).cast() }
+    }
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub(crate) union unnamed_yaml_emitter_t_output {
+    /// String output data.
+    pub string: unnamed_yaml_emitter_t_output_string,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub(crate) struct unnamed_yaml_emitter_t_output_string {
+    /// The buffer pointer.
+    pub buffer: *mut libc::c_uchar,
+    /// The buffer size.
+    pub size: size_t,
+    /// The number of written bytes.
+    pub size_written: *mut size_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub(crate) struct unnamed_yaml_emitter_t_anchor_data {
+    /// The anchor value.
+    pub anchor: *mut yaml_char_t,
+    /// The anchor length.
+    pub anchor_length: size_t,
+    /// Is it an alias?
+    pub alias: bool,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub(crate) struct unnamed_yaml_emitter_t_tag_data {
+    /// The tag handle.
+    pub handle: *mut yaml_char_t,
+    /// The tag handle length.
+    pub handle_length: size_t,
+    /// The tag suffix.
+    pub suffix: *mut yaml_char_t,
+    /// The tag suffix length.
+    pub suffix_length: size_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub(crate) struct unnamed_yaml_emitter_t_scalar_data {
+    /// The scalar value.
+    pub value: *mut yaml_char_t,
+    /// The scalar length.
+    pub length: size_t,
+    /// Does the scalar contain line breaks?
+    pub multiline: bool,
+    /// Can the scalar be expessed in the flow plain style?
+    pub flow_plain_allowed: bool,
+    /// Can the scalar be expressed in the block plain style?
+    pub block_plain_allowed: bool,
+    /// Can the scalar be expressed in the single quoted style?
+    pub single_quoted_allowed: bool,
+    /// Can the scalar be expressed in the literal or folded styles?
+    pub block_allowed: bool,
+    /// The output style.
+    pub style: yaml_scalar_style_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub(crate) struct yaml_string_t {
+    pub start: *mut yaml_char_t,
+    pub end: *mut yaml_char_t,
+    pub pointer: *mut yaml_char_t,
+}
+
+pub(crate) const NULL_STRING: yaml_string_t = yaml_string_t {
+    start: ptr::null_mut::<yaml_char_t>(),
+    end: ptr::null_mut::<yaml_char_t>(),
+    pointer: ptr::null_mut::<yaml_char_t>(),
+};
+
+#[repr(C)]
+pub(crate) struct yaml_buffer_t<T> {
+    /// The beginning of the buffer.
+    pub start: *mut T,
+    /// The end of the buffer.
+    pub end: *mut T,
+    /// The current position of the buffer.
+    pub pointer: *mut T,
+    /// The last filled position of the buffer.
+    pub last: *mut T,
+}
+
+impl<T> Copy for yaml_buffer_t<T> {}
+impl<T> Clone for yaml_buffer_t<T> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+#[repr(C)]
+pub struct yaml_stack_t<T> {
+    /// The beginning of the stack.
+    pub start: *mut T,
+    /// The end of the stack.
+    pub end: *mut T,
+    /// The top of the stack.
+    pub top: *mut T,
+}
+
+impl<T> Copy for yaml_stack_t<T> {}
+impl<T> Clone for yaml_stack_t<T> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+#[repr(C)]
+pub(crate) struct yaml_queue_t<T> {
+    /// The beginning of the queue.
+    pub start: *mut T,
+    /// The end of the queue.
+    pub end: *mut T,
+    /// The head of the queue.
+    pub head: *mut T,
+    /// The tail of the queue.
+    pub tail: *mut T,
+}
+
+impl<T> Copy for yaml_queue_t<T> {}
+impl<T> Clone for yaml_queue_t<T> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
diff --git a/tests/bin/mod.rs b/tests/bin/mod.rs
new file mode 100644
index 0000000..0500980
--- /dev/null
+++ b/tests/bin/mod.rs
@@ -0,0 +1,48 @@
+use std::error::Error;
+use std::fs::File;
+use std::io::{Read, Write};
+use std::path::Path;
+use std::process::{Command, Stdio};
+
+pub struct Output {
+    pub success: bool,
+    pub stdout: Vec<u8>,
+    pub stderr: Vec<u8>,
+}
+
+pub fn run(
+    compiled: &str,
+    unsafe_main: unsafe fn(
+        stdin: &mut dyn Read,
+        stdout: &mut dyn Write,
+    ) -> Result<(), Box<dyn Error>>,
+    input: &Path,
+) -> Output {
+    if cfg!(miri) {
+        let mut input = File::open(input).unwrap();
+        let mut stdout = Vec::new();
+        let result = unsafe { unsafe_main(&mut input, &mut stdout) };
+
+        Output {
+            success: result.is_ok(),
+            stdout,
+            stderr: result
+                .err()
+                .as_ref()
+                .map_or_else(String::new, ToString::to_string)
+                .into(),
+        }
+    } else {
+        let output = Command::new(compiled)
+            .arg(input)
+            .stdin(Stdio::null())
+            .output()
+            .unwrap();
+
+        Output {
+            success: output.status.success(),
+            stdout: output.stdout,
+            stderr: output.stderr,
+        }
+    }
+}
diff --git a/tests/ignorelist/libyaml-emitter b/tests/ignorelist/libyaml-emitter
new file mode 100644
index 0000000..b52000f
--- /dev/null
+++ b/tests/ignorelist/libyaml-emitter
@@ -0,0 +1,72 @@
+26DV: Whitespace around colon in mappings
+2EBW: Allowed characters in keys
+2JQS: Block Mapping with Missing Keys
+2LFX: Spec Example 6.13. Reserved Directives [1.3]
+2SXE: Anchors With Colon in Name
+2XXW: Spec Example 2.25. Unordered Sets
+3MYT: Plain Scalar looking like key, comment, anchor and tag
+4ABK: Spec Example 7.17. Flow Mapping Separate Values
+4MUZ: Flow mapping colon on line after key
+4QFQ: Spec Example 8.2. Block Indentation Indicator [1.3]
+52DL: Explicit Non-Specific Tag [1.3]
+565N: Construct Binary
+5TYM: Spec Example 6.21. Local Tag Prefix
+5WE3: Spec Example 8.17. Explicit Block Mapping Entries
+6CK3: Spec Example 6.26. Tag Shorthands
+6FWR: Block Scalar Keep
+6KGN: Anchor for empty node
+6M2F: Aliases in Explicit Block Mapping
+6PBE: Zero-indented sequences in explicit mapping keys
+6SLA: Allowed characters in quoted mapping key
+6WLZ: Spec Example 6.18. Primary Tag Handle [1.3]
+6WPF: Spec Example 6.8. Flow Folding [1.3]
+6XDY: Two document start markers
+6ZKB: Spec Example 9.6. Stream
+7T8X: Spec Example 8.10. Folded Lines - 8.13. Final Empty Lines
+7W2P: Block Mapping with Missing Values
+7Z25: Bare document after document end marker
+8KB6: Multiline plain flow mapping key without value
+8XYN: Anchor with unicode character
+9BXH: Multiline doublequoted flow mapping key without value
+8MK2: Explicit Non-Specific Tag
+9DXL: Spec Example 9.6. Stream [1.3]
+9MMW: Spec Example 7.21. Single Pair Implicit Entries [1.3
+9TFX: Spec Example 7.6. Double Quoted Lines [1.3]
+B3HG: Spec Example 8.9. Folded Scalar [1.3]
+C2DT: Spec Example 7.18. Flow Mapping Adjacent Values
+DFF7: Spec Example 7.16. Flow Mapping Entries
+E76Z: Aliases in Implicit Block Mapping
+EX5H: Multiline Scalar at Top Level [1.3]
+EXG3: Three dashes and content without space [1.3]
+FBC9: Allowed characters in plain scalars
+FH7J: Tags on Empty Scalars
+FRK4: Spec Example 7.3. Completely Empty Flow Nodes
+J3BT: Spec Example 5.12. Tabs and Spaces
+JDH8: Plain Scalar looking like key, comment, anchor and tag [1.3]
+JTV5: Block Mapping with Multiline Scalars
+K54U: Tab after document header
+KK5P: Various combinations of explicit block mappings
+KSS4: Scalars on --- line
+KZN9: Spec Example 7.21. Single Pair Implicit Entries
+LE5A: Spec Example 7.24. Flow Nodes
+M7A3: Spec Example 9.3. Bare Documents
+M9B4: Spec Example 8.7. Literal Scalar
+NAT4: Various empty or newline only quoted strings
+NHX8: Empty Lines at End of Document
+PUW8: Document start on last line
+PW8X: Anchors on Empty Scalars
+Q8AD: Spec Example 7.5. Double Quoted Line Breaks [1.3]
+S3PD: Spec Example 8.18. Implicit Block Mapping Entries
+S4JQ: Spec Example 6.28. Non-Specific Tags
+T26H: Spec Example 8.8. Literal Content [1.3]
+T4YY: Spec Example 7.9. Single Quoted Lines [1.3]
+T5N4: Spec Example 8.7. Literal Scalar [1.3]
+UT92: Spec Example 9.4. Explicit Documents
+W42U: Spec Example 8.15. Block Sequence Entry Types
+W4TN: Spec Example 9.5. Directives Documents
+W5VH: Allowed characters in alias
+WZ62: Spec Example 7.2. Empty Content
+X38W: Aliases in Flow Objects
+XLQ9: Multiline scalar that looks like a YAML directive
+Y2GN: Anchor with colon in the middle
+ZWK4: Key with anchor after missing explicit mapping value
diff --git a/tests/ignorelist/libyaml-parser b/tests/ignorelist/libyaml-parser
new file mode 100644
index 0000000..94029f6
--- /dev/null
+++ b/tests/ignorelist/libyaml-parser
@@ -0,0 +1,34 @@
+2JQS: Block Mapping with Missing Keys
+2LFX: Spec Example 6.13. Reserved Directives [1.3]
+2SXE: Anchors With Colon in Name
+4ABK: Spec Example 7.17. Flow Mapping Separate Values
+4MUZ: Flow mapping colon on line after key
+5MUD: Colon and adjacent value on next line
+6BCT: Spec Example 6.3. Separation Spaces
+6LVF: Spec Example 6.13. Reserved Directives
+6M2F: Aliases in Explicit Block Mapping
+7Z25: Bare document after document end marker
+8XYN: Anchor with unicode character
+9MMW: Spec Example 7.21. Single Pair Implicit Entries [1.3
+9SA2: Multiline double quoted flow mapping key
+A2M4: Spec Example 6.2. Indentation Indicators
+BEC7: Spec Example 6.14. “YAML” directive
+DBG4: Spec Example 7.10. Plain Characters
+DK3J: Zero indented block scalar with line that looks like a comment
+FP8R: Zero indented block scalar
+FRK4: Spec Example 7.3. Completely Empty Flow Nodes
+HWV9: Document-end marker
+K3WX: Colon and adjacent value after comment on next line
+KZN9: Spec Example 7.21. Single Pair Implicit Entries
+M7A3: Spec Example 9.3. Bare Documents
+NHX8: Empty Lines at End of Document
+NJ66: Multiline plain flow mapping key
+Q5MG: Tab at beginning of line followed by a flow mapping
+QT73: Comment and document-end marker
+R4YG: Spec Example 8.2. Block Indentation Indicator
+S3PD: Spec Example 8.18. Implicit Block Mapping Entries
+UT92: Spec Example 9.4. Explicit Documents
+W4TN: Spec Example 9.5. Directives Documents
+W5VH: Allowed characters in alias
+WZ62: Spec Example 7.2. Empty Content
+Y2GN: Anchor with colon in the middle
diff --git a/tests/ignorelist/libyaml-parser-error b/tests/ignorelist/libyaml-parser-error
new file mode 100644
index 0000000..aa83f1a
--- /dev/null
+++ b/tests/ignorelist/libyaml-parser-error
@@ -0,0 +1,10 @@
+9C9N: Wrong indented flow sequence
+9HCY: Need document footer before directives
+9JBA: Invalid comment after end of flow sequence
+CVW2: Invalid comment after comma
+EB22: Missing document-end marker before directive
+QB6E: Wrong indented multiline quoted scalar
+RHX7: YAML directive without document end marker
+S98Z: Block scalar with more spaces than first content line
+SU5Z: Comment without whitespace after doublequoted scalar
+X4QW: Comment without whitespace after block scalar indicator
diff --git a/tests/test_emitter.rs b/tests/test_emitter.rs
new file mode 100644
index 0000000..852be2c
--- /dev/null
+++ b/tests/test_emitter.rs
@@ -0,0 +1,37 @@
+#![allow(clippy::type_complexity)]
+
+mod bin;
+#[path = "../src/bin/run-emitter-test-suite.rs"]
+#[allow(dead_code)]
+mod run_emitter_test_suite;
+
+use std::fs;
+use std::path::Path;
+
+fn test(id: &str) {
+    let dir = Path::new("tests")
+        .join("data")
+        .join("yaml-test-suite")
+        .join(id);
+
+    let output = bin::run(
+        env!("CARGO_BIN_EXE_run-emitter-test-suite"),
+        run_emitter_test_suite::unsafe_main,
+        &dir.join("test.event"),
+    );
+
+    let stdout = String::from_utf8_lossy(&output.stdout);
+    let stderr = String::from_utf8_lossy(&output.stderr);
+    eprint!("{}", stderr);
+
+    let out = if dir.join("out.yaml").exists() {
+        dir.join("out.yaml")
+    } else {
+        dir.join("in.yaml")
+    };
+    let expected = fs::read_to_string(out).unwrap();
+    pretty_assertions::assert_str_eq!(expected, stdout);
+    assert!(output.success);
+}
+
+unsafe_libyaml_test_suite::test_emitter!();
diff --git a/tests/test_parser.rs b/tests/test_parser.rs
new file mode 100644
index 0000000..190db26
--- /dev/null
+++ b/tests/test_parser.rs
@@ -0,0 +1,32 @@
+#![allow(clippy::type_complexity)]
+
+mod bin;
+#[path = "../src/bin/run-parser-test-suite.rs"]
+#[allow(dead_code)]
+mod run_parser_test_suite;
+
+use std::fs;
+use std::path::Path;
+
+fn test(id: &str) {
+    let dir = Path::new("tests")
+        .join("data")
+        .join("yaml-test-suite")
+        .join(id);
+
+    let output = bin::run(
+        env!("CARGO_BIN_EXE_run-parser-test-suite"),
+        run_parser_test_suite::unsafe_main,
+        &dir.join("in.yaml"),
+    );
+
+    let stdout = String::from_utf8_lossy(&output.stdout);
+    let stderr = String::from_utf8_lossy(&output.stderr);
+    eprint!("{}", stderr);
+
+    let expected = fs::read_to_string(dir.join("test.event")).unwrap();
+    pretty_assertions::assert_str_eq!(expected, stdout);
+    assert!(output.success);
+}
+
+unsafe_libyaml_test_suite::test_parser!();
diff --git a/tests/test_parser_error.rs b/tests/test_parser_error.rs
new file mode 100644
index 0000000..9473de8
--- /dev/null
+++ b/tests/test_parser_error.rs
@@ -0,0 +1,31 @@
+#![allow(clippy::type_complexity)]
+
+mod bin;
+#[path = "../src/bin/run-parser-test-suite.rs"]
+#[allow(dead_code)]
+mod run_parser_test_suite;
+
+use std::path::Path;
+
+fn test(id: &str) {
+    let dir = Path::new("tests")
+        .join("data")
+        .join("yaml-test-suite")
+        .join(id);
+
+    let output = bin::run(
+        env!("CARGO_BIN_EXE_run-parser-test-suite"),
+        run_parser_test_suite::unsafe_main,
+        &dir.join("in.yaml"),
+    );
+
+    if output.success {
+        let stdout = String::from_utf8_lossy(&output.stdout);
+        let stderr = String::from_utf8_lossy(&output.stderr);
+        eprint!("{}", stdout);
+        eprint!("{}", stderr);
+        panic!("expected parse to fail");
+    }
+}
+
+unsafe_libyaml_test_suite::test_parser_error!();