diff --git a/b2/Makefile b/b2/Makefile index f1cc9f8..7f099b8 100644 --- a/b2/Makefile +++ b/b2/Makefile @@ -13,7 +13,7 @@ SHELL = /bin/bash CFLAGS = -g -Wall $(shell pkg-config --cflags glib-2.0) SLOPPY = -Wno-unused -Wno-implicit-function-declaration -OBJS = boom.o chr.o comp.o db.o dump.o eval.o param.o relop.o \ +OBJS = bom.o boom.o chr.o comp.o db.o dump.o eval.o param.o relop.o \ subex.o subst.o util.o \ vstring.o lex.yy.o y.tab.o LDLIBS = -lfl $(shell pkg-config --libs glib-2.0) diff --git a/b2/bom.c b/b2/bom.c new file mode 100644 index 0000000..371d773 --- /dev/null +++ b/b2/bom.c @@ -0,0 +1,71 @@ +/* + * 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 "util.h" +#include "lang.h" +#include "bom.h" + + +struct bom *bom = NULL; +int n_bom = 0; + + +struct bom *bom_parse_line(const char *s) +{ + struct bom *b; + const char *t; + char *f; + + bom = realloc(bom, sizeof(struct bom)*(n_bom+1)); + if (!bom) + abort(); + b = bom+n_bom++; + + if (*s++ != '|') + abort(); + while (*s == ' ' || *s == '\t') + s++; + for (t = s+1; *t && !isspace(*t); t++); + if (!*t) + yyerror("invalid BOM record (1)\n"); + b->ref = stralloc_n(s, t-s); + b->sym = NULL; + b->fields = NULL; + b->n_fields = 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; +} diff --git a/b2/bom.h b/b2/bom.h new file mode 100644 index 0000000..63d3f65 --- /dev/null +++ b/b2/bom.h @@ -0,0 +1,34 @@ +/* + * bom.h - 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. + */ + + +#ifndef BOM_H +#define BOM_H + +#include "param.h" + + +struct bom { + const char *ref; /* component reference */ + const char *sym; /* symbol */ + const char **fields; /* fields */ + int n_fields; + const struct param *vars; /* variables (before conversion) */ + const struct bom *next; +}; + +extern struct bom *bom; +extern int n_bom; + + +struct bom *bom_parse_line(const char *line); + +#endif /* !BOM_H */ diff --git a/b2/boom.c b/b2/boom.c index 3968aad..02153f0 100644 --- a/b2/boom.c +++ b/b2/boom.c @@ -82,6 +82,7 @@ static void usage(const char *name) " -x currency exchange\n" " -p providers\n" " -s substitutions\n" +" -b KiCad eeschema BOM\n" " -q var=value ... run substitutions with the specified inputs\n" " -Q var=value ... run substitutions and then do parametric search\n" , name); @@ -107,6 +108,8 @@ int main(int argc, char **argv) process = parse_providers; else if (!strcmp(argv[i], "-s")) process = parse_substitutions; + else if (!strcmp(argv[i], "-b")) + process = parse_kicad_bom; else if (!strcmp(argv[i], "-q")) process = add_var; else if (!strcmp(argv[i], "-Q")) { diff --git a/b2/lang.h b/b2/lang.h index 00ac8eb..78f0f04 100644 --- a/b2/lang.h +++ b/b2/lang.h @@ -28,6 +28,7 @@ void parse_inventory(const char *name); void parse_currencies(const char *name); void parse_providers(const char *name); void parse_substitutions(const char *name); +void parse_kicad_bom(const char *name); void yywarnf(const char *fmt, ...); void __attribute__((noreturn)) yyerrorf(const char *fmt, ...); diff --git a/b2/lang.l b/b2/lang.l index 14052f0..7941d54 100644 --- a/b2/lang.l +++ b/b2/lang.l @@ -18,6 +18,7 @@ #include "util.h" #include "param.h" #include "chr.h" +#include "bom.h" #include "y.tab.h" #include "lang.h" @@ -25,8 +26,9 @@ extern int yyparse(void); static int start_token; -static int expose_nl; -static int pattern; +static int expose_nl; /* 0: ignore \n; 1: return TOK_NL */ +static int pattern; /* 0: = relops are normal; 1: relops switch to PAT */ +static int hash; /* number of hashes seen in BOM mode */ static const char *file_name; static int lineno; @@ -107,6 +109,7 @@ ID [-_A-Za-z0-9()+./] PAT "\\"[^\t\n]|[^ \t\n\\] %s ID PAT +%x BOM %% @@ -126,6 +129,16 @@ PAT "\\"[^\t\n]|[^ \t\n\\] yylval.s = stralloc(yytext); return PATTERN; } +"eeschema \("[^\n]* { hash = 0; + return BOM_EESCHEMA; } +"|"[^\n]* { if (hash == 1) + bom_parse_line(yytext); } +"#End Cmp" { YY_FLUSH_BUFFER; + return 0; } +#[^\n]* hash++; +\n lineno++; +. return *yytext; + [<>=] { if (pattern) BEGIN(PAT); return *yytext; } @@ -183,3 +196,13 @@ void __attribute__((noreturn)) yyerror(const char *s) fprintf(stderr, "%s:%d: %s\n", file_name, lineno, s); exit(1); } + + +/* Define parse_kicad_bom here, so that we have access to BOM and INITIAL */ + +void parse_kicad_bom(const char *name) +{ + BEGIN(BOM); + do_parse(name, START_BOM, 1, 0); + BEGIN(INITIAL); +} diff --git a/b2/lang.y b/b2/lang.y index 721a3d5..1055726 100644 --- a/b2/lang.y +++ b/b2/lang.y @@ -101,7 +101,8 @@ static struct subst *parse_jump(const char *keyword, const char *target) %token START_HIERARCHY START_CHAR START_INVENTORY -%token START_EXCHANGE START_PROVIDERS START_SUBST +%token START_EXCHANGE START_PROVIDERS START_SUBST START_BOM +%token BOM_EESCHEMA %token TOK_LE TOK_GE TOK_NL %token WORD PATTERN @@ -138,6 +139,7 @@ all: { substitutions = $2; } + | START_BOM bom ; @@ -653,3 +655,17 @@ opt_block: $$ = $2; } ; + + +/* ----- KiCad BOM (from eeschema) ----------------------------------------- */ + + +bom: + BOM_EESCHEMA + /* + * The KiCad BOM syntax is quite alien, so we just check the + * overall structure here, leave extracting the lines with + * actual content to the lexer, and do all the detail work in + * bom.c + */ + ;