]> andersk Git - libyaml.git/blame - src/loader.c
Picked typofix from Ruby's Psych parser
[libyaml.git] / src / loader.c
CommitLineData
e27a3c88
KS
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
c9b74def 16yaml_parser_set_composer_error(yaml_parser_t *parser,
e27a3c88
KS
17 const char *problem, yaml_mark_t problem_mark);
18
19static int
c9b74def 20yaml_parser_set_composer_error_context(yaml_parser_t *parser,
e27a3c88
KS
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{
252c575a 228 yaml_alias_data_t data;
e27a3c88
KS
229 yaml_alias_data_t *alias_data;
230
231 if (!anchor) return 1;
232
252c575a
KS
233 data.anchor = anchor;
234 data.index = index;
0174ed6e
KS
235 data.mark = parser->document->nodes.start[index-1].start_mark;
236
e27a3c88
KS
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,
bdf4d192
SH
242 "found duplicate anchor; first occurrence",
243 alias_data->mark, "second occurrence", data.mark);
e27a3c88
KS
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 int index;
287 yaml_char_t *tag = first_event->data.scalar.tag;
288
2d94fc50
KS
289 if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
290
e27a3c88
KS
291 if (!tag || strcmp((char *)tag, "!") == 0) {
292 yaml_free(tag);
c9b74def 293 tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
e27a3c88
KS
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
310error:
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
321static int
322yaml_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
2d94fc50
KS
334 if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
335
e27a3c88
KS
336 if (!tag || strcmp((char *)tag, "!") == 0) {
337 yaml_free(tag);
c9b74def 338 tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
e27a3c88
KS
339 if (!tag) goto error;
340 }
341
342 if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) 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) {
2d94fc50
KS
358 if (!STACK_LIMIT(parser,
359 parser->document->nodes.start[index-1].data.sequence.items,
360 INT_MAX-1)) return 0;
e27a3c88
KS
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
373error:
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
383static int
384yaml_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
2d94fc50
KS
397 if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
398
e27a3c88
KS
399 if (!tag || strcmp((char *)tag, "!") == 0) {
400 yaml_free(tag);
c9b74def 401 tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
e27a3c88
KS
402 if (!tag) goto error;
403 }
404
405 if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) 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) {
2d94fc50
KS
421 if (!STACK_LIMIT(parser,
422 parser->document->nodes.start[index-1].data.mapping.pairs,
423 INT_MAX-1)) return 0;
e27a3c88
KS
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
439error:
440 yaml_free(tag);
441 yaml_free(first_event->data.mapping_start.anchor);
442 return 0;
443}
444
This page took 0.165808 seconds and 5 git commands to generate.