Root/b2/bom.c

1/*
2 * bom.c - BOM data
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 <stdio.h>
15#include <string.h>
16#include <ctype.h>
17#include <assert.h>
18
19#include "util.h"
20#include "lang.h"
21#include "relop.h"
22#include "param.h"
23#include "subst.h"
24#include "subex.h"
25#include "bom.h"
26
27
28#define INDENT 4
29
30
31struct bom *bom = NULL;
32int n_bom = 0;
33
34
35static struct bom *bom_find(const char *ref)
36{
37    struct bom *b;
38
39    for (b = bom; b != bom+n_bom; b++)
40        if (b->ref == ref)
41            return b;
42    return NULL;
43}
44
45
46struct bom *bom_parse_line(const char *s)
47{
48    struct bom *b;
49    const char *ref, *t;
50    char *f;
51
52    if (*s++ != '|')
53        abort();
54    while (*s == ' ' || *s == '\t')
55        s++;
56    for (t = s+1; *t && !isspace(*t); t++);
57    if (!*t)
58        yyerror("invalid BOM record");
59
60    ref = unique_n(s, t-s);
61    if (bom_find(ref))
62        yyerrorf("duplicate component reference %s", ref);
63
64    bom = realloc(bom, sizeof(struct bom)*(n_bom+1));
65    if (!bom)
66        abort();
67    b = bom+n_bom++;
68
69    b->ref = ref;
70    b->sym = NULL;
71    b->fields = NULL;
72    b->n_fields = 0;
73    b->vars = 0;
74
75    for (s = t; *t && *t != '\n'; s = t+1) {
76        while (*s == ' ' || *s == '\t')
77            s++;
78        if (*s == ';' || *s == '\n') {
79            f = NULL;
80            t = s;
81        } else {
82            for (t = s+1; *t && *t != ';' && !isspace(*t); t++);
83            f = stralloc_n(s, t-s);
84            while (*t == ' ' || *t == '\t')
85                t++;
86        }
87
88        /* VAL, FP, F1 ... */
89        b->fields =
90            realloc(b->fields, sizeof(const char *)*(b->n_fields+1));
91        if (!b->fields)
92            abort();
93        b->fields[b->n_fields] = f ? unique(f) : unique("");
94        b->n_fields++;
95        free(f);
96    }
97    return b;
98}
99
100
101void bom_set_sym(const char *ref, const char *sym)
102{
103    struct bom *b;
104
105    b = bom_find(ref);
106    if (!b)
107        yyerrorf("cannot find component reference \"%s\"", ref);
108    if (b->sym)
109        yyerrorf("symbol is already set in \"%s\"", ref);
110    b->sym = sym;
111}
112
113
114static void add_var(struct param ***last, struct param *var)
115{
116    **last = var;
117    *last = &var->next;
118}
119
120
121int bom_subst(struct bom *b, const struct subst *sub)
122{
123    char tmp[4];
124    struct param *vars = NULL, **last = &vars;
125    struct param *out;
126    int i, res;
127
128    /* must be last, for removal with n_bom-- to work */
129    assert(b == bom+n_bom-1);
130
131    /* set input variables */
132    add_var(&last, make_var("REF", rel_eq, b->ref));
133    if (b->n_fields && *b->fields[0])
134        add_var(&last, make_var("VAL", rel_eq, b->fields[0]));
135    if (b->n_fields > 1 && *b->fields[1])
136        add_var(&last, make_var("FP", rel_eq, b->fields[1]));
137    else
138        yywarnf("\"%s\" has no footprint", b->ref);
139    for (i = 2; i != b->n_fields; i++)
140        if (*b->fields[i]) {
141            sprintf(tmp, "F%d", i-1);
142            add_var(&last, make_var(tmp, rel_eq, b->fields[i]));
143        }
144    if (b->sym)
145        add_var(&last, make_var("SYM", rel_eq, b->sym));
146
147    /* run substitutions */
148    res = substitute(sub, vars, &out);
149    if (res) {
150        b->vars = merge_vars(vars, out);
151        free_vars(out);
152    } else {
153        n_bom--;
154    }
155    free_vars(vars);
156    return res;
157}
158
159
160void bom_dump(FILE *file, const struct bom *b)
161{
162    const char **f;
163    const struct param *var;
164
165    fprintf(file, "%s (%s)\n", b->ref, b->sym ? b->sym : "?");
166    fprintf(file, "%*s", INDENT, "");
167    for (f = b->fields; f != b->fields+b->n_fields; f++)
168        fprintf(file, "%s%s", f == b->fields ? "" : " ",
169            **f ? *f : "-");
170    fprintf(file, "\n");
171    if (!b->vars)
172        return;
173    fprintf(file, "%*s", INDENT, "");
174    for (var = b->vars; var; var = var->next) {
175        fprintf(file, "%s%s", var == b->vars ? "" : " ", var->u.name);
176        dump_relop(file, var->op);
177        fprintf(file, "%s", var->value.u.s);
178    }
179    fprintf(file, "\n");
180}
181

Archive Download this file

Branches:
master



interactive