/* This file is part of "reprepro" * Copyright (C) 2003,2004,2005,2006,2007,2008,2009 Bernhard R. Link * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301 USA */ #include #include #include #include #include #include "error.h" #include "mprintf.h" #include "strlist.h" #include "atoms.h" const char **atoms_architectures; const char **atoms_components; const char * const packagetypes[4] = { "!!NONE!!", "dsc", "deb", "udeb" }; const char **atoms_packagetypes = (const char **)&packagetypes; const char **atoms_commands; static int command_count; static const char * const types[4] = { "architecture", "component", "packagetype", "command" }; const char **atomtypes = (const char **)types; /* trivial implementation for now, perhaps make it more complicated later */ static struct strlist architectures, components; retvalue atoms_init(int count) { retvalue r; strlist_init(&architectures); strlist_init(&components); /* add a 0th entry to all, so 0 means uninitialized */ r = strlist_add_dup(&architectures, "!!NONE!!"); if (RET_WAS_ERROR(r)) return r; r = strlist_add_dup(&architectures, "source"); if (RET_WAS_ERROR(r)) return r; r = strlist_add_dup(&architectures, "all"); if (RET_WAS_ERROR(r)) return r; r = strlist_add_dup(&components, "!!NONE!!"); if (RET_WAS_ERROR(r)) return r; /* a fallback component to put things without a component in */ r = strlist_add_dup(&components, "strange"); if (RET_WAS_ERROR(r)) return r; atoms_components = (const char**)components.values; atoms_architectures = (const char**)architectures.values; command_count = count; if (command_count > 0) { atoms_commands = nzNEW(command_count + 1, const char*); if (FAILEDTOALLOC(atoms_commands)) return RET_ERROR_OOM; } return RET_OK; } retvalue architecture_intern(const char *value, architecture_t *atom_p) { retvalue r; int i; i = strlist_ofs(&architectures, value); if (i >= 0) { *atom_p = (architecture_t)i; return RET_OK; } i = architectures.count; r = strlist_add_dup(&architectures, value); atoms_architectures = (const char**)architectures.values; if (RET_IS_OK(r)) { *atom_p = (architecture_t)i; return RET_OK; } else return r; } retvalue component_intern(const char *value, component_t *atom_p) { retvalue r; int i; i = strlist_ofs(&components, value); if (i >= 0) { *atom_p = (component_t)i; return RET_OK; } i = components.count; r = strlist_add_dup(&components, value); atoms_components = (const char**)components.values; if (RET_IS_OK(r)) { *atom_p = (component_t)i; return RET_OK; } else return r; } architecture_t architecture_find(const char *value) { int i = strlist_ofs(&architectures, value); if (i < 0) return atom_unknown; else return (architecture_t)i; } architecture_t architecture_find_l(const char *value, size_t l) { architecture_t a; for (a = architectures.count - 1 ; a > 0 ; a--) { const char *name = atoms_architectures[a]; size_t len = strlen(name); if (len == l && memcmp(name, value, len) == 0) return a; } return atom_unknown; } // TODO: this might be called a lot, perhaps optimize it... component_t component_find_l(const char *value, size_t l) { component_t a; for (a = components.count - 1 ; a > 0 ; a--) { const char *name = atoms_components[a]; size_t len = strlen(name); if (len == l && memcmp(name, value, len) == 0) return a; } return atom_unknown; } component_t component_find(const char *value) { int i = strlist_ofs(&components, value); if (i < 0) return atom_unknown; else return (architecture_t)i; } packagetype_t packagetype_find(const char *value) { if (strcmp(value, "dsc") == 0) return pt_dsc; else if (strcmp(value, "deb") == 0) return pt_deb; else if (strcmp(value, "udeb") == 0) return pt_udeb; else return atom_unknown; } packagetype_t packagetype_find_l(const char *value, size_t len) { if (len == 3) { if (strncmp(value, "dsc", 3) == 0) return pt_dsc; else if (strncmp(value, "deb", 3) == 0) return pt_deb; } else if (len == 4 && strncmp(value, "udeb", 4) == 0) return pt_udeb; return atom_unknown; } static inline command_t command_find(const char *value) { command_t c; for (c = command_count ; c > 0 ; c--) { if (strcmp(atoms_commands[c], value) == 0) return c; } return atom_unknown; } atom_t atom_find(enum atom_type type, const char *value) { switch (type) { case at_packagetype: return packagetype_find(value); case at_architecture: return architecture_find(value); case at_component: return component_find(value); case at_command: return command_find(value); default: return atom_unknown; } } retvalue atom_intern(enum atom_type type, const char *value, atom_t *atom_p) { assert (type == at_architecture || type == at_component); switch (type) { case at_architecture: return architecture_intern(value, atom_p); case at_component: return component_intern(value, atom_p); default: return RET_ERROR; } } void atomlist_init(struct atomlist *list) { list->count = 0; list->size = 0; list->atoms = 0; } void atomlist_done(struct atomlist *list) { if (list->size > 0) { assert (list->atoms != 0); free(list->atoms); } /* reset atoms but not size, so reuse can be catched */ list->atoms = NULL; } /* add a atom uniquely (perhaps sorted), RET_NOTHING when already there */ retvalue atomlist_add_uniq(struct atomlist *list, atom_t atom) { int i; atom_t *n; assert (atom_defined(atom)); for (i = 0 ; i < list->count ; i++) { if (list->atoms[i] == atom) return RET_NOTHING; } if (list->size <= list->count) { n = realloc(list->atoms, (sizeof(atom_t))*(list->count + 8)); if (FAILEDTOALLOC(n)) return RET_ERROR_OOM; list->size = list->count + 8; list->atoms = n; } list->atoms[list->count++] = atom; return RET_OK; } retvalue atomlist_add(struct atomlist *list, atom_t atom) { atom_t *n; assert (atom_defined(atom)); if (list->size <= list->count) { n = realloc(list->atoms, (sizeof(atom_t))*(list->count + 8)); if (FAILEDTOALLOC(n)) return RET_ERROR_OOM; list->size = list->count + 8; list->atoms = n; } list->atoms[list->count++] = atom; return RET_OK; } /* replace the contents of dest with those from orig, which get emptied */ void atomlist_move(struct atomlist *dest, struct atomlist *orig) { dest->atoms = orig->atoms; dest->count = orig->count; dest->size = orig->size; /* reset atoms but not size, so reuse can be catched */ orig->atoms = NULL; } bool atomlist_hasexcept(const struct atomlist *list, atom_t atom) { int i; for (i = 0 ; i < list->count ; i++) { if (list->atoms[i] != atom) return true; } return false; } bool atomlist_in(const struct atomlist *list, atom_t atom) { int i; for (i = 0 ; i < list->count ; i++) { if (list->atoms[i] == atom) return true; } return false; } int atomlist_ofs(const struct atomlist *list, atom_t atom) { int i; for (i = 0 ; i < list->count ; i++) { if (list->atoms[i] == atom) return i; } return -1; } bool atomlist_subset(const struct atomlist *list, const struct atomlist *subset, atom_t *missing) { int i, j; for (j = 0 ; j < subset->count ; j++) { atom_t atom = subset->atoms[j]; for (i = 0 ; i < list->count ; i++) { if (list->atoms[i] == atom) break; } if (i >= list->count) { if (missing != NULL) *missing = atom; return false; } } return true; } retvalue atomlist_fprint(FILE *file, enum atom_type type, const struct atomlist *list) { const char **atoms = NULL; int c; atom_t *p; retvalue result; assert(list != NULL); assert(file != NULL); switch (type) { case at_architecture: atoms = atoms_architectures; break; case at_component: atoms = atoms_components; break; case at_packagetype: atoms = atoms_packagetypes; break; case at_command: atoms = atoms_commands; break; } assert(atoms != NULL); c = list->count; p = list->atoms; result = RET_OK; while (c > 0) { if (fputs(atoms[*(p++)], file) == EOF) result = RET_ERROR; if (--c > 0 && fputc(' ', file) == EOF) result = RET_ERROR; } return result; } component_t components_count(void) { return components.count; } retvalue atomlist_filllist(enum atom_type type, struct atomlist *list, char *string, const char **missing) { struct atomlist l; char *e; retvalue r; atom_t a; atomlist_init(&l); while (*string != '\0') { e = strchr(string, '|'); if (e == NULL) e = strchr(string, '\0'); else *(e++) = '\0'; a = atom_find(type, string); if (!atom_defined(a)) { atomlist_done(&l); *missing = string; return RET_NOTHING; } r = atomlist_add(&l, a); if (RET_WAS_ERROR(r)) { atomlist_done(&l); return r; } string = e; } atomlist_move(list, &l); return RET_OK; }