Actual source code: loader.c

      1: #include "yaml_private.h"

      3: /*
      4:  * API functions.
      5:  */

      7: YAML_DECLARE(int)
      8: yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);

     10: /*
     11:  * Error handling.
     12:  */

     14: static int
     15: yaml_parser_set_composer_error(yaml_parser_t *parser,
     16:         const char *problem, yaml_mark_t problem_mark);

     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);

     24: /*
     25:  * Alias handling.
     26:  */

     28: static int
     29: yaml_parser_register_anchor(yaml_parser_t *parser,
     30:         int index, yaml_char_t *anchor);

     32: /*
     33:  * Clean up functions.
     34:  */

     36: static void
     37: yaml_parser_delete_aliases(yaml_parser_t *parser);

     39: /*
     40:  * Document loading context.
     41:  */
     42: struct loader_ctx {
     43:     int *start;
     44:     int *end;
     45:     int *top;
     46: };

     48: /*
     49:  * Composer functions.
     50:  */
     51: static int
     52: yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx);

     54: static int
     55: yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event);

     57: static int
     58: yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event,
     59:         struct loader_ctx *ctx);

     61: static int
     62: yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event,
     63:         struct loader_ctx *ctx);

     65: static int
     66: yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event,
     67:         struct loader_ctx *ctx);

     69: static int
     70: yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event,
     71:         struct loader_ctx *ctx);

     73: static int
     74: yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event,
     75:         struct loader_ctx *ctx);

     77: static int
     78: yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event,
     79:         struct loader_ctx *ctx);

     81: /*
     82:  * Load the next document of the stream.
     83:  */

     85: YAML_DECLARE(int)
     86: yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
     87: {
     88:     yaml_event_t event;

     90:     assert(parser);     /* Non-NULL parser object is expected. */
     91:     assert(document);   /* Non-NULL document object is expected. */

     93:     memset(document, 0, sizeof(yaml_document_t));
     94:     if (!STACK_INIT(parser, document->nodes, yaml_node_t*))
     95:         goto error;

     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:     }

    103:     if (parser->stream_end_produced) {
    104:         return 1;
    105:     }

    107:     if (!yaml_parser_parse(parser, &event)) goto error;
    108:     if (event.type == YAML_STREAM_END_EVENT) {
    109:         return 1;
    110:     }

    112:     if (!STACK_INIT(parser, parser->aliases, yaml_alias_data_t*))
    113:         goto error;

    115:     parser->document = document;

    117:     if (!yaml_parser_load_document(parser, &event)) goto error;

    119:     yaml_parser_delete_aliases(parser);
    120:     parser->document = NULL;

    122:     return 1;

    124: error:

    126:     yaml_parser_delete_aliases(parser);
    127:     yaml_document_delete(document);
    128:     parser->document = NULL;

    130:     return 0;
    131: }

    133: /*
    134:  * Set composer error.
    135:  */

    137: static int
    138: yaml_parser_set_composer_error(yaml_parser_t *parser,
    139:         const char *problem, yaml_mark_t problem_mark)
    140: {
    141:     parser->error = YAML_COMPOSER_ERROR;
    142:     parser->problem = problem;
    143:     parser->problem_mark = problem_mark;

    145:     return 0;
    146: }

    148: /*
    149:  * Set composer error with context.
    150:  */

    152: static int
    153: yaml_parser_set_composer_error_context(yaml_parser_t *parser,
    154:         const char *context, yaml_mark_t context_mark,
    155:         const char *problem, yaml_mark_t problem_mark)
    156: {
    157:     parser->error = YAML_COMPOSER_ERROR;
    158:     parser->context = context;
    159:     parser->context_mark = context_mark;
    160:     parser->problem = problem;
    161:     parser->problem_mark = problem_mark;

    163:     return 0;
    164: }

    166: /*
    167:  * Delete the stack of aliases.
    168:  */

    170: static void
    171: yaml_parser_delete_aliases(yaml_parser_t *parser)
    172: {
    173:     while (!STACK_EMPTY(parser, parser->aliases)) {
    174:         yaml_free(POP(parser, parser->aliases).anchor);
    175:     }
    176:     STACK_DEL(parser, parser->aliases);
    177: }

    179: /*
    180:  * Compose a document object.
    181:  */

    183: static int
    184: yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event)
    185: {
    186:     struct loader_ctx ctx = { NULL, NULL, NULL };

    188:     assert(event->type == YAML_DOCUMENT_START_EVENT);
    189:                         /* DOCUMENT-START is expected. */

    191:     parser->document->version_directive
    192:         = event->data.document_start.version_directive;
    193:     parser->document->tag_directives.start
    194:         = event->data.document_start.tag_directives.start;
    195:     parser->document->tag_directives.end
    196:         = event->data.document_start.tag_directives.end;
    197:     parser->document->start_implicit
    198:         = event->data.document_start.implicit;
    199:     parser->document->start_mark = event->start_mark;

    201:     if (!STACK_INIT(parser, ctx, int*)) return 0;
    202:     if (!yaml_parser_load_nodes(parser, &ctx)) {
    203:         STACK_DEL(parser, ctx);
    204:         return 0;
    205:     }
    206:     STACK_DEL(parser, ctx);

    208:     return 1;
    209: }

    211: /*
    212:  * Compose a node tree.
    213:  */

    215: static int
    216: yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx)
    217: {
    218:     yaml_event_t event;

    220:     do {
    221:         if (!yaml_parser_parse(parser, &event)) return 0;

    223:         switch (event.type) {
    224:             case YAML_ALIAS_EVENT:
    225:                 if (!yaml_parser_load_alias(parser, &event, ctx)) return 0;
    226:                 break;
    227:             case YAML_SCALAR_EVENT:
    228:                 if (!yaml_parser_load_scalar(parser, &event, ctx)) return 0;
    229:                 break;
    230:             case YAML_SEQUENCE_START_EVENT:
    231:                 if (!yaml_parser_load_sequence(parser, &event, ctx)) return 0;
    232:                 break;
    233:             case YAML_SEQUENCE_END_EVENT:
    234:                 if (!yaml_parser_load_sequence_end(parser, &event, ctx))
    235:                     return 0;
    236:                 break;
    237:             case YAML_MAPPING_START_EVENT:
    238:                 if (!yaml_parser_load_mapping(parser, &event, ctx)) return 0;
    239:                 break;
    240:             case YAML_MAPPING_END_EVENT:
    241:                 if (!yaml_parser_load_mapping_end(parser, &event, ctx))
    242:                     return 0;
    243:                 break;
    244:             default:
    245:                 assert(0);  /* Could not happen. */
    246:                 return 0;
    247:             case YAML_DOCUMENT_END_EVENT:
    248:                 break;
    249:         }
    250:     } while (event.type != YAML_DOCUMENT_END_EVENT);

    252:     parser->document->end_implicit = event.data.document_end.implicit;
    253:     parser->document->end_mark = event.end_mark;

    255:     return 1;
    256: }

    258: /*
    259:  * Add an anchor.
    260:  */

    262: static int
    263: yaml_parser_register_anchor(yaml_parser_t *parser,
    264:         int index, yaml_char_t *anchor)
    265: {
    266:     yaml_alias_data_t data;
    267:     yaml_alias_data_t *alias_data;

    269:     if (!anchor) return 1;

    271:     data.anchor = anchor;
    272:     data.index = index;
    273:     data.mark = parser->document->nodes.start[index-1].start_mark;

    275:     for (alias_data = parser->aliases.start;
    276:             alias_data != parser->aliases.top; alias_data ++) {
    277:         if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
    278:             yaml_free(anchor);
    279:             return yaml_parser_set_composer_error_context(parser,
    280:                     "found duplicate anchor; first occurrence",
    281:                     alias_data->mark, "second occurrence", data.mark);
    282:         }
    283:     }

    285:     if (!PUSH(parser, parser->aliases, data)) {
    286:         yaml_free(anchor);
    287:         return 0;
    288:     }

    290:     return 1;
    291: }

    293: /*
    294:  * Compose node into its parent in the stree.
    295:  */

    297: static int
    298: yaml_parser_load_node_add(yaml_parser_t *parser, struct loader_ctx *ctx,
    299:         int index)
    300: {
    301:     struct yaml_node_s *parent;
    302:     int parent_index;

    304:     if (STACK_EMPTY(parser, *ctx)) {
    305:         /* This is the root node, there's no tree to add it to. */
    306:         return 1;
    307:     }

    309:     parent_index = *((*ctx).top - 1);
    310:     parent = &parser->document->nodes.start[parent_index-1];

    312:     switch (parent->type) {
    313:         case YAML_SEQUENCE_NODE:
    314:             if (!STACK_LIMIT(parser, parent->data.sequence.items, INT_MAX-1))
    315:                 return 0;
    316:             if (!PUSH(parser, parent->data.sequence.items, index))
    317:                 return 0;
    318:             break;
    319:         case YAML_MAPPING_NODE: {
    320:             yaml_node_pair_t pair;
    321:             if (!STACK_EMPTY(parser, parent->data.mapping.pairs)) {
    322:                 yaml_node_pair_t *p = parent->data.mapping.pairs.top - 1;
    323:                 if (p->key != 0 && p->value == 0) {
    324:                     p->value = index;
    325:                     break;
    326:                 }
    327:             }

    329:             pair.key = index;
    330:             pair.value = 0;
    331:             if (!STACK_LIMIT(parser, parent->data.mapping.pairs, INT_MAX-1))
    332:                 return 0;
    333:             if (!PUSH(parser, parent->data.mapping.pairs, pair))
    334:                 return 0;

    336:             break;
    337:         }
    338:         default:
    339:             assert(0); /* Could not happen. */
    340:             return 0;
    341:     }
    342:     return 1;
    343: }

    345: /*
    346:  * Compose a node corresponding to an alias.
    347:  */

    349: static int
    350: yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event,
    351:         struct loader_ctx *ctx)
    352: {
    353:     yaml_char_t *anchor = event->data.alias.anchor;
    354:     yaml_alias_data_t *alias_data;

    356:     for (alias_data = parser->aliases.start;
    357:             alias_data != parser->aliases.top; alias_data ++) {
    358:         if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
    359:             yaml_free(anchor);
    360:             return yaml_parser_load_node_add(parser, ctx, alias_data->index);
    361:         }
    362:     }

    364:     yaml_free(anchor);
    365:     return yaml_parser_set_composer_error(parser, "found undefined alias",
    366:             event->start_mark);
    367: }

    369: /*
    370:  * Compose a scalar node.
    371:  */

    373: static int
    374: yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event,
    375:         struct loader_ctx *ctx)
    376: {
    377:     yaml_node_t node;
    378:     int index;
    379:     yaml_char_t *tag = event->data.scalar.tag;

    381:     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;

    383:     if (!tag || strcmp((char *)tag, "!") == 0) {
    384:         yaml_free(tag);
    385:         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
    386:         if (!tag) goto error;
    387:     }

    389:     SCALAR_NODE_INIT(node, tag, event->data.scalar.value,
    390:             event->data.scalar.length, event->data.scalar.style,
    391:             event->start_mark, event->end_mark);

    393:     if (!PUSH(parser, parser->document->nodes, node)) goto error;

    395:     index = parser->document->nodes.top - parser->document->nodes.start;

    397:     if (!yaml_parser_register_anchor(parser, index,
    398:                 event->data.scalar.anchor)) return 0;

    400:     return yaml_parser_load_node_add(parser, ctx, index);

    402: error:
    403:     yaml_free(tag);
    404:     yaml_free(event->data.scalar.anchor);
    405:     yaml_free(event->data.scalar.value);
    406:     return 0;
    407: }

    409: /*
    410:  * Compose a sequence node.
    411:  */

    413: static int
    414: yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event,
    415:         struct loader_ctx *ctx)
    416: {
    417:     yaml_node_t node;
    418:     struct {
    419:         yaml_node_item_t *start;
    420:         yaml_node_item_t *end;
    421:         yaml_node_item_t *top;
    422:     } items = { NULL, NULL, NULL };
    423:     int index;
    424:     yaml_char_t *tag = event->data.sequence_start.tag;

    426:     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;

    428:     if (!tag || strcmp((char *)tag, "!") == 0) {
    429:         yaml_free(tag);
    430:         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
    431:         if (!tag) goto error;
    432:     }

    434:     if (!STACK_INIT(parser, items, yaml_node_item_t*)) goto error;

    436:     SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
    437:             event->data.sequence_start.style,
    438:             event->start_mark, event->end_mark);

    440:     if (!PUSH(parser, parser->document->nodes, node)) goto error;

    442:     index = parser->document->nodes.top - parser->document->nodes.start;

    444:     if (!yaml_parser_register_anchor(parser, index,
    445:                 event->data.sequence_start.anchor)) return 0;

    447:     if (!yaml_parser_load_node_add(parser, ctx, index)) return 0;

    449:     if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0;
    450:     if (!PUSH(parser, *ctx, index)) return 0;

    452:     return 1;

    454: error:
    455:     yaml_free(tag);
    456:     yaml_free(event->data.sequence_start.anchor);
    457:     return 0;
    458: }

    460: static int
    461: yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event,
    462:         struct loader_ctx *ctx)
    463: {
    464:     int index;

    466:     assert(((*ctx).top - (*ctx).start) > 0);

    468:     index = *((*ctx).top - 1);
    469:     assert(parser->document->nodes.start[index-1].type == YAML_SEQUENCE_NODE);
    470:     parser->document->nodes.start[index-1].end_mark = event->end_mark;

    472:     (void)POP(parser, *ctx);

    474:     return 1;
    475: }

    477: /*
    478:  * Compose a mapping node.
    479:  */

    481: static int
    482: yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event,
    483:         struct loader_ctx *ctx)
    484: {
    485:     yaml_node_t node;
    486:     struct {
    487:         yaml_node_pair_t *start;
    488:         yaml_node_pair_t *end;
    489:         yaml_node_pair_t *top;
    490:     } pairs = { NULL, NULL, NULL };
    491:     int index;
    492:     yaml_char_t *tag = event->data.mapping_start.tag;

    494:     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;

    496:     if (!tag || strcmp((char *)tag, "!") == 0) {
    497:         yaml_free(tag);
    498:         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
    499:         if (!tag) goto error;
    500:     }

    502:     if (!STACK_INIT(parser, pairs, yaml_node_pair_t*)) goto error;

    504:     MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
    505:             event->data.mapping_start.style,
    506:             event->start_mark, event->end_mark);

    508:     if (!PUSH(parser, parser->document->nodes, node)) goto error;

    510:     index = parser->document->nodes.top - parser->document->nodes.start;

    512:     if (!yaml_parser_register_anchor(parser, index,
    513:                 event->data.mapping_start.anchor)) return 0;

    515:     if (!yaml_parser_load_node_add(parser, ctx, index)) return 0;

    517:     if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0;
    518:     if (!PUSH(parser, *ctx, index)) return 0;

    520:     return 1;

    522: error:
    523:     yaml_free(tag);
    524:     yaml_free(event->data.mapping_start.anchor);
    525:     return 0;
    526: }

    528: static int
    529: yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event,
    530:         struct loader_ctx *ctx)
    531: {
    532:     int index;

    534:     assert(((*ctx).top - (*ctx).start) > 0);

    536:     index = *((*ctx).top - 1);
    537:     assert(parser->document->nodes.start[index-1].type == YAML_MAPPING_NODE);
    538:     parser->document->nodes.start[index-1].end_mark = event->end_mark;

    540:     (void)POP(parser, *ctx);

    542:     return 1;
    543: }