1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2024-11-18 03:38:06 +02:00
eda-tools/b2/param.c

189 lines
3.4 KiB
C

/*
* param.c - Parameters and values
*
* 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 <stdlib.h>
#include <glib.h>
#include "util.h"
#include "lang.h"
#include "param.h"
static GTree *tree;
static int duplicate(const char *a, const struct equiv *b)
{
while (b) {
if (a == b->name)
return 1;
b = b->next;
}
return 0;
}
static void check_duplicates(const struct names *n)
{
const struct names *na, *nb;
const struct equiv *ea;
for (na = n; na; na = na->next) {
for (ea = na->equiv; ea; ea = ea->next) {
if (duplicate(ea->name, ea->next))
yyerrorf("duplicate name \"%s\"", ea->name);
for (nb = na->next; nb; nb = nb->next)
if (duplicate(ea->name, nb->equiv))
yyerrorf("duplicate name \"%s\"",
ea->name);
}
}
}
static gint comp(gconstpointer a, gconstpointer b)
{
return a == b ? 0 : a < b ? -1 : 1;
}
void register_nameset(const char *name, const struct names *set)
{
if (!tree)
tree = g_tree_new(comp);
if (g_tree_lookup(tree, name))
yyerrorf("duplicate name set \"%s\"", name);
check_duplicates(set);
g_tree_insert(tree, (void *) name, (void *) set);
}
const struct names *find_nameset(const char *name)
{
return tree ? g_tree_lookup(tree, name) : NULL;
}
struct lookup_data {
const struct names *first_name;
const char *name;
};
static gboolean rev_traverse(gpointer key, gpointer value, gpointer data)
{
struct lookup_data *d = data;
if (d->first_name == value) {
d->name = key;
return TRUE;
}
return FALSE;
}
const char *nameset_rev_lookup(const struct names *first_name)
{
struct lookup_data data = {
.first_name = first_name,
.name = NULL,
};
g_tree_foreach(tree, rev_traverse, (void *) &data);
return data.name;
}
#define MKOPS(type) \
const struct param_ops param_ops_##type = { \
.eval = eval_##type, \
.comp = comp_##type, \
.dump = dump_##type, \
}
MKOPS(name);
MKOPS(set);
MKOPS(abs);
MKOPS(rel);
/* ----- Parameters as general-purpose (string) variables ------------------ */
struct param *make_var(const char *name, enum relop op, const char *val)
{
struct param *var;
var = alloc_type(struct param);
var->u.name = unique(name);
var->op = op;
var->value.u.s = unique(val);
var->next = NULL;
return var;
}
const char *var_lookup(const struct param *vars, const char *name)
{
while (vars) {
if (vars->u.name == name)
return vars->value.u.s;
vars = vars->next;
}
return NULL;
}
/*
* The variables in list "a" have lower priority than those in list "b",
* i.e., a variable in "a" is only picked if there is no variable with the
* same name in "b".
*/
struct param *merge_vars(const struct param *a, const struct param *b)
{
const struct param *v;
struct param *res, **last = &res;
while (a) {
for (v = b; v; v = v->next)
if (a->u.name == v->u.name)
break;
if (!v) {
*last = alloc_type(struct param);
**last = *a;
last = &(*last)->next;
}
a = a->next;
}
for (v = b; v; v = v->next) {
*last = alloc_type(struct param);
**last = *v;
last = &(*last)->next;
}
*last = NULL;
return res;
}
void free_vars(struct param *vars)
{
struct param *next;
while (vars) {
next = vars->next;
free(vars);
vars = next;
}
}