source: libyaml/trunk/src/parser.c @ 274

Revision 274, 43.4 KB checked in by xi, 6 years ago (diff)

Merged grammar fixes from the stable branch.

Line 
1
2/*
3 * The parser implements the following grammar:
4 *
5 * stream               ::= STREAM-START implicit_document? explicit_document* STREAM-END
6 * implicit_document    ::= block_node DOCUMENT-END*
7 * explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
8 * block_node_or_indentless_sequence    ::=
9 *                          ALIAS
10 *                          | properties (block_content | indentless_block_sequence)?
11 *                          | block_content
12 *                          | indentless_block_sequence
13 * block_node           ::= ALIAS
14 *                          | properties block_content?
15 *                          | block_content
16 * flow_node            ::= ALIAS
17 *                          | properties flow_content?
18 *                          | flow_content
19 * properties           ::= TAG ANCHOR? | ANCHOR TAG?
20 * block_content        ::= block_collection | flow_collection | SCALAR
21 * flow_content         ::= flow_collection | SCALAR
22 * block_collection     ::= block_sequence | block_mapping
23 * flow_collection      ::= flow_sequence | flow_mapping
24 * block_sequence       ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
25 * indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
26 * block_mapping        ::= BLOCK-MAPPING_START
27 *                          ((KEY block_node_or_indentless_sequence?)?
28 *                          (VALUE block_node_or_indentless_sequence?)?)*
29 *                          BLOCK-END
30 * flow_sequence        ::= FLOW-SEQUENCE-START
31 *                          (flow_sequence_entry FLOW-ENTRY)*
32 *                          flow_sequence_entry?
33 *                          FLOW-SEQUENCE-END
34 * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
35 * flow_mapping         ::= FLOW-MAPPING-START
36 *                          (flow_mapping_entry FLOW-ENTRY)*
37 *                          flow_mapping_entry?
38 *                          FLOW-MAPPING-END
39 * flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
40 */
41
42#include "yaml_private.h"
43
44/*
45 * Peek the next token in the token queue.
46 */
47
48#define PEEK_TOKEN(parser)                                                      \
49    ((parser->is_token_available || yaml_parser_fetch_more_tokens(parser)) ?    \
50        QUEUE_ITER(parser, parser->tokens, 0) : NULL)
51
52/*
53 * Remove the next token from the queue (must be called after PEEK_TOKEN).
54 */
55
56#define SKIP_TOKEN(parser)                                                      \
57    (parser->is_token_available = 0,                                            \
58     parser->tokens_parsed ++,                                                  \
59     parser->is_stream_end_produced =                                           \
60        (QUEUE_ITER(parser, parser->tokens, 0)->type == YAML_STREAM_END_TOKEN), \
61     parser->tokens.head ++)
62
63/*
64 * Public API declarations.
65 */
66
67YAML_DECLARE(int)
68yaml_parser_parse_event(yaml_parser_t *parser, yaml_event_t *event);
69
70/*
71 * State functions.
72 */
73
74static int
75yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event);
76
77static int
78yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event);
79
80static int
81yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event,
82        int implicit);
83
84static int
85yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event);
86
87static int
88yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event);
89
90static int
91yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
92        int block, int indentless_sequence);
93
94static int
95yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
96        yaml_event_t *event, int first);
97
98static int
99yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
100        yaml_event_t *event);
101
102static int
103yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
104        yaml_event_t *event, int first);
105
106static int
107yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
108        yaml_event_t *event);
109
110static int
111yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
112        yaml_event_t *event, int first);
113
114static int
115yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
116        yaml_event_t *event);
117
118static int
119yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
120        yaml_event_t *event);
121
122static int
123yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
124        yaml_event_t *event);
125
126static int
127yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
128        yaml_event_t *event, int first);
129
130static int
131yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
132        yaml_event_t *event, int empty);
133
134/*
135 * Utility functions.
136 */
137
138static int
139yaml_parser_process_empty_scalar(yaml_parser_t *parser,
140        yaml_event_t *event, yaml_mark_t mark);
141
142static int
143yaml_parser_process_directives(yaml_parser_t *parser,
144        yaml_version_directive_t **version_directive_ref,
145        yaml_tag_directive_t **tag_directives_list_ref,
146        size_t *tag_directives_length_ref,
147        size_t *tag_directives_capacity_ref);
148
149static int
150yaml_parser_append_tag_directive(yaml_parser_t *parser,
151        yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark);
152
153/*
154 * Get the next event.
155 */
156
157YAML_DECLARE(int)
158yaml_parser_parse_event(yaml_parser_t *parser, yaml_event_t *event)
159{
160    assert(parser);     /* Non-NULL parser object is expected. */
161    assert(event);      /* Non-NULL event object is expected. */
162
163    /* Erase the event object. */
164
165    memset(event, 0, sizeof(yaml_event_t));
166
167    /* No events after the end of the stream or error. */
168
169    if (parser->is_stream_end_produced || parser->error.type
170            || parser->state == YAML_PARSE_END_STATE) {
171        return 1;
172    }
173
174    /* Generate the next event. */
175
176    return yaml_parser_state_machine(parser, event);
177}
178
179/*
180 * State dispatcher.
181 */
182
183static int
184yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event)
185{
186    switch (parser->state)
187    {
188        case YAML_PARSE_STREAM_START_STATE:
189            return yaml_parser_parse_stream_start(parser, event);
190
191        case YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE:
192            return yaml_parser_parse_document_start(parser, event, 1);
193
194        case YAML_PARSE_DOCUMENT_START_STATE:
195            return yaml_parser_parse_document_start(parser, event, 0);
196
197        case YAML_PARSE_DOCUMENT_CONTENT_STATE:
198            return yaml_parser_parse_document_content(parser, event);
199
200        case YAML_PARSE_DOCUMENT_END_STATE:
201            return yaml_parser_parse_document_end(parser, event);
202
203        case YAML_PARSE_BLOCK_NODE_STATE:
204            return yaml_parser_parse_node(parser, event, 1, 0);
205
206        case YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
207            return yaml_parser_parse_node(parser, event, 1, 1);
208
209        case YAML_PARSE_FLOW_NODE_STATE:
210            return yaml_parser_parse_node(parser, event, 0, 0);
211
212        case YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
213            return yaml_parser_parse_block_sequence_entry(parser, event, 1);
214
215        case YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
216            return yaml_parser_parse_block_sequence_entry(parser, event, 0);
217
218        case YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
219            return yaml_parser_parse_indentless_sequence_entry(parser, event);
220
221        case YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
222            return yaml_parser_parse_block_mapping_key(parser, event, 1);
223
224        case YAML_PARSE_BLOCK_MAPPING_KEY_STATE:
225            return yaml_parser_parse_block_mapping_key(parser, event, 0);
226
227        case YAML_PARSE_BLOCK_MAPPING_VALUE_STATE:
228            return yaml_parser_parse_block_mapping_value(parser, event);
229
230        case YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
231            return yaml_parser_parse_flow_sequence_entry(parser, event, 1);
232
233        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
234            return yaml_parser_parse_flow_sequence_entry(parser, event, 0);
235
236        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
237            return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event);
238
239        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
240            return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event);
241
242        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
243            return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event);
244
245        case YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
246            return yaml_parser_parse_flow_mapping_key(parser, event, 1);
247
248        case YAML_PARSE_FLOW_MAPPING_KEY_STATE:
249            return yaml_parser_parse_flow_mapping_key(parser, event, 0);
250
251        case YAML_PARSE_FLOW_MAPPING_VALUE_STATE:
252            return yaml_parser_parse_flow_mapping_value(parser, event, 0);
253
254        case YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
255            return yaml_parser_parse_flow_mapping_value(parser, event, 1);
256
257        default:
258            assert(0);      /* Invalid state. */
259    }
260
261    return 0;
262}
263
264/*
265 * Parse the production:
266 * stream   ::= STREAM-START implicit_document? explicit_document* STREAM-END
267 *              ************
268 */
269
270static int
271yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event)
272{
273    yaml_token_t *token;
274
275    token = PEEK_TOKEN(parser);
276    if (!token) return 0;
277
278    if (token->type != YAML_STREAM_START_TOKEN) {
279        return PARSER_ERROR_INIT(parser,
280                "did not find expected <stream-start>", token->start_mark);
281    }
282
283    parser->state = YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE;
284    STREAM_START_EVENT_INIT(*event, token->data.stream_start.encoding,
285            token->start_mark, token->start_mark);
286    SKIP_TOKEN(parser);
287
288    return 1;
289}
290
291/*
292 * Parse the productions:
293 * implicit_document    ::= block_node DOCUMENT-END*
294 *                          *
295 * explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
296 *                          *************************
297 */
298
299static int
300yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event,
301        int implicit)
302{
303    yaml_token_t *token;
304    yaml_version_directive_t *version_directive = NULL;
305    struct {
306        yaml_tag_directive_t *list;
307        size_t length;
308        size_t capacity;
309    } tag_directives = { NULL, 0, 0 };
310
311    token = PEEK_TOKEN(parser);
312    if (!token) return 0;
313
314    /* Parse extra document end indicators. */
315
316    if (!implicit)
317    {
318        while (token->type == YAML_DOCUMENT_END_TOKEN) {
319            SKIP_TOKEN(parser);
320            token = PEEK_TOKEN(parser);
321            if (!token) return 0;
322        }
323    }
324
325    /* Parse an implicit document. */
326
327    if (implicit && token->type != YAML_VERSION_DIRECTIVE_TOKEN &&
328            token->type != YAML_TAG_DIRECTIVE_TOKEN &&
329            token->type != YAML_DOCUMENT_START_TOKEN &&
330            token->type != YAML_STREAM_END_TOKEN)
331    {
332        if (!yaml_parser_process_directives(parser, NULL, NULL, NULL, NULL))
333            return 0;
334        if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE))
335            return 0;
336        parser->state = YAML_PARSE_BLOCK_NODE_STATE;
337        DOCUMENT_START_EVENT_INIT(*event, NULL, NULL, 0, 0, 1,
338                token->start_mark, token->start_mark);
339        return 1;
340    }
341
342    /* Parse an explicit document. */
343
344    else if (token->type != YAML_STREAM_END_TOKEN)
345    {
346        yaml_mark_t start_mark, end_mark;
347        start_mark = token->start_mark;
348        if (!yaml_parser_process_directives(parser, &version_directive,
349                    &tag_directives.list, &tag_directives.length,
350                    &tag_directives.capacity))
351            return 0;
352        token = PEEK_TOKEN(parser);
353        if (!token) goto error;
354        if (token->type != YAML_DOCUMENT_START_TOKEN) {
355            PARSER_ERROR_INIT(parser,
356                    "did not find expected <document start>", token->start_mark);
357            goto error;
358        }
359        if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE))
360            goto error;
361        parser->state = YAML_PARSE_DOCUMENT_CONTENT_STATE;
362        end_mark = token->end_mark;
363        DOCUMENT_START_EVENT_INIT(*event, version_directive,
364                tag_directives.list, tag_directives.length,
365                tag_directives.capacity, 0,
366                start_mark, end_mark);
367        SKIP_TOKEN(parser);
368        version_directive = NULL;
369        tag_directives.list = NULL;
370        tag_directives.length = tag_directives.capacity = 0;
371        return 1;
372    }
373
374    /* Parse the stream end. */
375
376    else
377    {
378        parser->state = YAML_PARSE_END_STATE;
379        STREAM_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
380        SKIP_TOKEN(parser);
381        return 1;
382    }
383
384error:
385    yaml_free(version_directive);
386    while (!STACK_EMPTY(parser, tag_directives)) {
387        yaml_tag_directive_t tag_directive = POP(parser, tag_directives);
388        yaml_free(tag_directive.handle);
389        yaml_free(tag_directive.prefix);
390    }
391    STACK_DEL(parser, tag_directives);
392    return 0;
393}
394
395/*
396 * Parse the productions:
397 * explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
398 *                                                    ***********
399 */
400
401static int
402yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event)
403{
404    yaml_token_t *token;
405
406    token = PEEK_TOKEN(parser);
407    if (!token) return 0;
408
409    if (token->type == YAML_VERSION_DIRECTIVE_TOKEN ||
410            token->type == YAML_TAG_DIRECTIVE_TOKEN ||
411            token->type == YAML_DOCUMENT_START_TOKEN ||
412            token->type == YAML_DOCUMENT_END_TOKEN ||
413            token->type == YAML_STREAM_END_TOKEN) {
414        parser->state = POP(parser, parser->states);
415        return yaml_parser_process_empty_scalar(parser, event,
416                token->start_mark);
417    }
418    else {
419        return yaml_parser_parse_node(parser, event, 1, 0);
420    }
421}
422
423/*
424 * Parse the productions:
425 * implicit_document    ::= block_node DOCUMENT-END*
426 *                                     *************
427 * explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
428 *                                                                *************
429 */
430
431static int
432yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event)
433{
434    yaml_token_t *token;
435    yaml_mark_t start_mark, end_mark;
436    int implicit = 1;
437
438    token = PEEK_TOKEN(parser);
439    if (!token) return 0;
440
441    start_mark = end_mark = token->start_mark;
442
443    if (token->type == YAML_DOCUMENT_END_TOKEN) {
444        end_mark = token->end_mark;
445        SKIP_TOKEN(parser);
446        implicit = 0;
447    }
448
449    while (!STACK_EMPTY(parser, parser->tag_directives)) {
450        yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
451        yaml_free(tag_directive.handle);
452        yaml_free(tag_directive.prefix);
453    }
454
455    parser->state = YAML_PARSE_DOCUMENT_START_STATE;
456    DOCUMENT_END_EVENT_INIT(*event, implicit, start_mark, end_mark);
457
458    return 1;
459}
460
461/*
462 * Parse the productions:
463 * block_node_or_indentless_sequence    ::=
464 *                          ALIAS
465 *                          *****
466 *                          | properties (block_content | indentless_block_sequence)?
467 *                            **********  *
468 *                          | block_content | indentless_block_sequence
469 *                            *
470 * block_node           ::= ALIAS
471 *                          *****
472 *                          | properties block_content?
473 *                            ********** *
474 *                          | block_content
475 *                            *
476 * flow_node            ::= ALIAS
477 *                          *****
478 *                          | properties flow_content?
479 *                            ********** *
480 *                          | flow_content
481 *                            *
482 * properties           ::= TAG ANCHOR? | ANCHOR TAG?
483 *                          *************************
484 * block_content        ::= block_collection | flow_collection | SCALAR
485 *                                                               ******
486 * flow_content         ::= flow_collection | SCALAR
487 *                                            ******
488 */
489
490static int
491yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
492        int block, int indentless_sequence)
493{
494    yaml_token_t *token;
495    yaml_char_t *anchor = NULL;
496    yaml_char_t *tag_handle = NULL;
497    yaml_char_t *tag_suffix = NULL;
498    yaml_char_t *tag = NULL;
499    yaml_mark_t start_mark, end_mark, tag_mark;
500    int implicit;
501
502    token = PEEK_TOKEN(parser);
503    if (!token) return 0;
504
505    if (token->type == YAML_ALIAS_TOKEN)
506    {
507        parser->state = POP(parser, parser->states);
508        ALIAS_EVENT_INIT(*event, token->data.alias.value,
509                token->start_mark, token->end_mark);
510        SKIP_TOKEN(parser);
511        return 1;
512    }
513
514    else
515    {
516        start_mark = end_mark = token->start_mark;
517
518        if (token->type == YAML_ANCHOR_TOKEN)
519        {
520            anchor = token->data.anchor.value;
521            start_mark = token->start_mark;
522            end_mark = token->end_mark;
523            SKIP_TOKEN(parser);
524            token = PEEK_TOKEN(parser);
525            if (!token) goto error;
526            if (token->type == YAML_TAG_TOKEN)
527            {
528                tag_handle = token->data.tag.handle;
529                tag_suffix = token->data.tag.suffix;
530                tag_mark = token->start_mark;
531                end_mark = token->end_mark;
532                SKIP_TOKEN(parser);
533                token = PEEK_TOKEN(parser);
534                if (!token) goto error;
535            }
536        }
537        else if (token->type == YAML_TAG_TOKEN)
538        {
539            tag_handle = token->data.tag.handle;
540            tag_suffix = token->data.tag.suffix;
541            start_mark = tag_mark = token->start_mark;
542            end_mark = token->end_mark;
543            SKIP_TOKEN(parser);
544            token = PEEK_TOKEN(parser);
545            if (!token) goto error;
546            if (token->type == YAML_ANCHOR_TOKEN)
547            {
548                anchor = token->data.anchor.value;
549                end_mark = token->end_mark;
550                SKIP_TOKEN(parser);
551                token = PEEK_TOKEN(parser);
552                if (!token) goto error;
553            }
554        }
555
556        if (tag_handle) {
557            if (!*tag_handle) {
558                tag = tag_suffix;
559                yaml_free(tag_handle);
560                tag_handle = tag_suffix = NULL;
561            }
562            else {
563                int idx;
564                for (idx = 0; idx < parser->tag_directives.length; idx++) {
565                    yaml_tag_directive_t *tag_directive =
566                        STACK_ITER(parser, parser->tag_directives, idx);
567                    if (strcmp((char *)tag_directive->handle, (char *)tag_handle) == 0) {
568                        size_t prefix_len = strlen((char *)tag_directive->prefix);
569                        size_t suffix_len = strlen((char *)tag_suffix);
570                        tag = yaml_malloc(prefix_len+suffix_len+1);
571                        if (!tag) {
572                            MEMORY_ERROR_INIT(parser);
573                            goto error;
574                        }
575                        memcpy(tag, tag_directive->prefix, prefix_len);
576                        memcpy(tag+prefix_len, tag_suffix, suffix_len);
577                        tag[prefix_len+suffix_len] = '\0';
578                        yaml_free(tag_handle);
579                        yaml_free(tag_suffix);
580                        tag_handle = tag_suffix = NULL;
581                        break;
582                    }
583                }
584                if (!tag) {
585                    PARSER_ERROR_WITH_CONTEXT_INIT(parser,
586                            "while parsing a node", start_mark,
587                            "found undefined tag handle", tag_mark);
588                    goto error;
589                }
590            }
591        }
592
593        implicit = (!tag || !*tag);
594        if (indentless_sequence && token->type == YAML_BLOCK_ENTRY_TOKEN) {
595            end_mark = token->end_mark;
596            parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
597            SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
598                    YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark);
599            return 1;
600        }
601        else {
602            if (token->type == YAML_SCALAR_TOKEN) {
603                int plain_implicit = 0;
604                int quoted_implicit = 0;
605                end_mark = token->end_mark;
606                if ((token->data.scalar.style == YAML_PLAIN_SCALAR_STYLE && !tag)
607                        || (tag && strcmp((char *)tag, "!") == 0)) {
608                    plain_implicit = 1;
609                }
610                else if (!tag) {
611                    quoted_implicit = 1;
612                }
613                parser->state = POP(parser, parser->states);
614                SCALAR_EVENT_INIT(*event, anchor, tag,
615                        token->data.scalar.value, token->data.scalar.length,
616                        plain_implicit, quoted_implicit,
617                        token->data.scalar.style, start_mark, end_mark);
618                SKIP_TOKEN(parser);
619                return 1;
620            }
621            else if (token->type == YAML_FLOW_SEQUENCE_START_TOKEN) {
622                end_mark = token->end_mark;
623                parser->state = YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE;
624                SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
625                        YAML_FLOW_SEQUENCE_STYLE, start_mark, end_mark);
626                return 1;
627            }
628            else if (token->type == YAML_FLOW_MAPPING_START_TOKEN) {
629                end_mark = token->end_mark;
630                parser->state = YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE;
631                MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit,
632                        YAML_FLOW_MAPPING_STYLE, start_mark, end_mark);
633                return 1;
634            }
635            else if (block && token->type == YAML_BLOCK_SEQUENCE_START_TOKEN) {
636                end_mark = token->end_mark;
637                parser->state = YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE;
638                SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
639                        YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark);
640                return 1;
641            }
642            else if (block && token->type == YAML_BLOCK_MAPPING_START_TOKEN) {
643                end_mark = token->end_mark;
644                parser->state = YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE;
645                MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit,
646                        YAML_BLOCK_MAPPING_STYLE, start_mark, end_mark);
647                return 1;
648            }
649            else if (anchor || tag) {
650                yaml_char_t *value = yaml_malloc(1);
651                if (!value) {
652                    MEMORY_ERROR_INIT(parser);
653                    goto error;
654                }
655                value[0] = '\0';
656                parser->state = POP(parser, parser->states);
657                SCALAR_EVENT_INIT(*event, anchor, tag, value, 0,
658                        implicit, 0, YAML_PLAIN_SCALAR_STYLE,
659                        start_mark, end_mark);
660                return 1;
661            }
662            else {
663                PARSER_ERROR_WITH_CONTEXT_INIT(parser,
664                        (block ? "while parsing a block node"
665                         : "while parsing a flow node"), start_mark,
666                        "did not find expected node content", token->start_mark);
667                goto error;
668            }
669        }
670    }
671
672error:
673    yaml_free(anchor);
674    yaml_free(tag_handle);
675    yaml_free(tag_suffix);
676    yaml_free(tag);
677
678    return 0;
679}
680
681/*
682 * Parse the productions:
683 * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
684 *                    ********************  *********** *             *********
685 */
686
687static int
688yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
689        yaml_event_t *event, int first)
690{
691    yaml_token_t *token;
692
693    if (first) {
694        token = PEEK_TOKEN(parser);
695        if (!PUSH(parser, parser->marks, token->start_mark))
696            return 0;
697        SKIP_TOKEN(parser);
698    }
699
700    token = PEEK_TOKEN(parser);
701    if (!token) return 0;
702
703    if (token->type == YAML_BLOCK_ENTRY_TOKEN)
704    {
705        yaml_mark_t mark = token->end_mark;
706        SKIP_TOKEN(parser);
707        token = PEEK_TOKEN(parser);
708        if (!token) return 0;
709        if (token->type != YAML_BLOCK_ENTRY_TOKEN &&
710                token->type != YAML_BLOCK_END_TOKEN) {
711            if (!PUSH(parser, parser->states,
712                        YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE))
713                return 0;
714            return yaml_parser_parse_node(parser, event, 1, 0);
715        }
716        else {
717            parser->state = YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE;
718            return yaml_parser_process_empty_scalar(parser, event, mark);
719        }
720    }
721
722    else if (token->type == YAML_BLOCK_END_TOKEN)
723    {
724        yaml_mark_t dummy_mark;     /* Used to eliminate a compiler warning. */
725        parser->state = POP(parser, parser->states);
726        dummy_mark = POP(parser, parser->marks);
727        SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
728        SKIP_TOKEN(parser);
729        return 1;
730    }
731
732    else
733    {
734        return PARSER_ERROR_WITH_CONTEXT_INIT(parser,
735                "while parsing a block collection", POP(parser, parser->marks),
736                "did not find expected '-' indicator", token->start_mark);
737    }
738}
739
740/*
741 * Parse the productions:
742 * indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
743 *                           *********** *
744 */
745
746static int
747yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
748        yaml_event_t *event)
749{
750    yaml_token_t *token;
751
752    token = PEEK_TOKEN(parser);
753    if (!token) return 0;
754
755    if (token->type == YAML_BLOCK_ENTRY_TOKEN)
756    {
757        yaml_mark_t mark = token->end_mark;
758        SKIP_TOKEN(parser);
759        token = PEEK_TOKEN(parser);
760        if (!token) return 0;
761        if (token->type != YAML_BLOCK_ENTRY_TOKEN &&
762                token->type != YAML_KEY_TOKEN &&
763                token->type != YAML_VALUE_TOKEN &&
764                token->type != YAML_BLOCK_END_TOKEN) {
765            if (!PUSH(parser, parser->states,
766                        YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE))
767                return 0;
768            return yaml_parser_parse_node(parser, event, 1, 0);
769        }
770        else {
771            parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
772            return yaml_parser_process_empty_scalar(parser, event, mark);
773        }
774    }
775
776    else
777    {
778        parser->state = POP(parser, parser->states);
779        SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->start_mark);
780        return 1;
781    }
782}
783
784/*
785 * Parse the productions:
786 * block_mapping        ::= BLOCK-MAPPING_START
787 *                          *******************
788 *                          ((KEY block_node_or_indentless_sequence?)?
789 *                            *** *
790 *                          (VALUE block_node_or_indentless_sequence?)?)*
791 *
792 *                          BLOCK-END
793 *                          *********
794 */
795
796static int
797yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
798        yaml_event_t *event, int first)
799{
800    yaml_token_t *token;
801
802    if (first) {
803        token = PEEK_TOKEN(parser);
804        if (!PUSH(parser, parser->marks, token->start_mark))
805            return 0;
806        SKIP_TOKEN(parser);
807    }
808
809    token = PEEK_TOKEN(parser);
810    if (!token) return 0;
811
812    if (token->type == YAML_KEY_TOKEN)
813    {
814        yaml_mark_t mark = token->end_mark;
815        SKIP_TOKEN(parser);
816        token = PEEK_TOKEN(parser);
817        if (!token) return 0;
818        if (token->type != YAML_KEY_TOKEN &&
819                token->type != YAML_VALUE_TOKEN &&
820                token->type != YAML_BLOCK_END_TOKEN) {
821            if (!PUSH(parser, parser->states,
822                        YAML_PARSE_BLOCK_MAPPING_VALUE_STATE))
823                return 0;
824            return yaml_parser_parse_node(parser, event, 1, 1);
825        }
826        else {
827            parser->state = YAML_PARSE_BLOCK_MAPPING_VALUE_STATE;
828            return yaml_parser_process_empty_scalar(parser, event, mark);
829        }
830    }
831
832    else if (token->type == YAML_BLOCK_END_TOKEN)
833    {
834        yaml_mark_t dummy_mark;     /* Used to eliminate a compiler warning. */
835        parser->state = POP(parser, parser->states);
836        dummy_mark = POP(parser, parser->marks);
837        MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
838        SKIP_TOKEN(parser);
839        return 1;
840    }
841
842    else
843    {
844        return PARSER_ERROR_WITH_CONTEXT_INIT(parser,
845                "while parsing a block mapping", POP(parser, parser->marks),
846                "did not find expected key", token->start_mark);
847    }
848}
849
850/*
851 * Parse the productions:
852 * block_mapping        ::= BLOCK-MAPPING_START
853 *
854 *                          ((KEY block_node_or_indentless_sequence?)?
855 *
856 *                          (VALUE block_node_or_indentless_sequence?)?)*
857 *                           ***** *
858 *                          BLOCK-END
859 *
860 */
861
862static int
863yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
864        yaml_event_t *event)
865{
866    yaml_token_t *token;
867
868    token = PEEK_TOKEN(parser);
869    if (!token) return 0;
870
871    if (token->type == YAML_VALUE_TOKEN)
872    {
873        yaml_mark_t mark = token->end_mark;
874        SKIP_TOKEN(parser);
875        token = PEEK_TOKEN(parser);
876        if (!token) return 0;
877        if (token->type != YAML_KEY_TOKEN &&
878                token->type != YAML_VALUE_TOKEN &&
879                token->type != YAML_BLOCK_END_TOKEN) {
880            if (!PUSH(parser, parser->states,
881                        YAML_PARSE_BLOCK_MAPPING_KEY_STATE))
882                return 0;
883            return yaml_parser_parse_node(parser, event, 1, 1);
884        }
885        else {
886            parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
887            return yaml_parser_process_empty_scalar(parser, event, mark);
888        }
889    }
890
891    else
892    {
893        parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
894        return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
895    }
896}
897
898/*
899 * Parse the productions:
900 * flow_sequence        ::= FLOW-SEQUENCE-START
901 *                          *******************
902 *                          (flow_sequence_entry FLOW-ENTRY)*
903 *                           *                   **********
904 *                          flow_sequence_entry?
905 *                          *
906 *                          FLOW-SEQUENCE-END
907 *                          *****************
908 * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
909 *                          *
910 */
911
912static int
913yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
914        yaml_event_t *event, int first)
915{
916    yaml_token_t *token;
917    yaml_mark_t dummy_mark;     /* Used to eliminate a compiler warning. */
918
919    if (first) {
920        token = PEEK_TOKEN(parser);
921        if (!PUSH(parser, parser->marks, token->start_mark))
922            return 0;
923        SKIP_TOKEN(parser);
924    }
925
926    token = PEEK_TOKEN(parser);
927    if (!token) return 0;
928
929    if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN)
930    {
931        if (!first) {
932            if (token->type == YAML_FLOW_ENTRY_TOKEN) {
933                SKIP_TOKEN(parser);
934                token = PEEK_TOKEN(parser);
935                if (!token) return 0;
936            }
937            else {
938                return PARSER_ERROR_WITH_CONTEXT_INIT(parser,
939                        "while parsing a flow sequence", POP(parser, parser->marks),
940                        "did not find expected ',' or ']'", token->start_mark);
941            }
942        }
943
944        if (token->type == YAML_KEY_TOKEN) {
945            parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE;
946            MAPPING_START_EVENT_INIT(*event, NULL, NULL,
947                    1, YAML_FLOW_MAPPING_STYLE,
948                    token->start_mark, token->end_mark);
949            SKIP_TOKEN(parser);
950            return 1;
951        }
952
953        else if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
954            if (!PUSH(parser, parser->states,
955                        YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE))
956                return 0;
957            return yaml_parser_parse_node(parser, event, 0, 0);
958        }
959    }
960
961    parser->state = POP(parser, parser->states);
962    dummy_mark = POP(parser, parser->marks);
963    SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
964    SKIP_TOKEN(parser);
965    return 1;
966}
967
968/*
969 * Parse the productions:
970 * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
971 *                                      *** *
972 */
973
974static int
975yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
976        yaml_event_t *event)
977{
978    yaml_token_t *token;
979
980    token = PEEK_TOKEN(parser);
981    if (!token) return 0;
982
983    if (token->type != YAML_VALUE_TOKEN && token->type != YAML_FLOW_ENTRY_TOKEN
984            && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
985        if (!PUSH(parser, parser->states,
986                    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE))
987            return 0;
988        return yaml_parser_parse_node(parser, event, 0, 0);
989    }
990    else {
991        yaml_mark_t mark = token->end_mark;
992        SKIP_TOKEN(parser);
993        parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE;
994        return yaml_parser_process_empty_scalar(parser, event, mark);
995    }
996}
997
998/*
999 * Parse the productions:
1000 * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1001 *                                                      ***** *
1002 */
1003
1004static int
1005yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
1006        yaml_event_t *event)
1007{
1008    yaml_token_t *token;
1009
1010    token = PEEK_TOKEN(parser);
1011    if (!token) return 0;
1012
1013    if (token->type == YAML_VALUE_TOKEN) {
1014        SKIP_TOKEN(parser);
1015        token = PEEK_TOKEN(parser);
1016        if (!token) return 0;
1017        if (token->type != YAML_FLOW_ENTRY_TOKEN
1018                && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
1019            if (!PUSH(parser, parser->states,
1020                        YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE))
1021                return 0;
1022            return yaml_parser_parse_node(parser, event, 0, 0);
1023        }
1024    }
1025    parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE;
1026    return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
1027}
1028
1029/*
1030 * Parse the productions:
1031 * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1032 *                                                                      *
1033 */
1034
1035static int
1036yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
1037        yaml_event_t *event)
1038{
1039    yaml_token_t *token;
1040
1041    token = PEEK_TOKEN(parser);
1042    if (!token) return 0;
1043
1044    parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE;
1045
1046    MAPPING_END_EVENT_INIT(*event, token->start_mark, token->start_mark);
1047    return 1;
1048}
1049
1050/*
1051 * Parse the productions:
1052 * flow_mapping         ::= FLOW-MAPPING-START
1053 *                          ******************
1054 *                          (flow_mapping_entry FLOW-ENTRY)*
1055 *                           *                  **********
1056 *                          flow_mapping_entry?
1057 *                          ******************
1058 *                          FLOW-MAPPING-END
1059 *                          ****************
1060 * flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1061 *                          *           *** *
1062 */
1063
1064static int
1065yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
1066        yaml_event_t *event, int first)
1067{
1068    yaml_token_t *token;
1069    yaml_mark_t dummy_mark;     /* Used to eliminate a compiler warning. */
1070
1071    if (first) {
1072        token = PEEK_TOKEN(parser);
1073        if (!PUSH(parser, parser->marks, token->start_mark))
1074            return 0;
1075        SKIP_TOKEN(parser);
1076    }
1077
1078    token = PEEK_TOKEN(parser);
1079    if (!token) return 0;
1080
1081    if (token->type != YAML_FLOW_MAPPING_END_TOKEN)
1082    {
1083        if (!first) {
1084            if (token->type == YAML_FLOW_ENTRY_TOKEN) {
1085                SKIP_TOKEN(parser);
1086                token = PEEK_TOKEN(parser);
1087                if (!token) return 0;
1088            }
1089            else {
1090                return PARSER_ERROR_WITH_CONTEXT_INIT(parser,
1091                        "while parsing a flow mapping", POP(parser, parser->marks),
1092                        "did not find expected ',' or '}'", token->start_mark);
1093            }
1094        }
1095
1096        if (token->type == YAML_KEY_TOKEN) {
1097            SKIP_TOKEN(parser);
1098            token = PEEK_TOKEN(parser);
1099            if (!token) return 0;
1100            if (token->type != YAML_VALUE_TOKEN
1101                    && token->type != YAML_FLOW_ENTRY_TOKEN
1102                    && token->type != YAML_FLOW_MAPPING_END_TOKEN) {
1103                if (!PUSH(parser, parser->states,
1104                            YAML_PARSE_FLOW_MAPPING_VALUE_STATE))
1105                    return 0;
1106                return yaml_parser_parse_node(parser, event, 0, 0);
1107            }
1108            else {
1109                parser->state = YAML_PARSE_FLOW_MAPPING_VALUE_STATE;
1110                return yaml_parser_process_empty_scalar(parser, event,
1111                        token->start_mark);
1112            }
1113        }
1114        else if (token->type != YAML_FLOW_MAPPING_END_TOKEN) {
1115            if (!PUSH(parser, parser->states,
1116                        YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE))
1117                return 0;
1118            return yaml_parser_parse_node(parser, event, 0, 0);
1119        }
1120    }
1121
1122    parser->state = POP(parser, parser->states);
1123    dummy_mark = POP(parser, parser->marks);
1124    MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
1125    SKIP_TOKEN(parser);
1126    return 1;
1127}
1128
1129/*
1130 * Parse the productions:
1131 * flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1132 *                                   *                  ***** *
1133 */
1134
1135static int
1136yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
1137        yaml_event_t *event, int empty)
1138{
1139    yaml_token_t *token;
1140
1141    token = PEEK_TOKEN(parser);
1142    if (!token) return 0;
1143
1144    if (empty) {
1145        parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
1146        return yaml_parser_process_empty_scalar(parser, event,
1147                token->start_mark);
1148    }
1149
1150    if (token->type == YAML_VALUE_TOKEN) {
1151        SKIP_TOKEN(parser);
1152        token = PEEK_TOKEN(parser);
1153        if (!token) return 0;
1154        if (token->type != YAML_FLOW_ENTRY_TOKEN
1155                && token->type != YAML_FLOW_MAPPING_END_TOKEN) {
1156            if (!PUSH(parser, parser->states,
1157                        YAML_PARSE_FLOW_MAPPING_KEY_STATE))
1158                return 0;
1159            return yaml_parser_parse_node(parser, event, 0, 0);
1160        }
1161    }
1162
1163    parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
1164    return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
1165}
1166
1167/*
1168 * Generate an empty scalar event.
1169 */
1170
1171static int
1172yaml_parser_process_empty_scalar(yaml_parser_t *parser, yaml_event_t *event,
1173        yaml_mark_t mark)
1174{
1175    yaml_char_t *value;
1176
1177    value = yaml_malloc(1);
1178    if (!value) {
1179        return MEMORY_ERROR_INIT(parser);
1180    }
1181    value[0] = '\0';
1182
1183    SCALAR_EVENT_INIT(*event, NULL, NULL, value, 0,
1184            1, 0, YAML_PLAIN_SCALAR_STYLE, mark, mark);
1185
1186    return 1;
1187}
1188
1189/*
1190 * Parse directives.
1191 */
1192
1193static int
1194yaml_parser_process_directives(yaml_parser_t *parser,
1195        yaml_version_directive_t **version_directive_ref,
1196        yaml_tag_directive_t **tag_directives_list_ref,
1197        size_t *tag_directives_length_ref,
1198        size_t *tag_directives_capacity_ref)
1199{
1200    yaml_tag_directive_t default_tag_directives[] = {
1201        {(yaml_char_t *)"!", (yaml_char_t *)"!"},
1202        {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"},
1203        {NULL, NULL}
1204    };
1205    yaml_tag_directive_t *default_tag_directive;
1206    yaml_version_directive_t *version_directive = NULL;
1207    struct {
1208        yaml_tag_directive_t *list;
1209        size_t length;
1210        size_t capacity;
1211    } tag_directives = { NULL, 0, 0 };
1212    yaml_token_t *token;
1213
1214    if (!STACK_INIT(parser, tag_directives, INITIAL_STACK_CAPACITY))
1215        goto error;
1216
1217    token = PEEK_TOKEN(parser);
1218    if (!token) goto error;
1219
1220    while (token->type == YAML_VERSION_DIRECTIVE_TOKEN ||
1221            token->type == YAML_TAG_DIRECTIVE_TOKEN)
1222    {
1223        if (token->type == YAML_VERSION_DIRECTIVE_TOKEN) {
1224            if (version_directive) {
1225                PARSER_ERROR_INIT(parser,
1226                        "found duplicate %YAML directive", token->start_mark);
1227                goto error;
1228            }
1229            if (token->data.version_directive.major != 1
1230                    || token->data.version_directive.minor != 1) {
1231                PARSER_ERROR_INIT(parser,
1232                        "found incompatible YAML document", token->start_mark);
1233                goto error;
1234            }
1235            version_directive = yaml_malloc(sizeof(yaml_version_directive_t));
1236            if (!version_directive) {
1237                MEMORY_ERROR_INIT(parser);
1238                goto error;
1239            }
1240            version_directive->major = token->data.version_directive.major;
1241            version_directive->minor = token->data.version_directive.minor;
1242        }
1243
1244        else if (token->type == YAML_TAG_DIRECTIVE_TOKEN) {
1245            yaml_tag_directive_t value = {
1246                token->data.tag_directive.handle,
1247                token->data.tag_directive.prefix
1248            };
1249            if (!yaml_parser_append_tag_directive(parser, value, 0,
1250                        token->start_mark))
1251                goto error;
1252            if (!PUSH(parser, tag_directives, value))
1253                goto error;
1254        }
1255
1256        SKIP_TOKEN(parser);
1257        token = PEEK_TOKEN(parser);
1258        if (!token) goto error;
1259    }
1260   
1261    for (default_tag_directive = default_tag_directives;
1262            default_tag_directive->handle; default_tag_directive++) {
1263        if (!yaml_parser_append_tag_directive(parser, *default_tag_directive, 1,
1264                    token->start_mark))
1265            goto error;
1266    }
1267
1268    if (version_directive_ref) {
1269        *version_directive_ref = version_directive;
1270    }
1271    if (tag_directives_list_ref) {
1272        if (STACK_EMPTY(parser, tag_directives)) {
1273            *tag_directives_list_ref = NULL;
1274            *tag_directives_length_ref = 0;
1275            *tag_directives_capacity_ref = 0;
1276            STACK_DEL(parser, tag_directives);
1277        }
1278        else {
1279            *tag_directives_list_ref = tag_directives.list;
1280            *tag_directives_length_ref = tag_directives.length;
1281            *tag_directives_capacity_ref = tag_directives.capacity;
1282        }
1283    }
1284    else {
1285        STACK_DEL(parser, tag_directives);
1286    }
1287
1288    return 1;
1289
1290error:
1291    yaml_free(version_directive);
1292    while (!STACK_EMPTY(parser, tag_directives)) {
1293        yaml_tag_directive_t tag_directive = POP(parser, tag_directives);
1294        yaml_free(tag_directive.handle);
1295        yaml_free(tag_directive.prefix);
1296    }
1297    STACK_DEL(parser, tag_directives);
1298    return 0;
1299}
1300
1301/*
1302 * Append a tag directive to the directives stack.
1303 */
1304
1305static int
1306yaml_parser_append_tag_directive(yaml_parser_t *parser,
1307        yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark)
1308{
1309    yaml_tag_directive_t *tag_directive;
1310    yaml_tag_directive_t copy = { NULL, NULL };
1311    int idx;
1312
1313    for (idx = 0; idx < parser->tag_directives.length; idx++) {
1314        yaml_tag_directive_t *tag_directive =
1315            STACK_ITER(parser, parser->tag_directives, idx);
1316        if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) {
1317            if (allow_duplicates)
1318                return 1;
1319            return PARSER_ERROR_INIT(parser,
1320                    "found duplicate %TAG directive", mark);
1321        }
1322    }
1323
1324    copy.handle = yaml_strdup(value.handle);
1325    copy.prefix = yaml_strdup(value.prefix);
1326    if (!copy.handle || !copy.prefix) {
1327        MEMORY_ERROR_INIT(parser);
1328        goto error;
1329    }
1330
1331    if (!PUSH(parser, parser->tag_directives, copy))
1332        goto error;
1333
1334    return 1;
1335
1336error:
1337    yaml_free(copy.handle);
1338    yaml_free(copy.prefix);
1339    return 0;
1340}
1341
Note: See TracBrowser for help on using the repository browser.