1
2#include "yaml_private.h"
3
4/*
5 * API functions.
6 */
7
8YAML_DECLARE(int)
9yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
10
11/*
12 * Error handling.
13 */
14
15static int
16yaml_parser_set_composer_error(yaml_parser_t *parser,
17        const char *problem, yaml_mark_t problem_mark);
18
19static int
20yaml_parser_set_composer_error_context(yaml_parser_t *parser,
21        const char *context, yaml_mark_t context_mark,
22        const char *problem, yaml_mark_t problem_mark);
23
24
25/*
26 * Alias handling.
27 */
28
29static int
30yaml_parser_register_anchor(yaml_parser_t *parser,
31        int index, yaml_char_t *anchor);
32
33/*
34 * Clean up functions.
35 */
36
37static void
38yaml_parser_delete_aliases(yaml_parser_t *parser);
39
40/*
41 * Composer functions.
42 */
43
44static int
45yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event);
46
47static int
48yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event);
49
50static int
51yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event);
52
53static int
54yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event);
55
56static int
57yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event);
58
59static int
60yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event);
61
62/*
63 * Load the next document of the stream.
64 */
65
66YAML_DECLARE(int)
67yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
68{
69    yaml_event_t event;
70
71    assert(parser);     /* Non-NULL parser object is expected. */
72    assert(document);   /* Non-NULL document object is expected. */
73
74    memset(document, 0, sizeof(yaml_document_t));
75    if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE))
76        goto error;
77
78    if (!parser->stream_start_produced) {
79        if (!yaml_parser_parse(parser, &event)) goto error;
80        assert(event.type == YAML_STREAM_START_EVENT);
81                        /* STREAM-START is expected. */
82    }
83
84    if (parser->stream_end_produced) {
85        return 1;
86    }
87
88    if (!yaml_parser_parse(parser, &event)) goto error;
89    if (event.type == YAML_STREAM_END_EVENT) {
90        return 1;
91    }
92
93    if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE))
94        goto error;
95
96    parser->document = document;
97
98    if (!yaml_parser_load_document(parser, &event)) goto error;
99
100    yaml_parser_delete_aliases(parser);
101    parser->document = NULL;
102
103    return 1;
104
105error:
106
107    yaml_parser_delete_aliases(parser);
108    yaml_document_delete(document);
109    parser->document = NULL;
110
111    return 0;
112}
113
114/*
115 * Set composer error.
116 */
117
118static int
119yaml_parser_set_composer_error(yaml_parser_t *parser,
120        const char *problem, yaml_mark_t problem_mark)
121{
122    parser->error = YAML_COMPOSER_ERROR;
123    parser->problem = problem;
124    parser->problem_mark = problem_mark;
125
126    return 0;
127}
128
129/*
130 * Set composer error with context.
131 */
132
133static int
134yaml_parser_set_composer_error_context(yaml_parser_t *parser,
135        const char *context, yaml_mark_t context_mark,
136        const char *problem, yaml_mark_t problem_mark)
137{
138    parser->error = YAML_COMPOSER_ERROR;
139    parser->context = context;
140    parser->context_mark = context_mark;
141    parser->problem = problem;
142    parser->problem_mark = problem_mark;
143
144    return 0;
145}
146
147/*
148 * Delete the stack of aliases.
149 */
150
151static void
152yaml_parser_delete_aliases(yaml_parser_t *parser)
153{
154    while (!STACK_EMPTY(parser, parser->aliases)) {
155        yaml_free(POP(parser, parser->aliases).anchor);
156    }
157    STACK_DEL(parser, parser->aliases);
158}
159
160/*
161 * Compose a document object.
162 */
163
164static int
165yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event)
166{
167    yaml_event_t event;
168
169    assert(first_event->type == YAML_DOCUMENT_START_EVENT);
170                        /* DOCUMENT-START is expected. */
171
172    parser->document->version_directive
173        = first_event->data.document_start.version_directive;
174    parser->document->tag_directives.start
175        = first_event->data.document_start.tag_directives.start;
176    parser->document->tag_directives.end
177        = first_event->data.document_start.tag_directives.end;
178    parser->document->start_implicit
179        = first_event->data.document_start.implicit;
180    parser->document->start_mark = first_event->start_mark;
181
182    if (!yaml_parser_parse(parser, &event)) return 0;
183
184    if (!yaml_parser_load_node(parser, &event)) return 0;
185
186    if (!yaml_parser_parse(parser, &event)) return 0;
187    assert(event.type == YAML_DOCUMENT_END_EVENT);
188                        /* DOCUMENT-END is expected. */
189
190    parser->document->end_implicit = event.data.document_end.implicit;
191    parser->document->end_mark = event.end_mark;
192
193    return 1;
194}
195
196/*
197 * Compose a node.
198 */
199
200static int
201yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event)
202{
203    switch (first_event->type) {
204        case YAML_ALIAS_EVENT:
205            return yaml_parser_load_alias(parser, first_event);
206        case YAML_SCALAR_EVENT:
207            return yaml_parser_load_scalar(parser, first_event);
208        case YAML_SEQUENCE_START_EVENT:
209            return yaml_parser_load_sequence(parser, first_event);
210        case YAML_MAPPING_START_EVENT:
211            return yaml_parser_load_mapping(parser, first_event);
212        default:
213            assert(0);  /* Could not happen. */
214            return 0;
215    }
216
217    return 0;
218}
219
220/*
221 * Add an anchor.
222 */
223
224static int
225yaml_parser_register_anchor(yaml_parser_t *parser,
226        int index, yaml_char_t *anchor)
227{
228    yaml_alias_data_t data;
229    yaml_alias_data_t *alias_data;
230
231    if (!anchor) return 1;
232
233    data.anchor = anchor;
234    data.index = index;
235    data.mark = parser->document->nodes.start[index-1].start_mark;
236
237    for (alias_data = parser->aliases.start;
238            alias_data != parser->aliases.top; alias_data ++) {
239        if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
240            yaml_free(anchor);
241            return yaml_parser_set_composer_error_context(parser,
242                    "found duplicate anchor; first occurence",
243                    alias_data->mark, "second occurence", data.mark);
244        }
245    }
246
247    if (!PUSH(parser, parser->aliases, data)) {
248        yaml_free(anchor);
249        return 0;
250    }
251
252    return 1;
253}
254
255/*
256 * Compose a node corresponding to an alias.
257 */
258
259static int
260yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
261{
262    yaml_char_t *anchor = first_event->data.alias.anchor;
263    yaml_alias_data_t *alias_data;
264
265    for (alias_data = parser->aliases.start;
266            alias_data != parser->aliases.top; alias_data ++) {
267        if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
268            yaml_free(anchor);
269            return alias_data->index;
270        }
271    }
272
273    yaml_free(anchor);
274    return yaml_parser_set_composer_error(parser, "found undefined alias",
275            first_event->start_mark);
276}
277
278/*
279 * Compose a scalar node.
280 */
281
282static int
283yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
284{
285    yaml_node_t node;
286    ptrdiff_t node_index;
287    int index;
288    yaml_char_t *tag = first_event->data.scalar.tag;
289
290    if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
291
292    if (!tag || strcmp((char *)tag, "!") == 0) {
293        yaml_free(tag);
294        tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
295        if (!tag) goto error;
296    }
297
298    SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
299            first_event->data.scalar.length, first_event->data.scalar.style,
300            first_event->start_mark, first_event->end_mark);
301
302    if (!PUSH(parser, parser->document->nodes, node)) goto error;
303
304    node_index = parser->document->nodes.top - parser->document->nodes.start;
305#if PTRDIFF_MAX > INT_MAX
306    if (node_index > INT_MAX) goto error;
307#endif
308    index = (int)node_index;
309
310    if (!yaml_parser_register_anchor(parser, index,
311                first_event->data.scalar.anchor)) return 0;
312
313    return index;
314
315error:
316    yaml_free(tag);
317    yaml_free(first_event->data.scalar.anchor);
318    yaml_free(first_event->data.scalar.value);
319    return 0;
320}
321
322/*
323 * Compose a sequence node.
324 */
325
326static int
327yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
328{
329    yaml_event_t event;
330    yaml_node_t node;
331    struct {
332        yaml_node_item_t *start;
333        yaml_node_item_t *end;
334        yaml_node_item_t *top;
335    } items = { NULL, NULL, NULL };
336    int index, item_index;
337    ptrdiff_t node_index;
338    yaml_char_t *tag = first_event->data.sequence_start.tag;
339
340    if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
341
342    if (!tag || strcmp((char *)tag, "!") == 0) {
343        yaml_free(tag);
344        tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
345        if (!tag) goto error;
346    }
347
348    if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;
349
350    SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
351            first_event->data.sequence_start.style,
352            first_event->start_mark, first_event->end_mark);
353
354    if (!PUSH(parser, parser->document->nodes, node)) goto error;
355
356    node_index = parser->document->nodes.top - parser->document->nodes.start;
357#if PTRDIFF_MAX > INT_MAX
358    if (node_index > INT_MAX) goto error;
359#endif
360    index = (int)node_index;
361
362    if (!yaml_parser_register_anchor(parser, index,
363                first_event->data.sequence_start.anchor)) return 0;
364
365    if (!yaml_parser_parse(parser, &event)) return 0;
366
367    while (event.type != YAML_SEQUENCE_END_EVENT) {
368        if (!STACK_LIMIT(parser,
369                    parser->document->nodes.start[index-1].data.sequence.items,
370                    INT_MAX-1)) return 0;
371        item_index = yaml_parser_load_node(parser, &event);
372        if (!item_index) return 0;
373        if (!PUSH(parser,
374                    parser->document->nodes.start[index-1].data.sequence.items,
375                    item_index)) return 0;
376        if (!yaml_parser_parse(parser, &event)) return 0;
377    }
378
379    parser->document->nodes.start[index-1].end_mark = event.end_mark;
380
381    return index;
382
383error:
384    yaml_free(tag);
385    yaml_free(first_event->data.sequence_start.anchor);
386    return 0;
387}
388
389/*
390 * Compose a mapping node.
391 */
392
393static int
394yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
395{
396    yaml_event_t event;
397    yaml_node_t node;
398    struct {
399        yaml_node_pair_t *start;
400        yaml_node_pair_t *end;
401        yaml_node_pair_t *top;
402    } pairs = { NULL, NULL, NULL };
403    int index;
404    ptrdiff_t node_index;
405    yaml_node_pair_t pair;
406    yaml_char_t *tag = first_event->data.mapping_start.tag;
407
408    if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
409
410    if (!tag || strcmp((char *)tag, "!") == 0) {
411        yaml_free(tag);
412        tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
413        if (!tag) goto error;
414    }
415
416    if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;
417
418    MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
419            first_event->data.mapping_start.style,
420            first_event->start_mark, first_event->end_mark);
421
422    if (!PUSH(parser, parser->document->nodes, node)) goto error;
423
424    node_index = parser->document->nodes.top - parser->document->nodes.start;
425#if PTRDIFF_MAX > INT_MAX
426    if (node_index > INT_MAX) goto error;
427#endif
428    index = (int)node_index;
429
430    if (!yaml_parser_register_anchor(parser, index,
431                first_event->data.mapping_start.anchor)) return 0;
432
433    if (!yaml_parser_parse(parser, &event)) return 0;
434
435    while (event.type != YAML_MAPPING_END_EVENT) {
436        if (!STACK_LIMIT(parser,
437                    parser->document->nodes.start[index-1].data.mapping.pairs,
438                    INT_MAX-1)) return 0;
439        pair.key = yaml_parser_load_node(parser, &event);
440        if (!pair.key) return 0;
441        if (!yaml_parser_parse(parser, &event)) return 0;
442        pair.value = yaml_parser_load_node(parser, &event);
443        if (!pair.value) return 0;
444        if (!PUSH(parser,
445                    parser->document->nodes.start[index-1].data.mapping.pairs,
446                    pair)) return 0;
447        if (!yaml_parser_parse(parser, &event)) return 0;
448    }
449
450    parser->document->nodes.start[index-1].end_mark = event.end_mark;
451
452    return index;
453
454error:
455    yaml_free(tag);
456    yaml_free(first_event->data.mapping_start.anchor);
457    return 0;
458}
459
460