atoms.c 9.21 KB
Newer Older
1
/*  This file is part of "reprepro"
2
 *  Copyright (C) 2003,2004,2005,2006,2007,2008,2009 Bernhard R. Link
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *  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 <config.h>

#include <assert.h>
#include <string.h>
20
#include <stdlib.h>
21 22 23 24 25 26 27 28
#include <stdio.h>
#include "error.h"
#include "mprintf.h"
#include "strlist.h"
#include "atoms.h"

const char **atoms_architectures;
const char **atoms_components;
29 30 31 32
const char * const packagetypes[4] = { "!!NONE!!", "dsc", "deb", "udeb" };
const char **atoms_packagetypes = (const char **)&packagetypes;
const char **atoms_commands;
static int command_count;
33 34 35
static const char * const types[4] = {
	"architecture", "component", "packagetype", "command"
};
36
const char **atomtypes = (const char **)types;
37 38 39 40

/* trivial implementation for now, perhaps make it more complicated later */
static struct strlist architectures, components;

41
retvalue atoms_init(int count) {
42 43 44 45
	retvalue r;
	strlist_init(&architectures);
	strlist_init(&components);

46 47 48
	/* add a 0th entry to all, so 0 means uninitialized */

	r = strlist_add_dup(&architectures, "!!NONE!!");
49
	if (RET_WAS_ERROR(r))
50 51
		return r;
	r = strlist_add_dup(&architectures, "source");
52
	if (RET_WAS_ERROR(r))
53
		return r;
54
	r = strlist_add_dup(&architectures, "all");
55
	if (RET_WAS_ERROR(r))
56 57
		return r;
	r = strlist_add_dup(&components, "!!NONE!!");
58
	if (RET_WAS_ERROR(r))
59 60 61
		return r;
	/* a fallback component to put things without a component in */
	r = strlist_add_dup(&components, "strange");
62
	if (RET_WAS_ERROR(r))
63 64 65
		return r;
	atoms_components = (const char**)components.values;
	atoms_architectures = (const char**)architectures.values;
66
	command_count = count;
67 68 69
	if (command_count > 0) {
		atoms_commands = nzNEW(command_count + 1, const char*);
		if (FAILEDTOALLOC(atoms_commands))
70 71
			return RET_ERROR_OOM;
	}
72 73 74 75 76 77 78 79
	return RET_OK;
}

retvalue architecture_intern(const char *value, architecture_t *atom_p) {
	retvalue r;
	int i;

	i = strlist_ofs(&architectures, value);
80
	if (i >= 0) {
81 82 83 84 85 86
		*atom_p = (architecture_t)i;
		return RET_OK;
	}
	i = architectures.count;
	r = strlist_add_dup(&architectures, value);
	atoms_architectures = (const char**)architectures.values;
87
	if (RET_IS_OK(r)) {
88 89 90 91 92 93 94 95 96 97
		*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);
98
	if (i >= 0) {
99 100 101 102 103 104
		*atom_p = (component_t)i;
		return RET_OK;
	}
	i = components.count;
	r = strlist_add_dup(&components, value);
	atoms_components = (const char**)components.values;
105
	if (RET_IS_OK(r)) {
106 107 108 109 110 111 112
		*atom_p = (component_t)i;
		return RET_OK;
	} else
		return r;
}

architecture_t architecture_find(const char *value) {
113
	int i = strlist_ofs(&architectures, value);
114
	if (i < 0)
115 116 117
		return atom_unknown;
	else
		return (architecture_t)i;
118
}
119 120 121 122

architecture_t architecture_find_l(const char *value, size_t l) {
	architecture_t a;

123
	for (a = architectures.count - 1 ; a > 0 ; a--) {
124 125 126
		const char *name = atoms_architectures[a];
		size_t len = strlen(name);

127
		if (len == l && memcmp(name, value, len) == 0)
128 129 130 131 132
			return a;
	}
	return atom_unknown;
}

133 134 135 136
// TODO: this might be called a lot, perhaps optimize it...
component_t component_find_l(const char *value, size_t l) {
	component_t a;

137
	for (a = components.count - 1 ; a > 0 ; a--) {
138 139 140
		const char *name = atoms_components[a];
		size_t len = strlen(name);

141
		if (len == l && memcmp(name, value, len) == 0)
142 143 144 145 146
			return a;
	}
	return atom_unknown;
}

147
component_t component_find(const char *value) {
148
	int i = strlist_ofs(&components, value);
149
	if (i < 0)
150 151 152
		return atom_unknown;
	else
		return (architecture_t)i;
153
}
154

155
packagetype_t packagetype_find(const char *value) {
156
	if (strcmp(value, "dsc") == 0)
157
		return pt_dsc;
158
	else if (strcmp(value, "deb") == 0)
159
		return pt_deb;
160
	else if (strcmp(value, "udeb") == 0)
161
		return pt_udeb;
162 163 164
	else
		return atom_unknown;
}
165 166

packagetype_t packagetype_find_l(const char *value, size_t len) {
167 168
	if (len == 3) {
		if (strncmp(value, "dsc", 3) == 0)
169
			return pt_dsc;
170
		else if (strncmp(value, "deb", 3) == 0)
171
			return pt_deb;
172
	} else if (len == 4 && strncmp(value, "udeb", 4) == 0)
173 174 175 176
		return pt_udeb;
	return atom_unknown;
}

177 178 179
static inline command_t command_find(const char *value) {
	command_t c;

180 181
	for (c = command_count ; c > 0 ; c--) {
		if (strcmp(atoms_commands[c], value) == 0)
182 183 184 185 186 187
			return c;
	}
	return atom_unknown;
}

atom_t atom_find(enum atom_type type, const char *value) {
188
	switch (type) {
189 190 191 192 193 194 195 196 197 198 199 200 201 202
		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) {
203 204
	assert (type == at_architecture || type == at_component);
	switch (type) {
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
		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) {
220 221
	if (list->size > 0) {
		assert (list->atoms != 0);
222 223
		free(list->atoms);
	}
224
	/* reset atoms but not size, so reuse can be caught */
225 226 227 228 229 230 231 232
	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;

233
	assert (atom_defined(atom));
234

235 236
	for (i = 0 ; i < list->count ; i++) {
		if (list->atoms[i] == atom)
237 238
			return RET_NOTHING;
	}
239 240 241
	if (list->size <= list->count) {
		n = realloc(list->atoms, (sizeof(atom_t))*(list->count + 8));
		if (FAILEDTOALLOC(n))
242 243 244 245 246 247 248 249 250 251 252
			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;

253
	assert (atom_defined(atom));
254

255 256 257
	if (list->size <= list->count) {
		n = realloc(list->atoms, (sizeof(atom_t))*(list->count + 8));
		if (FAILEDTOALLOC(n))
258 259 260 261 262 263 264 265 266 267 268 269 270
			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;
271
	/* reset atoms but not size, so reuse can be caught */
272 273 274
	orig->atoms = NULL;
}

275 276 277
bool atomlist_hasexcept(const struct atomlist *list, atom_t atom) {
	int i;

278 279
	for (i = 0 ; i < list->count ; i++) {
		if (list->atoms[i] != atom)
280 281 282 283 284
			return true;
	}
	return false;
}

285 286 287
bool atomlist_in(const struct atomlist *list, atom_t atom) {
	int i;

288 289
	for (i = 0 ; i < list->count ; i++) {
		if (list->atoms[i] == atom)
290 291 292 293 294 295 296
			return true;
	}
	return false;
}
int atomlist_ofs(const struct atomlist *list, atom_t atom) {
	int i;

297 298
	for (i = 0 ; i < list->count ; i++) {
		if (list->atoms[i] == atom)
299 300 301 302 303 304 305 306
			return i;
	}
	return -1;
}

bool atomlist_subset(const struct atomlist *list, const struct atomlist *subset, atom_t *missing) {
	int i, j;

307
	for (j = 0 ; j < subset->count ; j++) {
308 309
		atom_t atom = subset->atoms[j];

310 311
		for (i = 0 ; i < list->count ; i++) {
			if (list->atoms[i] == atom)
312 313
				break;
		}
314 315
		if (i >= list->count) {
			if (missing != NULL)
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
				*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);

332
	switch (type) {
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
		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;
351 352
	while (c > 0) {
		if (fputs(atoms[*(p++)], file) == EOF)
353
			result = RET_ERROR;
354
		if (--c > 0 && fputc(' ', file) == EOF)
355 356 357 358
			result = RET_ERROR;
	}
	return result;
}
359 360 361 362

component_t components_count(void) {
	return components.count;
}
363 364 365 366 367 368 369 370

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);
371
	while (*string != '\0') {
372
		e = strchr(string, '|');
373
		if (e == NULL)
374 375 376 377
			e = strchr(string, '\0');
		else
			*(e++) = '\0';
		a = atom_find(type, string);
378
		if (!atom_defined(a)) {
379 380 381 382 383
			atomlist_done(&l);
			*missing = string;
			return RET_NOTHING;
		}
		r = atomlist_add(&l, a);
384
		if (RET_WAS_ERROR(r)) {
385 386 387 388 389 390 391 392
			atomlist_done(&l);
			return r;
		}
		string = e;
	}
	atomlist_move(list, &l);
	return RET_OK;
}