1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2024-11-25 23:21:54 +02:00
eda-tools/b2/bom.c

181 lines
3.6 KiB
C

/*
* 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>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "util.h"
#include "lang.h"
#include "relop.h"
#include "param.h"
#include "subst.h"
#include "subex.h"
#include "bom.h"
#define INDENT 4
struct bom *bom = NULL;
int n_bom = 0;
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;
}
struct bom *bom_parse_line(const char *s)
{
struct bom *b;
const char *ref, *t;
char *f;
if (*s++ != '|')
abort();
while (*s == ' ' || *s == '\t')
s++;
for (t = s+1; *t && !isspace(*t); t++);
if (!*t)
yyerror("invalid BOM record");
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;
b->sym = NULL;
b->fields = NULL;
b->n_fields = 0;
b->vars = 0;
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;
}
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;
}
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);
if (res) {
b->vars = merge_vars(vars, out);
free_vars(out);
} else {
n_bom--;
}
free_vars(vars);
return res;
}
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");
}