Root/b2/chr.c

1/*
2 * chr.h - Part characteristics
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 <assert.h>
14
15#include "util.h"
16#include "lang.h"
17#include "relop.h"
18#include "param.h"
19#include "chr.h"
20
21
22const struct format *field_find(const char *name, const struct field *tail)
23{
24    while (tail) {
25        if (tail->name == name)
26            return tail->fmt;
27        tail = tail->prev;
28    }
29    return NULL;
30}
31
32
33/* ----- Construction of the field hierarchy ------------------------------- */
34
35
36struct field *new_field(const char *name, const struct format *fmt,
37    const struct field *prev)
38{
39    struct field *field;
40
41    if (field_find(name, prev))
42        yyerrorf("duplicate field \"%s\"", name);
43    field = alloc_type(struct field);
44    field->name = name;
45    field->fmt = fmt;
46    field->sel = NULL;
47    field->any.fields = NULL;
48    field->any.rules = NULL;
49    field->next = NULL;
50    field->prev = NULL;
51    return field;
52}
53
54
55struct selector *new_selector(void)
56{
57    struct selector *sel;
58
59    sel = alloc_type(struct selector);
60    sel->cond = NULL;
61    sel->act.fields = NULL;
62    sel->act.rules = NULL;
63    sel->next = NULL;
64    return sel;
65}
66
67
68struct condition *new_condition(enum relop relop, const char *word)
69{
70    struct condition *cond;
71
72    cond = alloc_type(struct condition);
73    cond->value.u.s = word;
74    cond->relop = relop;
75    cond->next = NULL;
76    return cond;
77}
78
79
80static int comp(const void *a, enum relop op, const void *b, const void *user)
81{
82    return compare(user, a, op, b);
83}
84
85
86static void check_unreachable(const struct field *f,
87    const struct condition *c1, const struct condition *c2)
88{
89    if (relop_unreachable(c1->relop, c2->relop, &c1->value, &c2->value,
90        comp, f->fmt))
91        yywarn("unreachable condition");
92}
93
94
95void field_finalize(struct field *field)
96{
97    const struct selector *sel, *s2;
98    struct condition *cond;
99    const struct condition *c2;
100
101    for (sel = field->sel; sel; sel = sel->next)
102        for (cond = sel->cond; cond; cond = cond->next)
103            if (!evaluate(field->fmt, cond->value.u.s,
104                &cond->value))
105                yyerrorf("invalid value in selection");
106                /* @@@ indicate exact location */
107    for (sel = field->sel; sel; sel = sel->next)
108        for (cond = sel->cond; cond; cond = cond->next) {
109            for (c2 = cond->next; c2; c2 = c2->next)
110                check_unreachable(field, cond, c2);
111            for (s2 = sel->next; s2; s2 = s2->next)
112                for (c2 = s2->cond; c2; c2 = c2->next)
113                    check_unreachable(field, cond, c2);
114        }
115}
116
117
118/* ----- Dumping ----------------------------------------------------------- */
119
120
121#define INDENT 8
122
123
124static void dump_rules(FILE *file, const struct field *field, int level);
125
126
127static void dump_set_decl(FILE *file, const struct names *first_name)
128{
129    const char *name;
130
131    name = nameset_rev_lookup(first_name);
132    assert(name);
133    fprintf(file, "<%s>", name);
134}
135
136
137static void dump_field_decl(FILE *file, const struct field *field)
138{
139    if (field->fmt->ops == &param_ops_name)
140        fprintf(file, "*");
141    else if (field->fmt->ops == &param_ops_set)
142        dump_set_decl(file, field->fmt->u.set);
143    else if (field->fmt->ops == &param_ops_abs)
144        fprintf(file, "#%s",
145            field->fmt->u.abs ? field->fmt->u.abs : "#");
146    else if (field->fmt->ops == &param_ops_rel)
147        fprintf(file, "%%%s",
148            field->fmt->u.rel->u.abs ? field->fmt->u.rel->u.abs : "#");
149    else
150        abort();
151}
152
153
154static void dump_action(FILE *file, const struct action *act, int level)
155{
156    if (act->fields) {
157        fprintf(file, " ");
158        fields_dump(file, act->fields);
159    }
160    fprintf(file, "\n");
161    dump_rules(file, act->rules, level+1);
162}
163
164
165static void dump_one_rule(FILE *file, const struct field *field, int level)
166{
167    const struct selector *sel;
168    const struct condition *cond;
169
170    fprintf(file, "%*s%s=", level*INDENT, "", field->name);
171    dump_field_decl(file, field);
172
173    fprintf(file, " {\n");
174
175    for (sel = field->sel; sel; sel = sel->next) {
176        fprintf(file, "%*s", level*INDENT+INDENT/2, "");
177        for (cond = sel->cond; cond; cond = cond->next) {
178            if (cond != sel->cond)
179                fprintf(file, "|");
180            if (cond->relop != rel_eq)
181                dump_relop(file, cond->relop);
182            dump_param(file, field->fmt, &cond->value);
183        }
184        fprintf(file, ":");
185        dump_action(file, &sel->act, level);
186    }
187    if (field->any.fields || field->any.rules) {
188        fprintf(file, "%*s*:", level*INDENT+INDENT/2, "");
189        dump_action(file, &field->any, level);
190    }
191    fprintf(file, "%*s}\n", level*INDENT, "");
192}
193
194
195void fields_dump(FILE *file, const struct field *fields)
196{
197    const struct field *f;
198
199    if (!fields)
200        return;
201    fprintf(file, "{ ");
202    for (f = fields; f; f = f->next) {
203        fprintf(file, "%s%s=", f == fields ? "" : " ", f->name);
204        dump_field_decl(file, f);
205    }
206    fprintf(file, " }");
207}
208
209
210static void dump_rules(FILE *file, const struct field *field, int level)
211{
212    while (field) {
213        dump_one_rule(file, field, level);
214        field = field->next;
215    }
216}
217
218
219void rules_dump(FILE *file, const struct field *field)
220{
221    dump_rules(file, field, 0);
222}
223

Archive Download this file

Branches:
master



interactive