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