Root/b2/param.c

1/*
2 * param.c - Parameters and values
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12
13#include <stdlib.h>
14#include <glib.h>
15
16#include "util.h"
17#include "lang.h"
18#include "param.h"
19
20
21static GTree *tree;
22
23
24static int duplicate(const char *a, const struct equiv *b)
25{
26    while (b) {
27        if (a == b->name)
28            return 1;
29        b = b->next;
30    }
31    return 0;
32}
33
34
35static void check_duplicates(const struct names *n)
36{
37    const struct names *na, *nb;
38    const struct equiv *ea;
39
40    for (na = n; na; na = na->next) {
41        for (ea = na->equiv; ea; ea = ea->next) {
42            if (duplicate(ea->name, ea->next))
43                yyerrorf("duplicate name \"%s\"", ea->name);
44            for (nb = na->next; nb; nb = nb->next)
45                if (duplicate(ea->name, nb->equiv))
46                    yyerrorf("duplicate name \"%s\"",
47                        ea->name);
48        }
49    }
50}
51
52
53static gint comp(gconstpointer a, gconstpointer b)
54{
55    return a == b ? 0 : a < b ? -1 : 1;
56}
57
58
59void register_nameset(const char *name, const struct names *set)
60{
61    if (!tree)
62        tree = g_tree_new(comp);
63    if (g_tree_lookup(tree, name))
64        yyerrorf("duplicate name set \"%s\"", name);
65    check_duplicates(set);
66    g_tree_insert(tree, (void *) name, (void *) set);
67}
68
69
70const struct names *find_nameset(const char *name)
71{
72    return tree ? g_tree_lookup(tree, name) : NULL;
73}
74
75
76struct lookup_data {
77    const struct names *first_name;
78    const char *name;
79};
80
81
82static gboolean rev_traverse(gpointer key, gpointer value, gpointer data)
83{
84    struct lookup_data *d = data;
85
86    if (d->first_name == value) {
87        d->name = key;
88        return TRUE;
89    }
90    return FALSE;
91}
92
93
94const char *nameset_rev_lookup(const struct names *first_name)
95{
96    struct lookup_data data = {
97        .first_name = first_name,
98        .name = NULL,
99    };
100
101    g_tree_foreach(tree, rev_traverse, (void *) &data);
102    return data.name;
103}
104
105
106#define MKOPS(type) \
107    const struct param_ops param_ops_##type = { \
108        .eval = eval_##type, \
109        .comp = comp_##type, \
110        .dump = dump_##type, \
111    }
112
113
114MKOPS(name);
115MKOPS(set);
116MKOPS(abs);
117MKOPS(rel);
118
119
120/* ----- Parameters as general-purpose (string) variables ------------------ */
121
122
123struct param *make_var(const char *name, enum relop op, const char *val)
124{
125    struct param *var;
126
127    var = alloc_type(struct param);
128    var->u.name = unique(name);
129    var->op = op;
130    var->value.u.s = unique(val);
131    var->next = NULL;
132    return var;
133}
134
135
136const char *var_lookup(const struct param *vars, const char *name)
137{
138    while (vars) {
139        if (vars->u.name == name)
140            return vars->value.u.s;
141        vars = vars->next;
142    }
143    return NULL;
144}
145
146
147/*
148 * The variables in list "a" have lower priority than those in list "b",
149 * i.e., a variable in "a" is only picked if there is no variable with the
150 * same name in "b".
151 */
152
153struct param *merge_vars(const struct param *a, const struct param *b)
154{
155    const struct param *v;
156    struct param *res, **last = &res;
157
158    while (a) {
159        for (v = b; v; v = v->next)
160            if (a->u.name == v->u.name)
161                break;
162        if (!v) {
163            *last = alloc_type(struct param);
164            **last = *a;
165            last = &(*last)->next;
166        }
167        a = a->next;
168    }
169    for (v = b; v; v = v->next) {
170        *last = alloc_type(struct param);
171        **last = *v;
172        last = &(*last)->next;
173    }
174    *last = NULL;
175    return res;
176}
177
178
179void free_vars(struct param *vars)
180{
181    struct param *next;
182
183    while (vars) {
184        next = vars->next;
185        free(vars);
186        vars = next;
187    }
188}
189

Archive Download this file

Branches:
master



interactive