/* This file is part of Eclat. Copyright (C) 2012 Sergey Poznyakoff. Eclat is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Eclat is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Eclat. If not, see . */ #include "eclat.h" struct config_finish_hook_entry { struct config_finish_hook_entry *next; config_finish_hook_t fun; void *data; }; static struct config_finish_hook_entry *cfh_head, *cfh_tail; void add_config_finish_hook(config_finish_hook_t fun, void *data) { struct config_finish_hook_entry *ent = grecs_malloc(sizeof(*ent)); ent->next = NULL; ent->fun = fun; ent->data = data; if (cfh_tail) cfh_tail->next = ent; else cfh_head = ent; cfh_tail = ent; } int run_config_finish_hooks() { struct config_finish_hook_entry *p; int rc = 0; for (p = cfh_head; p; p = p->next) rc |= p->fun(p->data); return rc; } /* Translation table: region -> endpoint. Its elements are of struct ec2_param type. */ struct grecs_symtab *ec2_regtab; char * region_to_endpoint(const char *region) { struct ec2_param *p, key; key.name = (char*) region; p = grecs_symtab_lookup_or_install(ec2_regtab, &key, NULL); return p ? p->value : NULL; } static int cb_region(enum grecs_callback_command cmd, grecs_locus_t *locus, void *varptr, grecs_value_t *value, void *cb_data) { struct ec2_param *p, key; int install = 1; if (cmd != grecs_callback_set_value) { grecs_error(locus, 0, "Unexpected block statement"); return 1; } if (!value || value->type != GRECS_TYPE_ARRAY || value->v.arg.c != 2) { grecs_error(locus, 0, "expected two strings"); return 1; } if (value->v.arg.v[0]->type != GRECS_TYPE_STRING || value->v.arg.v[1]->type != GRECS_TYPE_STRING) { grecs_error(locus, 0, "expected two strings"); return 1; } key.name = value->v.arg.v[0]->v.string; p = grecs_symtab_lookup_or_install(ec2_regtab, &key, &install); if (!install) free(p->value); /* FIXME: Redefinition warning */ p->value = grecs_strdup(value->v.arg.v[1]->v.string); return 0; } static int cb_format(enum grecs_callback_command cmd, grecs_locus_t *locus, void *varptr, grecs_value_t *value, void *cb_data) { if (cmd != grecs_callback_set_value) { grecs_error(locus, 0, "Unexpected block statement"); return 1; } if (!value || value->type != GRECS_TYPE_ARRAY || value->v.arg.c != 2) { grecs_error(locus, 0, "expected two strings"); return 1; } if (value->v.arg.v[0]->type != GRECS_TYPE_STRING || value->v.arg.v[1]->type != GRECS_TYPE_STRING) { grecs_error(locus, 0, "expected two strings"); return 1; } set_command_format(value->v.arg.v[0]->v.string, value->v.arg.v[1]->v.string, &value->v.arg.v[1]->locus); } static int cb_define_format(enum grecs_callback_command cmd, grecs_locus_t *locus, void *varptr, grecs_value_t *value, void *cb_data) { if (cmd != grecs_callback_set_value) { grecs_error(locus, 0, "Unexpected block statement"); return 1; } if (!value || value->type != GRECS_TYPE_ARRAY || value->v.arg.c != 2) { grecs_error(locus, 0, "expected two strings"); return 1; } if (value->v.arg.v[0]->type != GRECS_TYPE_STRING || value->v.arg.v[1]->type != GRECS_TYPE_STRING) { grecs_error(locus, 0, "expected two strings"); return 1; } define_format(value->v.arg.v[0]->v.string, value->v.arg.v[1]->v.string, &value->v.arg.v[1]->locus); return 0; } static struct grecs_keyword eclat_kw[] = { { "default-endpoint", "hostname", "Set default EC2 endpoint", grecs_type_string, GRECS_DFLT, &endpoint }, { "region", " ", "Define a region", grecs_type_string, GRECS_MULT, NULL, 0, cb_region }, { "access-file", "file", "Specify a file containing `accessID:accessKey' pairs", grecs_type_string, GRECS_DFLT, &access_file_name }, { "default-region", "name", "Define default AWS region", grecs_type_string, GRECS_DFLT, ®ion_name }, { "format", " ", "Set default format for ", grecs_type_string, GRECS_MULT, NULL, 0, cb_format }, { "define-format", " ", "Define a named format", grecs_type_string, GRECS_MULT, NULL, 0, cb_define_format }, { "format-file", "file", "Read format from ", grecs_type_string, GRECS_DFLT, &format_file }, { NULL } }; void config_help() { static char docstring[] = N_("Configuration file structure for eclat.\n" "For more information, use `info eclat configuration'."); grecs_print_docstring(docstring, 0, stdout); grecs_print_statement_array(eclat_kw, 1, 0, stdout); } static void grecs_print_diag(grecs_locus_t const *locus, int err, int errcode, const char *msg) { diag(locus, err ? NULL : "warning", "%s", msg); } void config_init() { grecs_include_path_setup(DEFAULT_VERSION_INCLUDE_DIR, DEFAULT_INCLUDE_DIR, NULL); grecs_preprocessor = DEFAULT_PREPROCESSOR; grecs_log_to_stderr = 1; grecs_adjust_string_locations = 1; grecs_print_diag_fun = grecs_print_diag; ec2_regtab = grecs_symtab_create_default(sizeof(struct ec2_param)); } void config_finish(struct grecs_node *tree) { struct grecs_node *node; grecs_tree_reduce(tree, eclat_kw, GRECS_AGGR); if (debug_level(ECLAT_DEBCAT_CONF)) { grecs_print_node(tree, GRECS_NODE_FLAG_DEFAULT, stderr); fputc('\n', stdout); } if (grecs_tree_process(tree, eclat_kw)) exit(EX_CONFIG); if (grecs_error_count || run_config_finish_hooks()) exit(EX_CONFIG); }