/* This file is part of Eclat. Copyright (C) 2012-2018 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 "libeclat.h" #include struct seqmap { struct grecs_list *namelist; size_t nmaps; struct eclat_map **maps; }; static struct grecs_keyword seqmap_kw[] = { { "type", "'sequence", "Set sequence map type", grecs_type_null }, { "key", "", "key expression", grecs_type_null }, { "sequence", "arg", "list of maps to use", grecs_type_string, GRECS_LIST, NULL, offsetof(struct seqmap, namelist) }, { NULL } }; static void seqmap_confhelp() { static struct grecs_keyword seqmap_top[] = { { "map", "name: string", "Configuration for a sequence map", grecs_type_section, GRECS_INAC, NULL, 0, NULL, NULL, seqmap_kw }, { NULL } }; grecs_print_statement_array(seqmap_top, 1, 0, stdout); } static void seqmap_free(int dbg, void *data) { struct seqmap *seqmap = data; grecs_list_free(seqmap->namelist); if (seqmap->maps) { #if 0 size_t i; /* FIXME: Uncomment this when reference counters are implemented */ for (i = 0; i < seqmap->nmaps; i++) if (seqmap->maps[i]) eclat_map_free(seqmap->maps[i]); #endif free(seqmap->maps); } free(seqmap); } static int seqmap_config(int dbg, struct grecs_node *node, void *data) { struct seqmap *seqmap, **return_seqmap = data; int i; seqmap = grecs_zalloc(sizeof(*seqmap)); for (i = 0; seqmap_kw[i].ident; i++) seqmap_kw[i].varptr = seqmap; if (grecs_tree_process(node->down, seqmap_kw)) { seqmap_free(dbg, seqmap); return eclat_map_failure; } if (!seqmap->namelist || (seqmap->nmaps = grecs_list_size(seqmap->namelist)) == 0) { grecs_error(&node->locus, 0, "sequence empty"); seqmap_free(dbg, seqmap); return eclat_map_failure; } seqmap->maps = grecs_calloc(seqmap->nmaps, sizeof(seqmap->maps[0])); *return_seqmap = seqmap; return eclat_map_ok; } static int seqmap_open(int dbg, void *data) { struct seqmap *seqmap = data; struct grecs_list_entry *ep; size_t i; int rc; for (ep = seqmap->namelist->head, i = 0; ep; ep = ep->next, i++) { struct eclat_map *map; map = eclat_map_lookup(ep->data); if (!map) { err("no such map: %s", ep->data); return eclat_map_failure; } if ((rc = eclat_map_open(map)) != eclat_map_ok) return rc; seqmap->maps[i] = map; } return eclat_map_ok; } static int seqmap_close(int dbg, void *data) { struct seqmap *seqmap = data; size_t i; for (i = 0; i < seqmap->nmaps; i++) { if (seqmap->maps[i]) eclat_map_close(seqmap->maps[i]); } return eclat_map_ok; } static int seqmap_get(int dbg, int dir, void *data, const char *key, char **return_value) { struct seqmap *seqmap = data; size_t i; char *p = grecs_strdup(key); char *v; for (i = 0; i < seqmap->nmaps; i++) { int rc = eclat_map_get(seqmap->maps[i], dir, p, &v); free(p); if (rc != eclat_map_ok) { debug(dbg, 1, ("map %s returned %s", seqmap->maps[i]->name, eclat_map_strerror(rc))); return rc; } p = v; } *return_value = v; return eclat_map_ok; } struct eclat_map_drv eclat_map_drv_seq = { "sequence", seqmap_config, seqmap_open, seqmap_close, seqmap_get, seqmap_free, seqmap_confhelp };