diff options
author | Jeongik Cha <jeongik@google.com> | 2023-09-27 08:11:50 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-09-27 08:11:50 +0000 |
commit | a4fab8ba166d8c7e43abac77bea137ed3e935447 (patch) | |
tree | 4751d9b15c4bf6bc6b012e7fffb8773b1e9d4697 | |
parent | e6ff902e349bd38b7c8775e23f41f2780527eb08 (diff) | |
parent | d13ba9dfc1437a1824840d743abe1a2e1b513bc7 (diff) | |
download | unsafe-libyaml-a4fab8ba166d8c7e43abac77bea137ed3e935447.tar.gz |
Import unsafe-libyaml am: d13ba9dfc1
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/unsafe-libyaml/+/2754408
Change-Id: Ic2d3045c179624a657dabcb5394947f252d2e5cb
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
35 files changed, 12833 insertions, 0 deletions
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"] @@ -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 @@ -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) [![crates-io]](https://crates.io/crates/unsafe-libyaml) [![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!(); |