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