/* * 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 #include #include #include #include #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"); }