unsafe_libyaml/
loader.rs

1use crate::api::{yaml_free, yaml_malloc, yaml_stack_extend, yaml_strdup};
2use crate::externs::{memset, strcmp};
3use crate::success::{Success, FAIL, OK};
4use crate::yaml::yaml_char_t;
5use crate::{
6    libc, yaml_alias_data_t, yaml_document_delete, yaml_document_t, yaml_event_t, yaml_mark_t,
7    yaml_node_item_t, yaml_node_pair_t, yaml_node_t, yaml_parser_parse, yaml_parser_t, PointerExt,
8    YAML_ALIAS_EVENT, YAML_COMPOSER_ERROR, YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_START_EVENT,
9    YAML_MAPPING_END_EVENT, YAML_MAPPING_NODE, YAML_MAPPING_START_EVENT, YAML_MEMORY_ERROR,
10    YAML_SCALAR_EVENT, YAML_SCALAR_NODE, YAML_SEQUENCE_END_EVENT, YAML_SEQUENCE_NODE,
11    YAML_SEQUENCE_START_EVENT, YAML_STREAM_END_EVENT, YAML_STREAM_START_EVENT,
12};
13use core::mem::{size_of, MaybeUninit};
14use core::ptr::{self, addr_of_mut};
15
16#[repr(C)]
17struct loader_ctx {
18    start: *mut libc::c_int,
19    end: *mut libc::c_int,
20    top: *mut libc::c_int,
21}
22
23/// Parse the input stream and produce the next YAML document.
24///
25/// Call this function subsequently to produce a sequence of documents
26/// constituting the input stream.
27///
28/// If the produced document has no root node, it means that the document end
29/// has been reached.
30///
31/// An application is responsible for freeing any data associated with the
32/// produced document object using the yaml_document_delete() function.
33///
34/// An application must not alternate the calls of yaml_parser_load() with the
35/// calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break
36/// the parser.
37pub unsafe fn yaml_parser_load(
38    parser: *mut yaml_parser_t,
39    document: *mut yaml_document_t,
40) -> Success {
41    let current_block: u64;
42    let mut event = MaybeUninit::<yaml_event_t>::uninit();
43    let event = event.as_mut_ptr();
44    __assert!(!parser.is_null());
45    __assert!(!document.is_null());
46    memset(
47        document as *mut libc::c_void,
48        0,
49        size_of::<yaml_document_t>() as libc::c_ulong,
50    );
51    STACK_INIT!((*document).nodes, yaml_node_t);
52    if !(*parser).stream_start_produced {
53        if yaml_parser_parse(parser, event).fail {
54            current_block = 6234624449317607669;
55        } else {
56            __assert!((*event).type_ == YAML_STREAM_START_EVENT);
57            current_block = 7815301370352969686;
58        }
59    } else {
60        current_block = 7815301370352969686;
61    }
62    if current_block != 6234624449317607669 {
63        if (*parser).stream_end_produced {
64            return OK;
65        }
66        if yaml_parser_parse(parser, event).ok {
67            if (*event).type_ == YAML_STREAM_END_EVENT {
68                return OK;
69            }
70            STACK_INIT!((*parser).aliases, yaml_alias_data_t);
71            let fresh6 = addr_of_mut!((*parser).document);
72            *fresh6 = document;
73            if yaml_parser_load_document(parser, event).ok {
74                yaml_parser_delete_aliases(parser);
75                let fresh7 = addr_of_mut!((*parser).document);
76                *fresh7 = ptr::null_mut::<yaml_document_t>();
77                return OK;
78            }
79        }
80    }
81    yaml_parser_delete_aliases(parser);
82    yaml_document_delete(document);
83    let fresh8 = addr_of_mut!((*parser).document);
84    *fresh8 = ptr::null_mut::<yaml_document_t>();
85    FAIL
86}
87
88unsafe fn yaml_parser_set_composer_error(
89    parser: *mut yaml_parser_t,
90    problem: *const libc::c_char,
91    problem_mark: yaml_mark_t,
92) -> Success {
93    (*parser).error = YAML_COMPOSER_ERROR;
94    let fresh9 = addr_of_mut!((*parser).problem);
95    *fresh9 = problem;
96    (*parser).problem_mark = problem_mark;
97    FAIL
98}
99
100unsafe fn yaml_parser_set_composer_error_context(
101    parser: *mut yaml_parser_t,
102    context: *const libc::c_char,
103    context_mark: yaml_mark_t,
104    problem: *const libc::c_char,
105    problem_mark: yaml_mark_t,
106) -> Success {
107    (*parser).error = YAML_COMPOSER_ERROR;
108    let fresh10 = addr_of_mut!((*parser).context);
109    *fresh10 = context;
110    (*parser).context_mark = context_mark;
111    let fresh11 = addr_of_mut!((*parser).problem);
112    *fresh11 = problem;
113    (*parser).problem_mark = problem_mark;
114    FAIL
115}
116
117unsafe fn yaml_parser_delete_aliases(parser: *mut yaml_parser_t) {
118    while !STACK_EMPTY!((*parser).aliases) {
119        yaml_free(POP!((*parser).aliases).anchor as *mut libc::c_void);
120    }
121    STACK_DEL!((*parser).aliases);
122}
123
124unsafe fn yaml_parser_load_document(
125    parser: *mut yaml_parser_t,
126    event: *mut yaml_event_t,
127) -> Success {
128    let mut ctx = loader_ctx {
129        start: ptr::null_mut::<libc::c_int>(),
130        end: ptr::null_mut::<libc::c_int>(),
131        top: ptr::null_mut::<libc::c_int>(),
132    };
133    __assert!((*event).type_ == YAML_DOCUMENT_START_EVENT);
134    let fresh16 = addr_of_mut!((*(*parser).document).version_directive);
135    *fresh16 = (*event).data.document_start.version_directive;
136    let fresh17 = addr_of_mut!((*(*parser).document).tag_directives.start);
137    *fresh17 = (*event).data.document_start.tag_directives.start;
138    let fresh18 = addr_of_mut!((*(*parser).document).tag_directives.end);
139    *fresh18 = (*event).data.document_start.tag_directives.end;
140    (*(*parser).document).start_implicit = (*event).data.document_start.implicit;
141    (*(*parser).document).start_mark = (*event).start_mark;
142    STACK_INIT!(ctx, libc::c_int);
143    if yaml_parser_load_nodes(parser, addr_of_mut!(ctx)).fail {
144        STACK_DEL!(ctx);
145        return FAIL;
146    }
147    STACK_DEL!(ctx);
148    OK
149}
150
151unsafe fn yaml_parser_load_nodes(parser: *mut yaml_parser_t, ctx: *mut loader_ctx) -> Success {
152    let mut event = MaybeUninit::<yaml_event_t>::uninit();
153    let event = event.as_mut_ptr();
154    loop {
155        if yaml_parser_parse(parser, event).fail {
156            return FAIL;
157        }
158        match (*event).type_ {
159            YAML_ALIAS_EVENT => {
160                if yaml_parser_load_alias(parser, event, ctx).fail {
161                    return FAIL;
162                }
163            }
164            YAML_SCALAR_EVENT => {
165                if yaml_parser_load_scalar(parser, event, ctx).fail {
166                    return FAIL;
167                }
168            }
169            YAML_SEQUENCE_START_EVENT => {
170                if yaml_parser_load_sequence(parser, event, ctx).fail {
171                    return FAIL;
172                }
173            }
174            YAML_SEQUENCE_END_EVENT => {
175                if yaml_parser_load_sequence_end(parser, event, ctx).fail {
176                    return FAIL;
177                }
178            }
179            YAML_MAPPING_START_EVENT => {
180                if yaml_parser_load_mapping(parser, event, ctx).fail {
181                    return FAIL;
182                }
183            }
184            YAML_MAPPING_END_EVENT => {
185                if yaml_parser_load_mapping_end(parser, event, ctx).fail {
186                    return FAIL;
187                }
188            }
189            YAML_DOCUMENT_END_EVENT => {}
190            _ => {
191                __assert!(false);
192            }
193        }
194        if (*event).type_ == YAML_DOCUMENT_END_EVENT {
195            break;
196        }
197    }
198    (*(*parser).document).end_implicit = (*event).data.document_end.implicit;
199    (*(*parser).document).end_mark = (*event).end_mark;
200    OK
201}
202
203unsafe fn yaml_parser_register_anchor(
204    parser: *mut yaml_parser_t,
205    index: libc::c_int,
206    anchor: *mut yaml_char_t,
207) -> Success {
208    let mut data = MaybeUninit::<yaml_alias_data_t>::uninit();
209    let data = data.as_mut_ptr();
210    let mut alias_data: *mut yaml_alias_data_t;
211    if anchor.is_null() {
212        return OK;
213    }
214    (*data).anchor = anchor;
215    (*data).index = index;
216    (*data).mark = (*(*(*parser).document)
217        .nodes
218        .start
219        .wrapping_offset((index - 1) as isize))
220    .start_mark;
221    alias_data = (*parser).aliases.start;
222    while alias_data != (*parser).aliases.top {
223        if strcmp(
224            (*alias_data).anchor as *mut libc::c_char,
225            anchor as *mut libc::c_char,
226        ) == 0
227        {
228            yaml_free(anchor as *mut libc::c_void);
229            return yaml_parser_set_composer_error_context(
230                parser,
231                b"found duplicate anchor; first occurrence\0" as *const u8 as *const libc::c_char,
232                (*alias_data).mark,
233                b"second occurrence\0" as *const u8 as *const libc::c_char,
234                (*data).mark,
235            );
236        }
237        alias_data = alias_data.wrapping_offset(1);
238    }
239    PUSH!((*parser).aliases, *data);
240    OK
241}
242
243unsafe fn yaml_parser_load_node_add(
244    parser: *mut yaml_parser_t,
245    ctx: *mut loader_ctx,
246    index: libc::c_int,
247) -> Success {
248    if STACK_EMPTY!(*ctx) {
249        return OK;
250    }
251    let parent_index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
252    let parent: *mut yaml_node_t = addr_of_mut!(
253        *((*(*parser).document).nodes.start).wrapping_offset((parent_index - 1) as isize)
254    );
255    let current_block_17: u64;
256    match (*parent).type_ {
257        YAML_SEQUENCE_NODE => {
258            if STACK_LIMIT!(parser, (*parent).data.sequence.items).fail {
259                return FAIL;
260            }
261            PUSH!((*parent).data.sequence.items, index);
262        }
263        YAML_MAPPING_NODE => {
264            let mut pair = MaybeUninit::<yaml_node_pair_t>::uninit();
265            let pair = pair.as_mut_ptr();
266            if !STACK_EMPTY!((*parent).data.mapping.pairs) {
267                let p: *mut yaml_node_pair_t =
268                    (*parent).data.mapping.pairs.top.wrapping_offset(-1_isize);
269                if (*p).key != 0 && (*p).value == 0 {
270                    (*p).value = index;
271                    current_block_17 = 11307063007268554308;
272                } else {
273                    current_block_17 = 17407779659766490442;
274                }
275            } else {
276                current_block_17 = 17407779659766490442;
277            }
278            match current_block_17 {
279                11307063007268554308 => {}
280                _ => {
281                    (*pair).key = index;
282                    (*pair).value = 0;
283                    if STACK_LIMIT!(parser, (*parent).data.mapping.pairs).fail {
284                        return FAIL;
285                    }
286                    PUSH!((*parent).data.mapping.pairs, *pair);
287                }
288            }
289        }
290        _ => {
291            __assert!(false);
292        }
293    }
294    OK
295}
296
297unsafe fn yaml_parser_load_alias(
298    parser: *mut yaml_parser_t,
299    event: *mut yaml_event_t,
300    ctx: *mut loader_ctx,
301) -> Success {
302    let anchor: *mut yaml_char_t = (*event).data.alias.anchor;
303    let mut alias_data: *mut yaml_alias_data_t;
304    alias_data = (*parser).aliases.start;
305    while alias_data != (*parser).aliases.top {
306        if strcmp(
307            (*alias_data).anchor as *mut libc::c_char,
308            anchor as *mut libc::c_char,
309        ) == 0
310        {
311            yaml_free(anchor as *mut libc::c_void);
312            return yaml_parser_load_node_add(parser, ctx, (*alias_data).index);
313        }
314        alias_data = alias_data.wrapping_offset(1);
315    }
316    yaml_free(anchor as *mut libc::c_void);
317    yaml_parser_set_composer_error(
318        parser,
319        b"found undefined alias\0" as *const u8 as *const libc::c_char,
320        (*event).start_mark,
321    )
322}
323
324unsafe fn yaml_parser_load_scalar(
325    parser: *mut yaml_parser_t,
326    event: *mut yaml_event_t,
327    ctx: *mut loader_ctx,
328) -> Success {
329    let current_block: u64;
330    let mut node = MaybeUninit::<yaml_node_t>::uninit();
331    let node = node.as_mut_ptr();
332    let index: libc::c_int;
333    let mut tag: *mut yaml_char_t = (*event).data.scalar.tag;
334    if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
335        if tag.is_null()
336            || strcmp(
337                tag as *mut libc::c_char,
338                b"!\0" as *const u8 as *const libc::c_char,
339            ) == 0
340        {
341            yaml_free(tag as *mut libc::c_void);
342            tag = yaml_strdup(
343                b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
344            );
345            if tag.is_null() {
346                current_block = 10579931339944277179;
347            } else {
348                current_block = 11006700562992250127;
349            }
350        } else {
351            current_block = 11006700562992250127;
352        }
353        if current_block != 10579931339944277179 {
354            memset(
355                node as *mut libc::c_void,
356                0,
357                size_of::<yaml_node_t>() as libc::c_ulong,
358            );
359            (*node).type_ = YAML_SCALAR_NODE;
360            (*node).tag = tag;
361            (*node).start_mark = (*event).start_mark;
362            (*node).end_mark = (*event).end_mark;
363            (*node).data.scalar.value = (*event).data.scalar.value;
364            (*node).data.scalar.length = (*event).data.scalar.length;
365            (*node).data.scalar.style = (*event).data.scalar.style;
366            PUSH!((*(*parser).document).nodes, *node);
367            index = (*(*parser).document)
368                .nodes
369                .top
370                .c_offset_from((*(*parser).document).nodes.start)
371                as libc::c_int;
372            if yaml_parser_register_anchor(parser, index, (*event).data.scalar.anchor).fail {
373                return FAIL;
374            }
375            return yaml_parser_load_node_add(parser, ctx, index);
376        }
377    }
378    yaml_free(tag as *mut libc::c_void);
379    yaml_free((*event).data.scalar.anchor as *mut libc::c_void);
380    yaml_free((*event).data.scalar.value as *mut libc::c_void);
381    FAIL
382}
383
384unsafe fn yaml_parser_load_sequence(
385    parser: *mut yaml_parser_t,
386    event: *mut yaml_event_t,
387    ctx: *mut loader_ctx,
388) -> Success {
389    let current_block: u64;
390    let mut node = MaybeUninit::<yaml_node_t>::uninit();
391    let node = node.as_mut_ptr();
392    struct Items {
393        start: *mut yaml_node_item_t,
394        end: *mut yaml_node_item_t,
395        top: *mut yaml_node_item_t,
396    }
397    let mut items = Items {
398        start: ptr::null_mut::<yaml_node_item_t>(),
399        end: ptr::null_mut::<yaml_node_item_t>(),
400        top: ptr::null_mut::<yaml_node_item_t>(),
401    };
402    let index: libc::c_int;
403    let mut tag: *mut yaml_char_t = (*event).data.sequence_start.tag;
404    if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
405        if tag.is_null()
406            || strcmp(
407                tag as *mut libc::c_char,
408                b"!\0" as *const u8 as *const libc::c_char,
409            ) == 0
410        {
411            yaml_free(tag as *mut libc::c_void);
412            tag = yaml_strdup(
413                b"tag:yaml.org,2002:seq\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
414            );
415            if tag.is_null() {
416                current_block = 13474536459355229096;
417            } else {
418                current_block = 6937071982253665452;
419            }
420        } else {
421            current_block = 6937071982253665452;
422        }
423        if current_block != 13474536459355229096 {
424            STACK_INIT!(items, yaml_node_item_t);
425            memset(
426                node as *mut libc::c_void,
427                0,
428                size_of::<yaml_node_t>() as libc::c_ulong,
429            );
430            (*node).type_ = YAML_SEQUENCE_NODE;
431            (*node).tag = tag;
432            (*node).start_mark = (*event).start_mark;
433            (*node).end_mark = (*event).end_mark;
434            (*node).data.sequence.items.start = items.start;
435            (*node).data.sequence.items.end = items.end;
436            (*node).data.sequence.items.top = items.start;
437            (*node).data.sequence.style = (*event).data.sequence_start.style;
438            PUSH!((*(*parser).document).nodes, *node);
439            index = (*(*parser).document)
440                .nodes
441                .top
442                .c_offset_from((*(*parser).document).nodes.start)
443                as libc::c_int;
444            if yaml_parser_register_anchor(parser, index, (*event).data.sequence_start.anchor).fail
445            {
446                return FAIL;
447            }
448            if yaml_parser_load_node_add(parser, ctx, index).fail {
449                return FAIL;
450            }
451            if STACK_LIMIT!(parser, *ctx).fail {
452                return FAIL;
453            }
454            PUSH!(*ctx, index);
455            return OK;
456        }
457    }
458    yaml_free(tag as *mut libc::c_void);
459    yaml_free((*event).data.sequence_start.anchor as *mut libc::c_void);
460    FAIL
461}
462
463unsafe fn yaml_parser_load_sequence_end(
464    parser: *mut yaml_parser_t,
465    event: *mut yaml_event_t,
466    ctx: *mut loader_ctx,
467) -> Success {
468    __assert!(((*ctx).top).c_offset_from((*ctx).start) as libc::c_long > 0_i64);
469    let index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
470    __assert!(
471        (*((*(*parser).document).nodes.start).wrapping_offset((index - 1) as isize)).type_
472            == YAML_SEQUENCE_NODE
473    );
474    (*(*(*parser).document)
475        .nodes
476        .start
477        .wrapping_offset((index - 1) as isize))
478    .end_mark = (*event).end_mark;
479    let _ = POP!(*ctx);
480    OK
481}
482
483unsafe fn yaml_parser_load_mapping(
484    parser: *mut yaml_parser_t,
485    event: *mut yaml_event_t,
486    ctx: *mut loader_ctx,
487) -> Success {
488    let current_block: u64;
489    let mut node = MaybeUninit::<yaml_node_t>::uninit();
490    let node = node.as_mut_ptr();
491    struct Pairs {
492        start: *mut yaml_node_pair_t,
493        end: *mut yaml_node_pair_t,
494        top: *mut yaml_node_pair_t,
495    }
496    let mut pairs = Pairs {
497        start: ptr::null_mut::<yaml_node_pair_t>(),
498        end: ptr::null_mut::<yaml_node_pair_t>(),
499        top: ptr::null_mut::<yaml_node_pair_t>(),
500    };
501    let index: libc::c_int;
502    let mut tag: *mut yaml_char_t = (*event).data.mapping_start.tag;
503    if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
504        if tag.is_null()
505            || strcmp(
506                tag as *mut libc::c_char,
507                b"!\0" as *const u8 as *const libc::c_char,
508            ) == 0
509        {
510            yaml_free(tag as *mut libc::c_void);
511            tag = yaml_strdup(
512                b"tag:yaml.org,2002:map\0" as *const u8 as *const libc::c_char as *mut yaml_char_t,
513            );
514            if tag.is_null() {
515                current_block = 13635467803606088781;
516            } else {
517                current_block = 6937071982253665452;
518            }
519        } else {
520            current_block = 6937071982253665452;
521        }
522        if current_block != 13635467803606088781 {
523            STACK_INIT!(pairs, yaml_node_pair_t);
524            memset(
525                node as *mut libc::c_void,
526                0,
527                size_of::<yaml_node_t>() as libc::c_ulong,
528            );
529            (*node).type_ = YAML_MAPPING_NODE;
530            (*node).tag = tag;
531            (*node).start_mark = (*event).start_mark;
532            (*node).end_mark = (*event).end_mark;
533            (*node).data.mapping.pairs.start = pairs.start;
534            (*node).data.mapping.pairs.end = pairs.end;
535            (*node).data.mapping.pairs.top = pairs.start;
536            (*node).data.mapping.style = (*event).data.mapping_start.style;
537            PUSH!((*(*parser).document).nodes, *node);
538            index = (*(*parser).document)
539                .nodes
540                .top
541                .c_offset_from((*(*parser).document).nodes.start)
542                as libc::c_int;
543            if yaml_parser_register_anchor(parser, index, (*event).data.mapping_start.anchor).fail {
544                return FAIL;
545            }
546            if yaml_parser_load_node_add(parser, ctx, index).fail {
547                return FAIL;
548            }
549            if STACK_LIMIT!(parser, *ctx).fail {
550                return FAIL;
551            }
552            PUSH!(*ctx, index);
553            return OK;
554        }
555    }
556    yaml_free(tag as *mut libc::c_void);
557    yaml_free((*event).data.mapping_start.anchor as *mut libc::c_void);
558    FAIL
559}
560
561unsafe fn yaml_parser_load_mapping_end(
562    parser: *mut yaml_parser_t,
563    event: *mut yaml_event_t,
564    ctx: *mut loader_ctx,
565) -> Success {
566    __assert!(((*ctx).top).c_offset_from((*ctx).start) as libc::c_long > 0_i64);
567    let index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
568    __assert!(
569        (*((*(*parser).document).nodes.start).wrapping_offset((index - 1) as isize)).type_
570            == YAML_MAPPING_NODE
571    );
572    (*(*(*parser).document)
573        .nodes
574        .start
575        .wrapping_offset((index - 1) as isize))
576    .end_mark = (*event).end_mark;
577    let _ = POP!(*ctx);
578    OK
579}