xref: /petsc/src/sys/yaml/src/loader.c (revision 834855d6effb0d027771461c8e947ee1ce5a1e17)
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