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