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