/* * db.c - Parts database * * Copyright 2012 by Werner Almesberger * * This program 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 2 of the License, or * (at your option) any later version. */ #include #include #include "util.h" #include "lang.h" #include "chr.h" #include "db.h" static GTree *tree = NULL; static gint comp(gconstpointer a, gconstpointer b) { const struct part *pa = a; const struct part *pb = b; /* * Just subtracting the pointers may produce values outside the * range of gint values. */ return pa->domain == pb->domain ? pa->name < pb->name ? -1 : pa->name > pb->name ? 1 : 0 : pa->domain < pb->domain ? -1 : 1; } struct part *part_lookup(const char *domain, const char *name) { struct part part = { .domain = domain, .name = name, }; if (!tree) return NULL; return g_tree_lookup(tree, &part); } struct part *part_add(const char *domain, const char *name) { struct part part = { .domain = domain, .name = name, }; struct part *p; if (!tree) tree = g_tree_new(comp); p = g_tree_lookup(tree, &part); if (!p) { p = alloc_type(struct part); p->stock = NULL; p->next = p->prev = p; g_tree_insert(tree, p, p); } return p; } void part_alias(struct part *a, struct part *b) { struct part *tmp, *tmp2; tmp = a->next; a->next = b; b->prev->next = tmp; tmp2 = b->prev; b->prev = a; tmp->prev = tmp2; } static void convert_params(struct param **params, const struct field *f, struct param ***res) { struct param **p, *prm; const struct selector *sel; const struct condition *cond; while (f) { for (p = params; *p; p = &(*p)->next) if ((*p)->u.name == f->name) break; if (!*p) { f = f->next; continue; } /* remove from list */ prm = *p; *p = prm->next; /* convert parameter */ prm->u.field = f; if (!evaluate(f->fmt, prm->value.u.name, &prm->value)) yyerrorf("invalid value for %s", f->name); /* add to result list */ **res = prm; *res = &prm->next; prm->next = NULL; /* process selections */ for (sel = f->sel; sel; sel = sel->next) { for (cond = sel->cond; cond; cond = cond->next) if (compare(f->fmt, &prm->value, cond->relop, &cond->value)) break; if (cond) { convert_params(params, sel->act.fields, res); convert_params(params, sel->act.rules, res); break; } } if (!sel) { convert_params(params, f->any.fields, res); convert_params(params, f->any.rules, res); } f = f->next; } } void part_finalize(struct part *part, const struct field *field) { struct param *param = part->param; struct param **res = &part->param; struct param *next; part->param = NULL; convert_params(¶m, field, &res); while (param) { yywarnf("extra parameter: %s", param->u.name); next = param->next; free(param); param = next; } }