2012-05-23 22:05:24 +03:00
|
|
|
/*
|
|
|
|
* bom.c - BOM data
|
|
|
|
*
|
|
|
|
* 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>
|
2012-05-24 00:26:27 +03:00
|
|
|
#include <stdio.h>
|
2012-05-23 22:31:54 +03:00
|
|
|
#include <string.h>
|
2012-05-23 22:05:24 +03:00
|
|
|
#include <ctype.h>
|
2012-05-24 00:13:26 +03:00
|
|
|
#include <assert.h>
|
2012-05-23 22:05:24 +03:00
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
#include "lang.h"
|
2012-05-24 00:13:26 +03:00
|
|
|
#include "relop.h"
|
|
|
|
#include "param.h"
|
|
|
|
#include "subst.h"
|
|
|
|
#include "subex.h"
|
2012-05-23 22:05:24 +03:00
|
|
|
#include "bom.h"
|
|
|
|
|
|
|
|
|
2012-05-24 00:26:27 +03:00
|
|
|
#define INDENT 4
|
|
|
|
|
|
|
|
|
2012-05-23 22:05:24 +03:00
|
|
|
struct bom *bom = NULL;
|
|
|
|
int n_bom = 0;
|
|
|
|
|
|
|
|
|
2012-05-23 22:31:54 +03:00
|
|
|
static struct bom *bom_find(const char *ref)
|
|
|
|
{
|
|
|
|
struct bom *b;
|
|
|
|
|
|
|
|
for (b = bom; b != bom+n_bom; b++)
|
|
|
|
if (b->ref == ref)
|
|
|
|
return b;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-23 22:05:24 +03:00
|
|
|
struct bom *bom_parse_line(const char *s)
|
|
|
|
{
|
|
|
|
struct bom *b;
|
2012-05-23 22:31:54 +03:00
|
|
|
const char *ref, *t;
|
2012-05-23 22:05:24 +03:00
|
|
|
char *f;
|
|
|
|
|
|
|
|
if (*s++ != '|')
|
|
|
|
abort();
|
|
|
|
while (*s == ' ' || *s == '\t')
|
|
|
|
s++;
|
|
|
|
for (t = s+1; *t && !isspace(*t); t++);
|
|
|
|
if (!*t)
|
2012-05-23 23:26:35 +03:00
|
|
|
yyerror("invalid BOM record");
|
2012-05-23 22:31:54 +03:00
|
|
|
|
|
|
|
ref = unique_n(s, t-s);
|
|
|
|
if (bom_find(ref))
|
|
|
|
yyerrorf("duplicate component reference %s", ref);
|
|
|
|
|
|
|
|
bom = realloc(bom, sizeof(struct bom)*(n_bom+1));
|
|
|
|
if (!bom)
|
|
|
|
abort();
|
|
|
|
b = bom+n_bom++;
|
|
|
|
|
|
|
|
b->ref = ref;
|
2012-05-23 22:05:24 +03:00
|
|
|
b->sym = NULL;
|
|
|
|
b->fields = NULL;
|
|
|
|
b->n_fields = 0;
|
2012-05-24 00:13:26 +03:00
|
|
|
b->vars = 0;
|
2012-05-23 22:05:24 +03:00
|
|
|
|
|
|
|
for (s = t; *t && *t != '\n'; s = t+1) {
|
|
|
|
while (*s == ' ' || *s == '\t')
|
|
|
|
s++;
|
|
|
|
if (*s == ';' || *s == '\n') {
|
|
|
|
f = NULL;
|
|
|
|
t = s;
|
|
|
|
} else {
|
|
|
|
for (t = s+1; *t && *t != ';' && !isspace(*t); t++);
|
|
|
|
f = stralloc_n(s, t-s);
|
|
|
|
while (*t == ' ' || *t == '\t')
|
|
|
|
t++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* VAL, FP, F1 ... */
|
|
|
|
b->fields =
|
|
|
|
realloc(b->fields, sizeof(const char *)*(b->n_fields+1));
|
|
|
|
if (!b->fields)
|
|
|
|
abort();
|
|
|
|
b->fields[b->n_fields] = f ? unique(f) : unique("");
|
|
|
|
b->n_fields++;
|
|
|
|
free(f);
|
|
|
|
}
|
|
|
|
return b;
|
|
|
|
}
|
2012-05-23 23:26:35 +03:00
|
|
|
|
|
|
|
|
|
|
|
void bom_set_sym(const char *ref, const char *sym)
|
|
|
|
{
|
|
|
|
struct bom *b;
|
|
|
|
|
|
|
|
b = bom_find(ref);
|
|
|
|
if (!b)
|
|
|
|
yyerrorf("cannot find component reference \"%s\"", ref);
|
|
|
|
if (b->sym)
|
|
|
|
yyerrorf("symbol is already set in \"%s\"", ref);
|
|
|
|
b->sym = sym;
|
|
|
|
}
|
2012-05-24 00:13:26 +03:00
|
|
|
|
|
|
|
|
|
|
|
static void add_var(struct param ***last, struct param *var)
|
|
|
|
{
|
|
|
|
**last = var;
|
|
|
|
*last = &var->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int bom_subst(struct bom *b, const struct subst *sub)
|
|
|
|
{
|
|
|
|
char tmp[4];
|
|
|
|
struct param *vars = NULL, **last = &vars;
|
|
|
|
struct param *out;
|
|
|
|
int i, res;
|
|
|
|
|
|
|
|
/* must be last, for removal with n_bom-- to work */
|
|
|
|
assert(b == bom+n_bom-1);
|
|
|
|
|
|
|
|
/* set input variables */
|
|
|
|
add_var(&last, make_var("REF", rel_eq, b->ref));
|
|
|
|
if (b->n_fields && *b->fields[0])
|
|
|
|
add_var(&last, make_var("VAL", rel_eq, b->fields[0]));
|
|
|
|
if (b->n_fields > 1 && *b->fields[1])
|
|
|
|
add_var(&last, make_var("FP", rel_eq, b->fields[1]));
|
|
|
|
else
|
|
|
|
yywarnf("\"%s\" has no footprint", b->ref);
|
|
|
|
for (i = 2; i != b->n_fields; i++)
|
|
|
|
if (*b->fields[i]) {
|
|
|
|
sprintf(tmp, "F%d", i-1);
|
|
|
|
add_var(&last, make_var(tmp, rel_eq, b->fields[i]));
|
|
|
|
}
|
|
|
|
if (b->sym)
|
|
|
|
add_var(&last, make_var("SYM", rel_eq, b->sym));
|
|
|
|
|
|
|
|
/* run substitutions */
|
|
|
|
res = substitute(sub, vars, &out);
|
2012-05-24 06:09:20 +03:00
|
|
|
if (res) {
|
|
|
|
b->vars = merge_vars(vars, out);
|
|
|
|
free_vars(out);
|
|
|
|
} else {
|
2012-05-24 00:13:26 +03:00
|
|
|
n_bom--;
|
2012-05-24 06:09:20 +03:00
|
|
|
}
|
|
|
|
free_vars(vars);
|
2012-05-24 00:13:26 +03:00
|
|
|
return res;
|
|
|
|
}
|
2012-05-24 00:26:27 +03:00
|
|
|
|
|
|
|
|
|
|
|
void bom_dump(FILE *file, const struct bom *b)
|
|
|
|
{
|
|
|
|
const char **f;
|
|
|
|
const struct param *var;
|
|
|
|
|
|
|
|
fprintf(file, "%s (%s)\n", b->ref, b->sym ? b->sym : "?");
|
|
|
|
fprintf(file, "%*s", INDENT, "");
|
|
|
|
for (f = b->fields; f != b->fields+b->n_fields; f++)
|
|
|
|
fprintf(file, "%s%s", f == b->fields ? "" : " ",
|
|
|
|
**f ? *f : "-");
|
|
|
|
fprintf(file, "\n");
|
|
|
|
if (!b->vars)
|
|
|
|
return;
|
|
|
|
fprintf(file, "%*s", INDENT, "");
|
|
|
|
for (var = b->vars; var; var = var->next) {
|
|
|
|
fprintf(file, "%s%s", var == b->vars ? "" : " ", var->u.name);
|
|
|
|
dump_relop(file, var->op);
|
|
|
|
fprintf(file, "%s", var->value.u.s);
|
|
|
|
}
|
|
|
|
fprintf(file, "\n");
|
|
|
|
}
|