Ejemplo n.º 1
0
int h2o_configurator_apply_commands(h2o_configurator_context_t *ctx, yoml_t *node, int flags_mask, const char **ignore_commands)
{
    struct st_cmd_value_t {
        h2o_configurator_command_t *cmd;
        yoml_t *value;
    };
    H2O_VECTOR(struct st_cmd_value_t) deferred = {}, semi_deferred = {};
    size_t i;
    int ret = -1;

    if (node->type != YOML_TYPE_MAPPING) {
        h2o_configurator_errprintf(NULL, node, "node must be a MAPPING");
        goto Exit;
    }

    /* call on_enter of every configurator */
    if (setup_configurators(ctx, 1, node) != 0)
        goto Exit;

    /* handle the configuration commands */
    for (i = 0; i != node->data.mapping.size; ++i) {
        yoml_t *key = node->data.mapping.elements[i].key, *value = node->data.mapping.elements[i].value;
        h2o_configurator_command_t *cmd;
        /* obtain the target command */
        if (key->type != YOML_TYPE_SCALAR) {
            h2o_configurator_errprintf(NULL, key, "command must be a string");
            goto Exit;
        }
        if (ignore_commands != NULL) {
            size_t i;
            for (i = 0; ignore_commands[i] != NULL; ++i)
                if (strcmp(ignore_commands[i], key->data.scalar) == 0)
                    goto SkipCommand;
        }
        if ((cmd = h2o_configurator_get_command(ctx->globalconf, key->data.scalar)) == NULL) {
            h2o_configurator_errprintf(NULL, key, "unknown command: %s", key->data.scalar);
            goto Exit;
        }
        if ((cmd->flags & flags_mask) == 0) {
            h2o_configurator_errprintf(cmd, key, "the command cannot be used at this level");
            goto Exit;
        }
        /* check value type */
        if ((cmd->flags & (H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR | H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE |
                           H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING)) != 0) {
            switch (value->type) {
            case YOML_TYPE_SCALAR:
                if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR) == 0) {
                    h2o_configurator_errprintf(cmd, value, "argument cannot be a scalar");
                    goto Exit;
                }
                break;
            case YOML_TYPE_SEQUENCE:
                if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE) == 0) {
                    h2o_configurator_errprintf(cmd, value, "argument cannot be a sequence");
                    goto Exit;
                }
                break;
            case YOML_TYPE_MAPPING:
                if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING) == 0) {
                    h2o_configurator_errprintf(cmd, value, "argument cannot be a mapping");
                    goto Exit;
                }
                break;
            default:
                assert(!"unreachable");
                break;
            }
        }
        /* handle the command (or keep it for later execution) */
        if ((cmd->flags & H2O_CONFIGURATOR_FLAG_SEMI_DEFERRED) != 0) {
            h2o_vector_push_back(NULL, &semi_deferred, ((struct st_cmd_value_t){cmd, value}));
        } else if ((cmd->flags & H2O_CONFIGURATOR_FLAG_DEFERRED) != 0) {
Ejemplo n.º 2
0
int h2o_configurator_apply_commands(h2o_configurator_context_t *ctx, yoml_t *node, int flags_mask, const char **ignore_commands)
{
    struct {
        h2o_configurator_command_t *cmd;
        yoml_t *value;
    } *deferred;
    size_t num_deferred = 0, i;

    if (node->type != YOML_TYPE_MAPPING) {
        h2o_configurator_errprintf(NULL, node, "node must be a MAPPING");
        return -1;
    }
    deferred = alloca(sizeof(*deferred) * node->data.mapping.size);

    /* call on_enter of every configurator */
    if (setup_configurators(ctx, 1, node) != 0)
        return -1;

    /* handle the configuration commands */
    for (i = 0; i != node->data.mapping.size; ++i) {
        yoml_t *key = node->data.mapping.elements[i].key, *value = node->data.mapping.elements[i].value;
        h2o_configurator_command_t *cmd;
        /* obtain the target command */
        if (key->type != YOML_TYPE_SCALAR) {
            h2o_configurator_errprintf(NULL, key, "command must be a string");
            return -1;
        }
        if (ignore_commands != NULL) {
            size_t i;
            for (i = 0; ignore_commands[i] != NULL; ++i)
                if (strcmp(ignore_commands[i], key->data.scalar) == 0)
                    goto SkipCommand;
        }
        if ((cmd = h2o_configurator_get_command(ctx->globalconf, key->data.scalar)) == NULL) {
            h2o_configurator_errprintf(NULL, key, "unknown command: %s", key->data.scalar);
            return -1;
        }
        if ((cmd->flags & flags_mask) == 0) {
            h2o_configurator_errprintf(cmd, key, "the command cannot be used at this level");
            return -1;
        }
        /* check value type */
        if ((cmd->flags & (H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR | H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE |
                           H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING)) != 0) {
            switch (value->type) {
            case YOML_TYPE_SCALAR:
                if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR) == 0) {
                    h2o_configurator_errprintf(cmd, value, "argument cannot be a scalar");
                    return -1;
                }
                break;
            case YOML_TYPE_SEQUENCE:
                if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE) == 0) {
                    h2o_configurator_errprintf(cmd, value, "argument cannot be a sequence");
                    return -1;
                }
                break;
            case YOML_TYPE_MAPPING:
                if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING) == 0) {
                    h2o_configurator_errprintf(cmd, value, "argument cannot be a mapping");
                    return -1;
                }
                break;
            default:
                assert(!"unreachable");
                break;
            }
        }
        /* handle the command (or keep it for later execution) */
        if ((cmd->flags & H2O_CONFIGURATOR_FLAG_DEFERRED) != 0) {
            deferred[num_deferred].cmd = cmd;
            deferred[num_deferred].value = value;
            ++num_deferred;
        } else {
            if (cmd->cb(cmd, ctx, value) != 0)
                return -1;
        }
    SkipCommand:
        ;
    }
    for (i = 0; i != num_deferred; ++i) {
        if (deferred[i].cmd->cb(deferred[i].cmd, ctx, deferred[i].value) != 0)
            return -1;
    }

    /* call on_enter of every configurator */
    if (setup_configurators(ctx, 0, node) != 0)
        return -1;

    return 0;
}