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 16yaml_parser_set_composer_error(yaml_parser_t *parser, 17 const char *problem, yaml_mark_t problem_mark); 18 19static int 20yaml_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 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{ 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 occurence", 243 alias_data->mark, "second occurence", 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 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 ptrdiff_t node_index; 287 int index; 288 yaml_char_t *tag = first_event->data.scalar.tag; 289 290 if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; 291 292 if (!tag || strcmp((char *)tag, "!") == 0) { 293 yaml_free(tag); 294 tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG); 295 if (!tag) goto error; 296 } 297 298 SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value, 299 first_event->data.scalar.length, first_event->data.scalar.style, 300 first_event->start_mark, first_event->end_mark); 301 302 if (!PUSH(parser, parser->document->nodes, node)) goto error; 303 304 node_index = parser->document->nodes.top - parser->document->nodes.start; 305#if PTRDIFF_MAX > INT_MAX 306 if (node_index > INT_MAX) goto error; 307#endif 308 index = (int)node_index; 309 310 if (!yaml_parser_register_anchor(parser, index, 311 first_event->data.scalar.anchor)) return 0; 312 313 return index; 314 315error: 316 yaml_free(tag); 317 yaml_free(first_event->data.scalar.anchor); 318 yaml_free(first_event->data.scalar.value); 319 return 0; 320} 321 322/* 323 * Compose a sequence node. 324 */ 325 326static int 327yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event) 328{ 329 yaml_event_t event; 330 yaml_node_t node; 331 struct { 332 yaml_node_item_t *start; 333 yaml_node_item_t *end; 334 yaml_node_item_t *top; 335 } items = { NULL, NULL, NULL }; 336 int index, item_index; 337 ptrdiff_t node_index; 338 yaml_char_t *tag = first_event->data.sequence_start.tag; 339 340 if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; 341 342 if (!tag || strcmp((char *)tag, "!") == 0) { 343 yaml_free(tag); 344 tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG); 345 if (!tag) goto error; 346 } 347 348 if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error; 349 350 SEQUENCE_NODE_INIT(node, tag, items.start, items.end, 351 first_event->data.sequence_start.style, 352 first_event->start_mark, first_event->end_mark); 353 354 if (!PUSH(parser, parser->document->nodes, node)) goto error; 355 356 node_index = parser->document->nodes.top - parser->document->nodes.start; 357#if PTRDIFF_MAX > INT_MAX 358 if (node_index > INT_MAX) goto error; 359#endif 360 index = (int)node_index; 361 362 if (!yaml_parser_register_anchor(parser, index, 363 first_event->data.sequence_start.anchor)) return 0; 364 365 if (!yaml_parser_parse(parser, &event)) return 0; 366 367 while (event.type != YAML_SEQUENCE_END_EVENT) { 368 if (!STACK_LIMIT(parser, 369 parser->document->nodes.start[index-1].data.sequence.items, 370 INT_MAX-1)) return 0; 371 item_index = yaml_parser_load_node(parser, &event); 372 if (!item_index) return 0; 373 if (!PUSH(parser, 374 parser->document->nodes.start[index-1].data.sequence.items, 375 item_index)) return 0; 376 if (!yaml_parser_parse(parser, &event)) return 0; 377 } 378 379 parser->document->nodes.start[index-1].end_mark = event.end_mark; 380 381 return index; 382 383error: 384 yaml_free(tag); 385 yaml_free(first_event->data.sequence_start.anchor); 386 return 0; 387} 388 389/* 390 * Compose a mapping node. 391 */ 392 393static int 394yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event) 395{ 396 yaml_event_t event; 397 yaml_node_t node; 398 struct { 399 yaml_node_pair_t *start; 400 yaml_node_pair_t *end; 401 yaml_node_pair_t *top; 402 } pairs = { NULL, NULL, NULL }; 403 int index; 404 ptrdiff_t node_index; 405 yaml_node_pair_t pair; 406 yaml_char_t *tag = first_event->data.mapping_start.tag; 407 408 if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; 409 410 if (!tag || strcmp((char *)tag, "!") == 0) { 411 yaml_free(tag); 412 tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG); 413 if (!tag) goto error; 414 } 415 416 if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error; 417 418 MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end, 419 first_event->data.mapping_start.style, 420 first_event->start_mark, first_event->end_mark); 421 422 if (!PUSH(parser, parser->document->nodes, node)) goto error; 423 424 node_index = parser->document->nodes.top - parser->document->nodes.start; 425#if PTRDIFF_MAX > INT_MAX 426 if (node_index > INT_MAX) goto error; 427#endif 428 index = (int)node_index; 429 430 if (!yaml_parser_register_anchor(parser, index, 431 first_event->data.mapping_start.anchor)) return 0; 432 433 if (!yaml_parser_parse(parser, &event)) return 0; 434 435 while (event.type != YAML_MAPPING_END_EVENT) { 436 if (!STACK_LIMIT(parser, 437 parser->document->nodes.start[index-1].data.mapping.pairs, 438 INT_MAX-1)) return 0; 439 pair.key = yaml_parser_load_node(parser, &event); 440 if (!pair.key) return 0; 441 if (!yaml_parser_parse(parser, &event)) return 0; 442 pair.value = yaml_parser_load_node(parser, &event); 443 if (!pair.value) return 0; 444 if (!PUSH(parser, 445 parser->document->nodes.start[index-1].data.mapping.pairs, 446 pair)) return 0; 447 if (!yaml_parser_parse(parser, &event)) return 0; 448 } 449 450 parser->document->nodes.start[index-1].end_mark = event.end_mark; 451 452 return index; 453 454error: 455 yaml_free(tag); 456 yaml_free(first_event->data.mapping_start.anchor); 457 return 0; 458} 459 460