Add ability to generate dk, mouser and other partslists
authorKeith Packard <keithp@keithp.com>
Tue, 27 Oct 2015 02:22:08 +0000 (11:22 +0900)
committerKeith Packard <keithp@keithp.com>
Tue, 27 Oct 2015 02:22:08 +0000 (11:22 +0900)
This starts with partslist.csv and generates per-vendor lists. The DK
version is in the format needed to directly import into the DK BOM tool.

Signed-off-by: Keith Packard <keithp@keithp.com>
bin/partslist-vendor [new file with mode: 0755]
pcb.mk

diff --git a/bin/partslist-vendor b/bin/partslist-vendor
new file mode 100755 (executable)
index 0000000..9e25453
--- /dev/null
@@ -0,0 +1,162 @@
+#!/usr/bin/env nickle
+#
+# Convert CSV parts list into vendor import format
+#
+# Copyright © 2015 Keith Packard <keithp@keithp.com>, GPL v3+
+#
+
+bool   mfg_part = false;
+string[*]      vendors;
+string         vendor_list;
+string[*]      not_vendors;
+string         not_vendor_list;
+string input_name;
+string output_name;
+string         program;
+int    argi;
+int    lineno = 0;
+
+void fatal(string format, poly args ...)
+{
+       File::fprintf(stderr, format, args...);
+       exit(1);
+}
+
+string[*] read_line(file f) {
+       lineno++;
+       string  line = fgets(f);
+
+       return String::parse_csv(line);
+}
+
+string[*] header;
+
+string[*] required_elements = {
+       "quantity",
+       "vendor",
+       "vendor_part_number",
+       "mfg_part_number",
+       "device",
+       "value",
+};
+
+bool has_header_member(string member) {
+       for (int i = 0; i < dim(header); i++)
+               if (header[i] == member)
+                       return true;
+       return false;
+}
+
+bool has_vendor(string[*] vendors, string vendor) {
+       for (int i = 0; i < dim(vendors); i++)
+               if (vendors[i] == vendor)
+                       return true;
+       return false;
+}
+
+void read_header(file f) {
+       header = read_line(f);
+
+       for (int i = 0; i < dim(required_elements); i++)
+               if (!has_header_member(required_elements[i]))
+                       fatal("Missing header element \"%s\"\n", required_elements[i]);
+}
+
+string[string] read_entry(file f) {
+       string[*]       elements = read_line(f);
+       string[string]  entry = {};
+
+       if (dim(header) != dim(elements))
+               fatal("line %d: has %d instead of %d elements (%V)\n",
+                     lineno, dim(elements), dim(header), elements);
+
+       for (int i = 0; i < dim(header); i++) {
+               if (elements[i] == "")
+                       elements[i] = "unknown";
+               entry[header[i]] = elements[i];
+       }
+       return entry;
+}
+
+string part_number(string[string] entry)
+{
+       if (mfg_part)
+               return entry["mfg_part_number"];
+       else
+               return entry["vendor_part_number"];
+}
+
+void process_digikey(string[string] entry)
+{
+       printf("%s,%s,%s %s\n",
+              entry["quantity"],
+              part_number(entry),
+              entry["device"],
+              entry["value"]);
+}
+
+void process_other(string[string] entry) {
+       printf("%s,%s,%s,%s %s\n",
+              entry["vendor"],
+              entry["quantity"],
+              part_number(entry),
+              entry["device"],
+              entry["value"]);
+}
+
+void process_file(file f) {
+       read_header(f);
+       while (!File::end(f)) {
+               string[string] entry = read_entry(f);
+               string vendor = entry["vendor"];
+               if ((!is_uninit(&vendors) && has_vendor(vendors, vendor)) ||
+                   (!is_uninit(&not_vendors) && !has_vendor(not_vendors, vendor))) {
+                       switch (entry["vendor"]) {
+                       case "digikey":
+                               process_digikey(entry);
+                               break;
+                       default:
+                               process_other(entry);
+                               break;
+                       }
+               }
+       }
+}
+
+ParseArgs::argdesc argd = {
+       .args = {
+               { .var = { .arg_flag = &mfg_part },
+                 .abbr = 'm',
+                 .name = "mfg",
+                 .desc = "Display manufacturer part number"},
+               { .var = { .arg_string = &vendor_list },
+                 .abbr = 'v',
+                 .name = "vendor",
+                 .expr_name = "vendors",
+                 .desc = "Vendors to match"},
+               { .var = { .arg_string = &not_vendor_list },
+                 .abbr = 'n',
+                 .name = "not-vendor",
+                 .expr_name = "not-vendor",
+                 .desc = "Vendors to exclude"},
+       },
+       .unknown = &argi,
+};
+
+void main() {
+       ParseArgs::parseargs(&argd, &argv);
+       if (!is_uninit(&vendor_list))
+               vendors = String::parse_csv(vendor_list);
+
+       if (!is_uninit(&not_vendor_list))
+               not_vendors = String::parse_csv(not_vendor_list);
+
+       if (!is_uninit(&argi)) {
+               for (int i = argi; i < dim(argv); i++)
+                       twixt(file f = File::open(argv[i], "r"); File::close(f))
+                               process_file(f);
+       } else
+               process_file(stdin);
+}
+
+main();
diff --git a/pcb.mk b/pcb.mk
index 3ebd8f12739f16d7bbf8fcaaef7cdaae7d6af6d3..78264ec638500be25ba8301c0f42c773055ff868 100644 (file)
--- a/pcb.mk
+++ b/pcb.mk
@@ -28,15 +28,17 @@ partslist.csv:      $(SCHEMATICS) Makefile $(AM)/preferred-parts
        gnetlist -L $(SCHEME) -g partslistgag -o $(PROJECT).csvtmp $(SCHEMATICS)
        (head -n1 $(PROJECT).csvtmp; tail -n+2 $(PROJECT).csvtmp | sort -t \, -k 8 | awk -f $(AM)/bin/fillpartscsv ) > $@ && rm -f $(PROJECT).csvtmp
 
+partslist.dk: $(SCHEMATICS) Makefile $(AM)/preferred-parts partslist.csv
+       $(AM)/bin/partslist-vendor --vendor digikey partslist.csv > $@
 
-partslist.dk: $(SCHEMATICS) Makefile $(SCHEME)/gnet-partslist-bom.scm
-       gnetlist -L $(SCHEME) -g partslist-bom -Ovendor=digikey -o $@ $(SCHEMATICS)
-
-partslist-check.dk: $(SCHEMATICS) Makefile $(SCHEME)/gnet-partslist-mfg-bom.scm
-       gnetlist -L $(SCHEME) -g partslist-mfg-bom -Ovendor=digikey -o $@ $(SCHEMATICS)
+partslist-check.dk: $(SCHEMATICS) Makefile $(AM)/preferred-parts partslist.csv
+       $(AM)/bin/partslist-vendor --vendor digikey --mfg partslist.csv > $@
 
 partslist.mouser: $(SCHEMATICS) Makefile $(SCHEME)/gnet-partslist-bom.scm
-       gnetlist -L $(SCHEME) -g partslist-bom -Ovendor=mouser -o $@ $(SCHEMATICS)
+       $(AM)/bin/partslist-vendor --vendor mouser partslist.csv > $@
+
+partslist.other: $(SCHEMATICS) Makefile $(SCHEME)/gnet-partslist-bom.scm
+       $(AM)/bin/partslist-vendor --not-vendor digikey,mouser partslist.csv > $@
 
 pcb:   $(SCHEMATICS) project Makefile
        gsch2pcb project