1 
2 #include "yaml_private.h"
3 
4 /*
5  * API functions.
6  */
7 
8 YAML_DECLARE(int)
9 yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
10 
11 /*
12  * Error handling.
13  */
14 
15 static int
16 yaml_parser_set_composer_error(yaml_parser_t *parser,
17         const char *problem, yaml_mark_t problem_mark);
18 
19 static int
20 yaml_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 
29 static int
30 yaml_parser_register_anchor(yaml_parser_t *parser,
31         int index, yaml_char_t *anchor);
32 
33 /*
34  * Clean up functions.
35  */
36 
37 static void
38 yaml_parser_delete_aliases(yaml_parser_t *parser);
39 
40 /*
41  * Composer functions.
42  */
43 
44 static int
45 yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event);
46 
47 static int
48 yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event);
49 
50 static int
51 yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event);
52 
53 static int
54 yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event);
55 
56 static int
57 yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event);
58 
59 static int
60 yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event);
61 
62 /*
63  * Load the next document of the stream.
64  */
65 
66 YAML_DECLARE(int)
yaml_parser_load(yaml_parser_t * parser,yaml_document_t * document)67 yaml_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, yaml_node_t*))
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, yaml_alias_data_t*))
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 
105 error:
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 
118 static int
yaml_parser_set_composer_error(yaml_parser_t * parser,const char * problem,yaml_mark_t problem_mark)119 yaml_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 
133 static int
yaml_parser_set_composer_error_context(yaml_parser_t * parser,const char * context,yaml_mark_t context_mark,const char * problem,yaml_mark_t problem_mark)134 yaml_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 
151 static void
yaml_parser_delete_aliases(yaml_parser_t * parser)152 yaml_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 
164 static int
yaml_parser_load_document(yaml_parser_t * parser,yaml_event_t * first_event)165 yaml_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 
200 static int
yaml_parser_load_node(yaml_parser_t * parser,yaml_event_t * first_event)201 yaml_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 
224 static int
yaml_parser_register_anchor(yaml_parser_t * parser,int index,yaml_char_t * anchor)225 yaml_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 occurrence",
243                     alias_data->mark, "second occurrence", 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 
259 static int
yaml_parser_load_alias(yaml_parser_t * parser,yaml_event_t * first_event)260 yaml_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 
282 static int
yaml_parser_load_scalar(yaml_parser_t * parser,yaml_event_t * first_event)283 yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
284 {
285     yaml_node_t node;
286     int index;
287     yaml_char_t *tag = first_event->data.scalar.tag;
288 
289     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
290 
291     if (!tag || strcmp((char *)tag, "!") == 0) {
292         yaml_free(tag);
293         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
294         if (!tag) goto error;
295     }
296 
297     SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
298             first_event->data.scalar.length, first_event->data.scalar.style,
299             first_event->start_mark, first_event->end_mark);
300 
301     if (!PUSH(parser, parser->document->nodes, node)) goto error;
302 
303     index = parser->document->nodes.top - parser->document->nodes.start;
304 
305     if (!yaml_parser_register_anchor(parser, index,
306                 first_event->data.scalar.anchor)) return 0;
307 
308     return index;
309 
310 error:
311     yaml_free(tag);
312     yaml_free(first_event->data.scalar.anchor);
313     yaml_free(first_event->data.scalar.value);
314     return 0;
315 }
316 
317 /*
318  * Compose a sequence node.
319  */
320 
321 static int
yaml_parser_load_sequence(yaml_parser_t * parser,yaml_event_t * first_event)322 yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
323 {
324     yaml_event_t event;
325     yaml_node_t node;
326     struct {
327         yaml_node_item_t *start;
328         yaml_node_item_t *end;
329         yaml_node_item_t *top;
330     } items = { NULL, NULL, NULL };
331     int index, item_index;
332     yaml_char_t *tag = first_event->data.sequence_start.tag;
333 
334     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
335 
336     if (!tag || strcmp((char *)tag, "!") == 0) {
337         yaml_free(tag);
338         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
339         if (!tag) goto error;
340     }
341 
342     if (!STACK_INIT(parser, items, yaml_node_item_t*)) goto error;
343 
344     SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
345             first_event->data.sequence_start.style,
346             first_event->start_mark, first_event->end_mark);
347 
348     if (!PUSH(parser, parser->document->nodes, node)) goto error;
349 
350     index = parser->document->nodes.top - parser->document->nodes.start;
351 
352     if (!yaml_parser_register_anchor(parser, index,
353                 first_event->data.sequence_start.anchor)) return 0;
354 
355     if (!yaml_parser_parse(parser, &event)) return 0;
356 
357     while (event.type != YAML_SEQUENCE_END_EVENT) {
358         if (!STACK_LIMIT(parser,
359                     parser->document->nodes.start[index-1].data.sequence.items,
360                     INT_MAX-1)) return 0;
361         item_index = yaml_parser_load_node(parser, &event);
362         if (!item_index) return 0;
363         if (!PUSH(parser,
364                     parser->document->nodes.start[index-1].data.sequence.items,
365                     item_index)) return 0;
366         if (!yaml_parser_parse(parser, &event)) return 0;
367     }
368 
369     parser->document->nodes.start[index-1].end_mark = event.end_mark;
370 
371     return index;
372 
373 error:
374     yaml_free(tag);
375     yaml_free(first_event->data.sequence_start.anchor);
376     return 0;
377 }
378 
379 /*
380  * Compose a mapping node.
381  */
382 
383 static int
yaml_parser_load_mapping(yaml_parser_t * parser,yaml_event_t * first_event)384 yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
385 {
386     yaml_event_t event;
387     yaml_node_t node;
388     struct {
389         yaml_node_pair_t *start;
390         yaml_node_pair_t *end;
391         yaml_node_pair_t *top;
392     } pairs = { NULL, NULL, NULL };
393     int index;
394     yaml_node_pair_t pair;
395     yaml_char_t *tag = first_event->data.mapping_start.tag;
396 
397     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
398 
399     if (!tag || strcmp((char *)tag, "!") == 0) {
400         yaml_free(tag);
401         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
402         if (!tag) goto error;
403     }
404 
405     if (!STACK_INIT(parser, pairs, yaml_node_pair_t*)) goto error;
406 
407     MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
408             first_event->data.mapping_start.style,
409             first_event->start_mark, first_event->end_mark);
410 
411     if (!PUSH(parser, parser->document->nodes, node)) goto error;
412 
413     index = parser->document->nodes.top - parser->document->nodes.start;
414 
415     if (!yaml_parser_register_anchor(parser, index,
416                 first_event->data.mapping_start.anchor)) return 0;
417 
418     if (!yaml_parser_parse(parser, &event)) return 0;
419 
420     while (event.type != YAML_MAPPING_END_EVENT) {
421         if (!STACK_LIMIT(parser,
422                     parser->document->nodes.start[index-1].data.mapping.pairs,
423                     INT_MAX-1)) return 0;
424         pair.key = yaml_parser_load_node(parser, &event);
425         if (!pair.key) return 0;
426         if (!yaml_parser_parse(parser, &event)) return 0;
427         pair.value = yaml_parser_load_node(parser, &event);
428         if (!pair.value) return 0;
429         if (!PUSH(parser,
430                     parser->document->nodes.start[index-1].data.mapping.pairs,
431                     pair)) return 0;
432         if (!yaml_parser_parse(parser, &event)) return 0;
433     }
434 
435     parser->document->nodes.start[index-1].end_mark = event.end_mark;
436 
437     return index;
438 
439 error:
440     yaml_free(tag);
441     yaml_free(first_event->data.mapping_start.anchor);
442     return 0;
443 }
444 
445