Index: trunk/scconfig/plugins.h =================================================================== --- trunk/scconfig/plugins.h (revision 38022) +++ trunk/scconfig/plugins.h (revision 38023) @@ -90,8 +90,7 @@ plugin_header("\nExport plugins:\n") plugin_def("cam", "cam/job based export", sbuildin, 1) plugin_def("ddraft", "2D drafting helper", sbuildin, 1) -plugin_def("export_bom2", "Bill of Materials export", sbuildin, 1) -plugin_def("export_bom", "bom pcb_exporter", sbuildin, 1) +plugin_def("export_bom", "Bill of Materials export", sbuildin, 1) plugin_def("export_c_draw", "export drawing in C code", sdisable, 0) plugin_def("export_debug", "export debug draw", sdisable, 0) plugin_def("export_dxf", "DXF pcb_exporter", sbuildin, 1) Index: trunk/src/Makefile.dep =================================================================== --- trunk/src/Makefile.dep (revision 38022) +++ trunk/src/Makefile.dep (revision 38023) @@ -494,21 +494,12 @@ layer_grp.h rats_patch.h board.h data.h crosshair.h route.h buffer.h \ obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ ../src_3rd/libminuid/libminuid.h ht_subc.h obj_pstk_list.h obj_pstk.h \ - vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h hid_cam.h -../src_plugins/export_bom2/bom2.o: ../src_plugins/export_bom2/bom2.c \ - ../config.h conf_core.h globalconst.h build_run.h board.h vtroutestyle.h \ - attrib.h global_typedefs.h layer.h obj_common.h flag.h data_parent.h \ - obj_arc_list.h obj_arc.h obj_line_list.h obj_line.h obj_poly_list.h \ - obj_poly.h obj_text_list.h obj_text.h font.h obj_gfx_list.h obj_gfx.h \ - layer_grp.h rats_patch.h board.h data.h crosshair.h route.h buffer.h \ - obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ - ../src_3rd/libminuid/libminuid.h ht_subc.h obj_pstk_list.h obj_pstk.h \ vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h data_it.h data.h \ - ../src_plugins/export_bom2/bom2_conf.h hid_cam.h \ - ../src_plugins/export_bom2/conf_internal.c \ - ../src_plugins/export_bom2/../../src_3rd/rnd_inclib/lib_bom/lib_bom.h \ - ../src_plugins/export_bom2/../../src_3rd/rnd_inclib/lib_bom/lib_bom.c \ - ../src_plugins/export_bom2/bom2_conf_fields.h + ../src_plugins/export_bom/bom_conf.h hid_cam.h \ + ../src_plugins/export_bom/conf_internal.c \ + ../src_plugins/export_bom/../../src_3rd/rnd_inclib/lib_bom/lib_bom.h \ + ../src_plugins/export_bom/../../src_3rd/rnd_inclib/lib_bom/lib_bom.c \ + ../src_plugins/export_bom/bom_conf_fields.h ../src_plugins/export_c_draw/export_c_draw.o: \ ../src_plugins/export_c_draw/export_c_draw.c ../config.h conf_core.h \ globalconst.h board.h vtroutestyle.h attrib.h global_typedefs.h layer.h \ Index: trunk/src_3rd/rnd_inclib/lib_bom/lib_bom.c =================================================================== --- trunk/src_3rd/rnd_inclib/lib_bom/lib_bom.c (revision 38022) +++ trunk/src_3rd/rnd_inclib/lib_bom/lib_bom.c (revision 38023) @@ -37,7 +37,7 @@ int len; if (sep == NULL) { - rnd_message(RND_MSG_ERROR, "export_bom2: ignoring invalid template name (missing period): '%s'\n", li->name); + rnd_message(RND_MSG_ERROR, "export_bom: ignoring invalid template name (missing period): '%s'\n", li->name); continue; } if (strcmp(sep+1, "name") != 0) @@ -44,7 +44,7 @@ continue; len = sep - li->name; if (len > sizeof(id)-1) { - rnd_message(RND_MSG_ERROR, "export_bom2: ignoring invalid template name (too long): '%s'\n", li->name); + rnd_message(RND_MSG_ERROR, "export_bom: ignoring invalid template name (too long): '%s'\n", li->name); continue; } memcpy(id, li->name, len); @@ -151,7 +151,7 @@ end = strpbrk(*input, "?|%"); len = end - *input; if (len >= sizeof(aname) - 1) { - rnd_message(RND_MSG_ERROR, "bom2 tempalte error: attribute name '%s' too long\n", *input); + rnd_message(RND_MSG_ERROR, "bom tempalte error: attribute name '%s' too long\n", *input); return 1; } memcpy(aname, *input, len); @@ -161,7 +161,7 @@ end = strchr(*input, '%'); len = end - *input; if (len >= sizeof(unk_buf) - 1) { - rnd_message(RND_MSG_ERROR, "bom2 tempalte error: elem atribute '|unknown' field '%s' too long\n", *input); + rnd_message(RND_MSG_ERROR, "bom tempalte error: elem atribute '|unknown' field '%s' too long\n", *input); return 1; } memcpy(unk_buf, *input, len); @@ -175,7 +175,7 @@ end = strchr(*input, '%'); len = end - *input; if (len >= sizeof(unk_buf) - 1) { - rnd_message(RND_MSG_ERROR, "bom2 tempalte error: elem atribute trenary field '%s' too long\n", *input); + rnd_message(RND_MSG_ERROR, "bom tempalte error: elem atribute trenary field '%s' too long\n", *input); return 1; } Index: trunk/src_plugins/export_bom2/bom2.c =================================================================== --- trunk/src_plugins/export_bom2/bom2.c (revision 38022) +++ trunk/src_plugins/export_bom2/bom2.c (nonexistent) @@ -1,229 +0,0 @@ -#include "config.h" -#include "conf_core.h" -#include - -#include - -#include "build_run.h" -#include "board.h" -#include "data.h" -#include "data_it.h" -#include -#include -#include -#include "bom2_conf.h" - -#include -#include -#include -#include "hid_cam.h" -#include - -#include "../src_plugins/export_bom2/conf_internal.c" - -#define CONF_FN "export_bom2.conf" - -conf_bom2_t conf_bom2; - -const char *bom2_cookie = "BOM2 HID"; - -/* Maximum length of a template name (in the config file, in the enum) */ -#define MAX_TEMP_NAME_LEN 128 - - -/* This one can not be const because format enumeration is loaded run-time */ -static rnd_export_opt_t bom2_options[] = { - {"bom2file", "Name of the BoM output file", - RND_HATT_STRING, 0, 0, {0, 0, 0}, 0}, -#define HA_bom2file 0 - - {"format", "file format (template)", - RND_HATT_ENUM, 0, 0, {0, 0, 0}, NULL}, -#define HA_format 1 - - {"cam", "CAM instruction", - RND_HATT_STRING, 0, 0, {0, 0, 0}, 0}, -#define HA_cam 2 -}; - -#define NUM_OPTIONS (sizeof(bom2_options)/sizeof(bom2_options[0])) - -static rnd_hid_attr_val_t bom2_values[NUM_OPTIONS]; - -static const char *bom2_filename; - -typedef pcb_subc_t bom_obj_t; -#include "../../src_3rd/rnd_inclib/lib_bom/lib_bom.h" - -static const rnd_export_opt_t *bom2_get_export_options(rnd_hid_t *hid, int *n, rnd_design_t *dsg, void *appspec) -{ - const char *val = bom2_values[HA_bom2file].str; - - /* load all formats from the config */ - bom_build_fmts(&conf_bom2.plugins.export_bom2.templates); - - if (bom_fmt_names.used == 0) { - rnd_message(RND_MSG_ERROR, "export_bom2: can not set up export options: no template available\n"); - return NULL; - } - - bom2_options[HA_format].enumerations = (const char **)bom_fmt_names.array; - - /* set default filename */ - if ((dsg != NULL) && ((val == NULL) || (*val == '\0'))) - pcb_derive_default_filename(dsg->loadname, &bom2_values[HA_bom2file], ".bom2"); - - if (n) - *n = NUM_OPTIONS; - return bom2_options; -} - -static const char *subst_user(bom_subst_ctx_t *ctx, const char *key) -{ - if (strcmp(key, "author") == 0) return pcb_author(); - if (strcmp(key, "title") == 0) return RND_UNKNOWN(PCB->hidlib.name); - if (strncmp(key, "subc.", 5) == 0) { - key += 5; - - if (strncmp(key, "a.", 2) == 0) return pcb_attribute_get(&ctx->obj->Attributes, key+2); - else if (strcmp(key, "name") == 0) return ctx->name; - if (strcmp(key, "prefix") == 0) { - static char tmp[256]; /* this is safe: caller will make a copy right after we return */ - char *o = tmp; - const char *t; - int n = 0; - - for(t = ctx->name; isalpha(*t) && (n < sizeof(tmp)-1); t++,n++,o++) - *o = *t; - *o = '\0'; - return tmp; - } - } - - return NULL; -} - -static int print_bom(const bom_template_t *templ) -{ - FILE *f; - bom_subst_ctx_t ctx = {0}; - - f = rnd_fopen_askovr(&PCB->hidlib, bom2_filename, "w", NULL); - if (f == NULL) { - rnd_message(RND_MSG_ERROR, "Cannot open file %s for writing\n", bom2_filename); - return 1; - } - - bom_print_begin(&ctx, f, templ); - - /* For each subcircuit calculate an ID and count recurring IDs in a hash table and an array (for sorting) */ - PCB_SUBC_LOOP(PCB->Data); - { - const char *refdes = RND_UNKNOWN(pcb_attribute_get(&subc->Attributes, "refdes")); - bom_print_add(&ctx, subc, refdes); - } - PCB_END_LOOP; - - bom_print_all(&ctx); - bom_print_end(&ctx); - fclose(f); - - return 0; -} - -static void bom2_do_export(rnd_hid_t *hid, rnd_design_t *design, rnd_hid_attr_val_t *options, void *appspec) -{ - bom_template_t templ = {0}; - char **tid; - pcb_cam_t cam; - - if (!options) { - bom2_get_export_options(hid, 0, design, appspec); - options = bom2_values; - } - - bom2_filename = options[HA_bom2file].str; - if (!bom2_filename) - bom2_filename = "pcb-rnd-out.bom2"; - - pcb_cam_begin_nolayer(PCB, &cam, NULL, options[HA_cam].str, &bom2_filename); - - tid = vts0_get(&bom_fmt_ids, options[HA_format].lng, 0); - if ((tid == NULL) || (*tid == NULL)) { - rnd_message(RND_MSG_ERROR, "export_bom2: invalid template selected\n"); - return; - } - - bom_init_template(&templ, &conf_bom2.plugins.export_bom2.templates, *tid); - print_bom(&templ); - pcb_cam_end(&cam); -} - -static int bom2_usage(rnd_hid_t *hid, const char *topic) -{ - int n; - fprintf(stderr, "\nBOM exporter command line arguments:\n\n"); - bom2_get_export_options(hid, &n, NULL, NULL); - rnd_hid_usage(bom2_options, sizeof(bom2_options) / sizeof(bom2_options[0])); - fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x bom2 [bom2_options] foo.pcb\n\n"); - return 0; -} - -static int bom2_parse_arguments(rnd_hid_t *hid, int *argc, char ***argv) -{ - rnd_export_register_opts2(hid, bom2_options, sizeof(bom2_options) / sizeof(bom2_options[0]), bom2_cookie, 0); - - /* when called from the export() command this field may be uninitialized yet */ - if (bom2_options[HA_format].enumerations == NULL) - bom2_get_export_options(hid, NULL, NULL, NULL); - - return rnd_hid_parse_command_line(argc, argv); -} - -#include "../../src_3rd/rnd_inclib/lib_bom/lib_bom.c" - -rnd_hid_t bom2_hid; - -int pplg_check_ver_export_bom2(int ver_needed) { return 0; } - -void pplg_uninit_export_bom2(void) -{ - rnd_export_remove_opts_by_cookie(bom2_cookie); - rnd_conf_unreg_file(CONF_FN, export_bom2_conf_internal); - rnd_conf_unreg_fields("plugins/export_bom2/"); - bom_fmt_uninit(); - rnd_hid_remove_hid(&bom2_hid); -} - -int pplg_init_export_bom2(void) -{ - RND_API_CHK_VER; - - rnd_conf_reg_file(CONF_FN, export_bom2_conf_internal); - - memset(&bom2_hid, 0, sizeof(rnd_hid_t)); - -#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ - rnd_conf_reg_field(conf_bom2, field,isarray,type_name,cpath,cname,desc,flags); -#include "bom2_conf_fields.h" - - rnd_hid_nogui_init(&bom2_hid); - - bom2_hid.struct_size = sizeof(rnd_hid_t); - bom2_hid.name = "bom2"; - bom2_hid.description = "Exports a BoM (Bill of Material) using templates"; - bom2_hid.exporter = 1; - - bom2_hid.get_export_options = bom2_get_export_options; - bom2_hid.do_export = bom2_do_export; - bom2_hid.parse_arguments = bom2_parse_arguments; - bom2_hid.argument_array = bom2_values; - - bom2_hid.usage = bom2_usage; - - rnd_hid_register_hid(&bom2_hid); - rnd_hid_load_defaults(&bom2_hid, bom2_options, NUM_OPTIONS); - - bom_fmt_init(); - return 0; -} Index: trunk/src_plugins/export_bom2/export_bom2.pup =================================================================== --- trunk/src_plugins/export_bom2/export_bom2.pup (revision 38022) +++ trunk/src_plugins/export_bom2/export_bom2.pup (nonexistent) @@ -1,9 +0,0 @@ -$class export -$short Bill of Materials export -$long Export BoM (Bill of Materials) with configurable templates -$state works -$fmt-native no -$fmt-feature-w bom (Bill of Materials, text, templated) -$package export -default buildin -autoload 1 Index: trunk/src_plugins/export_bom2/export_bom2.conf =================================================================== --- trunk/src_plugins/export_bom2/export_bom2.conf (revision 38022) +++ trunk/src_plugins/export_bom2/export_bom2.conf (nonexistent) @@ -1,25 +0,0 @@ -### conf file header (compacted) -li:pcb-rnd-conf-v1 { ha:overwrite { ha:plugins { ha:export_bom2 { li:templates { - -### tempalates - -# classic gEDA/PCB BoM ######################################################### -geda.name = gEDA/PCB BoM -geda.header = {# $Id$ -# PcbBOM Version 1.0 -# Date: %UTC% -# Author: %author% -# Title: %title% - PCB BOM -# Quantity, Description, Value, RefDes -# -------------------------------------------- -} -geda.sort_id = {%subc.prefix%__%subc.a.footprint%__%subc.a.value%} -geda.item = {%count%,"%escape.subc.a.footprint%","%escape.subc.a.value|(unknown)%",%names% -} -geda.footer = {} -geda.needs_escape = {"} -geda.escape = {\\} - - -### conf file footer (compacted) -} } } } } Index: trunk/src_plugins/export_bom2/Plug.tmpasm =================================================================== --- trunk/src_plugins/export_bom2/Plug.tmpasm (revision 38022) +++ trunk/src_plugins/export_bom2/Plug.tmpasm (nonexistent) @@ -1,11 +0,0 @@ -put /local/rnd/mod {export_bom2} -put /local/rnd/mod/OBJS [@ $(PLUGDIR)/export_bom2/bom2.o @] -put /local/rnd/mod/CONF {$(PLUGDIR)/export_bom2/bom2_conf.h} -put /local/rnd/mod/CONFFILE {export_bom2.conf} -put /local/rnd/mod/CONFVAR {export_bom2_conf_internal} - -switch /local/module/export_bom2/controls - case {buildin} include /local/pcb/tmpasm/buildin; end; - case {plugin} include /local/pcb/tmpasm/plugin; end; - case {disable} include /local/pcb/tmpasm/disable; end; -end Index: trunk/src_plugins/export_bom2/bom2_conf.h =================================================================== --- trunk/src_plugins/export_bom2/bom2_conf.h (revision 38022) +++ trunk/src_plugins/export_bom2/bom2_conf.h (nonexistent) @@ -1,14 +0,0 @@ -#ifndef PCB_BOM2_CONF_H -#define PCB_BOM2_CONF_H - -#include - -typedef struct { - const struct { - const struct { - RND_CFT_LIST templates; - } export_bom2; - } plugins; -} conf_bom2_t; - -#endif Index: trunk/src_plugins/export_bom2/Makefile =================================================================== --- trunk/src_plugins/export_bom2/Makefile (revision 38022) +++ trunk/src_plugins/export_bom2/Makefile (nonexistent) @@ -1,5 +0,0 @@ -all: - cd ../../src && $(MAKE) mod_export_bom2 - -clean: - rm *.o *.so 2>/dev/null ; true Index: trunk/src_plugins/export_bom/Plug.tmpasm =================================================================== --- trunk/src_plugins/export_bom/Plug.tmpasm (revision 38022) +++ trunk/src_plugins/export_bom/Plug.tmpasm (revision 38023) @@ -1,5 +1,8 @@ put /local/rnd/mod {export_bom} put /local/rnd/mod/OBJS [@ $(PLUGDIR)/export_bom/bom.o @] +put /local/rnd/mod/CONF {$(PLUGDIR)/export_bom/bom_conf.h} +put /local/rnd/mod/CONFFILE {export_bom.conf} +put /local/rnd/mod/CONFVAR {export_bom_conf_internal} switch /local/module/export_bom/controls case {buildin} include /local/pcb/tmpasm/buildin; end; Index: trunk/src_plugins/export_bom/bom.c =================================================================== --- trunk/src_plugins/export_bom/bom.c (revision 38022) +++ trunk/src_plugins/export_bom/bom.c (revision 38023) @@ -1,25 +1,17 @@ -/* Print bill of materials file is which can be used for checking stock - and purchasing needed materials. */ - #include "config.h" #include "conf_core.h" +#include -#include -#include #include -#include -#include -#include - #include "build_run.h" #include "board.h" #include "data.h" +#include "data_it.h" #include -#include #include -#include #include +#include "bom_conf.h" #include #include @@ -27,24 +19,31 @@ #include "hid_cam.h" #include -const char *bom_cookie = "bom HID"; +#include "../src_plugins/export_bom/conf_internal.c" -static const rnd_export_opt_t bom_options[] = { -/* %start-doc options "8 BOM Creation" -@ftable @code -@item --bomfile -Name of the BOM output file. -@end ftable -%end-doc -*/ - {"bomfile", "Name of the BOM output file", +#define CONF_FN "export_bom.conf" + +conf_bom_t conf_bom; + +const char *bom_cookie = "BOM2 HID"; + +/* Maximum length of a template name (in the config file, in the enum) */ +#define MAX_TEMP_NAME_LEN 128 + + +/* This one can not be const because format enumeration is loaded run-time */ +static rnd_export_opt_t bom_options[] = { + {"bomfile", "Name of the BoM output file", RND_HATT_STRING, 0, 0, {0, 0, 0}, 0}, #define HA_bomfile 0 + {"format", "file format (template)", + RND_HATT_ENUM, 0, 0, {0, 0, 0}, NULL}, +#define HA_format 1 + {"cam", "CAM instruction", RND_HATT_STRING, 0, 0, {0, 0, 0}, 0}, -#define HA_cam 1 - +#define HA_cam 2 }; #define NUM_OPTIONS (sizeof(bom_options)/sizeof(bom_options[0])) @@ -53,17 +52,24 @@ static const char *bom_filename; -typedef struct pcb_bom_list_s { - char *descr; - char *value; - int num; - vts0_t refdes; - struct pcb_bom_list_s *next; -} pcb_bom_list_t; +typedef pcb_subc_t bom_obj_t; +#include "../../src_3rd/rnd_inclib/lib_bom/lib_bom.h" static const rnd_export_opt_t *bom_get_export_options(rnd_hid_t *hid, int *n, rnd_design_t *dsg, void *appspec) { const char *val = bom_values[HA_bomfile].str; + + /* load all formats from the config */ + bom_build_fmts(&conf_bom.plugins.export_bom.templates); + + if (bom_fmt_names.used == 0) { + rnd_message(RND_MSG_ERROR, "export_bom: can not set up export options: no template available\n"); + return NULL; + } + + bom_options[HA_format].enumerations = (const char **)bom_fmt_names.array; + + /* set default filename */ if ((dsg != NULL) && ((val == NULL) || (*val == '\0'))) pcb_derive_default_filename(dsg->loadname, &bom_values[HA_bomfile], ".bom"); @@ -72,160 +78,63 @@ return bom_options; } -char *pcb_bom_clean_str(const char *in) +static const char *subst_user(bom_subst_ctx_t *ctx, const char *key) { - char *out; - int i; + if (strcmp(key, "author") == 0) return pcb_author(); + if (strcmp(key, "title") == 0) return RND_UNKNOWN(PCB->hidlib.name); + if (strncmp(key, "subc.", 5) == 0) { + key += 5; - if ((out = malloc((strlen(in) + 1) * sizeof(char))) == NULL) { - fprintf(stderr, "Error: pcb_bom_clean_str() malloc() failed\n"); - exit(1); - } + if (strncmp(key, "a.", 2) == 0) return pcb_attribute_get(&ctx->obj->Attributes, key+2); + else if (strcmp(key, "name") == 0) return ctx->name; + if (strcmp(key, "prefix") == 0) { + static char tmp[256]; /* this is safe: caller will make a copy right after we return */ + char *o = tmp; + const char *t; + int n = 0; - /* copy over in to out with some character conversions. - Go all the way to then end to get the terminating \0 */ - for (i = 0; i <= strlen(in); i++) { - switch (in[i]) { - case '"': - out[i] = '\''; - break; - default: - out[i] = in[i]; + for(t = ctx->name; isalpha(*t) && (n < sizeof(tmp)-1); t++,n++,o++) + *o = *t; + *o = '\0'; + return tmp; } } - return out; + return NULL; } - -static pcb_bom_list_t *bom_insert(char *refdes, char *descr, char *value, pcb_bom_list_t * bom) +static int print_bom(const bom_template_t *templ) { - pcb_bom_list_t *newlist, *cur, *prev = NULL; + FILE *f; + bom_subst_ctx_t ctx = {0}; - if (bom == NULL) { - /* this is the first subcircuit so automatically create an entry */ - if ((newlist = malloc(sizeof(pcb_bom_list_t))) == NULL) { - fprintf(stderr, "malloc() failed in bom_insert()\n"); - exit(1); - } - - newlist->next = NULL; - newlist->descr = rnd_strdup(descr); - newlist->value = rnd_strdup(value); - newlist->num = 1; - vts0_init(&newlist->refdes); - vts0_append(&newlist->refdes, rnd_strdup(refdes)); - return newlist; + f = rnd_fopen_askovr(&PCB->hidlib, bom_filename, "w", NULL); + if (f == NULL) { + rnd_message(RND_MSG_ERROR, "Cannot open file %s for writing\n", bom_filename); + return 1; } - /* search and see if we already have used one of these components */ - cur = bom; - while(cur != NULL) { - if ((RND_NSTRCMP(descr, cur->descr) == 0) && (RND_NSTRCMP(value, cur->value) == 0)) { - cur->num++; - vts0_append(&cur->refdes, rnd_strdup(refdes)); - break; - } - prev = cur; - cur = cur->next; - } + bom_print_begin(&ctx, f, templ); - if (cur == NULL) { - if ((newlist = malloc(sizeof(pcb_bom_list_t))) == NULL) { - fprintf(stderr, "malloc() failed in bom_insert()\n"); - exit(1); - } - - prev->next = newlist; - - newlist->next = NULL; - newlist->descr = rnd_strdup(descr); - newlist->value = rnd_strdup(value); - newlist->num = 1; - vts0_init(&newlist->refdes); - vts0_append(&newlist->refdes, rnd_strdup(refdes)); - } - - return bom; -} - -/* If fp is not NULL then print out the bill of materials contained in - bom. Either way, free all memory which has been allocated for bom. */ -static void print_and_free(FILE * fp, pcb_bom_list_t *bom) -{ - pcb_bom_list_t *lastb; - char *descr, *value; - long n; - - while (bom != NULL) { - if (fp) { - descr = pcb_bom_clean_str(bom->descr); - value = pcb_bom_clean_str(bom->value); - fprintf(fp, "%d,\"%s\",\"%s\",", bom->num, descr, value); - free(descr); - free(value); - } - - for(n = 0; n < bom->refdes.used; n++) { - char *refdes = bom->refdes.array[n]; - if (fp) - fprintf(fp, "%s ", refdes); - free(refdes); - } - vts0_uninit(&bom->refdes); - if (fp) - fprintf(fp, "\n"); - lastb = bom; - bom = bom->next; - free(lastb); - } -} - -static int bom_print(void) -{ - char utcTime[64]; - FILE *fp; - pcb_bom_list_t *bom = NULL; - - rnd_print_utc(utcTime, sizeof(utcTime), 0); - + /* For each subcircuit calculate an ID and count recurring IDs in a hash table and an array (for sorting) */ PCB_SUBC_LOOP(PCB->Data); { - if (subc->extobj != NULL) continue; - - /* insert this component into the bill of materials list */ - bom = bom_insert((char *) RND_UNKNOWN(subc->refdes), - (char *) RND_UNKNOWN(pcb_subc_name(subc, "bom::footprint")), - (char *) RND_UNKNOWN(pcb_attribute_get(&subc->Attributes, "value")), - bom); + const char *refdes = RND_UNKNOWN(pcb_attribute_get(&subc->Attributes, "refdes")); + bom_print_add(&ctx, subc, refdes); } PCB_END_LOOP; - fp = rnd_fopen_askovr(&PCB->hidlib, bom_filename, "w", NULL); - if (!fp) { - rnd_message(RND_MSG_ERROR, "Cannot open file %s for writing\n", bom_filename); - print_and_free(NULL, bom); - return 1; - } + bom_print_all(&ctx); + bom_print_end(&ctx); + fclose(f); - fprintf(fp, "# $Id"); - fprintf(fp, "$\n"); - fprintf(fp, "# PcbBOM Version 1.0\n"); - fprintf(fp, "# Date: %s\n", utcTime); - fprintf(fp, "# Author: %s\n", pcb_author()); - fprintf(fp, "# Title: %s - PCB BOM\n", RND_UNKNOWN(PCB->hidlib.name)); - fprintf(fp, "# Quantity, Description, Value, RefDes\n"); - fprintf(fp, "# --------------------------------------------\n"); - - print_and_free(fp, bom); - - fclose(fp); - return 0; } static void bom_do_export(rnd_hid_t *hid, rnd_design_t *design, rnd_hid_attr_val_t *options, void *appspec) { + bom_template_t templ = {0}; + char **tid; pcb_cam_t cam; if (!options) { @@ -239,25 +148,40 @@ pcb_cam_begin_nolayer(PCB, &cam, NULL, options[HA_cam].str, &bom_filename); - bom_print(); + tid = vts0_get(&bom_fmt_ids, options[HA_format].lng, 0); + if ((tid == NULL) || (*tid == NULL)) { + rnd_message(RND_MSG_ERROR, "export_bom: invalid template selected\n"); + return; + } + + bom_init_template(&templ, &conf_bom.plugins.export_bom.templates, *tid); + print_bom(&templ); pcb_cam_end(&cam); } static int bom_usage(rnd_hid_t *hid, const char *topic) { - fprintf(stderr, "\nbom exporter command line arguments:\n\n"); + int n; + fprintf(stderr, "\nBOM exporter command line arguments:\n\n"); + bom_get_export_options(hid, &n, NULL, NULL); rnd_hid_usage(bom_options, sizeof(bom_options) / sizeof(bom_options[0])); fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x bom [bom_options] foo.pcb\n\n"); return 0; } - static int bom_parse_arguments(rnd_hid_t *hid, int *argc, char ***argv) { rnd_export_register_opts2(hid, bom_options, sizeof(bom_options) / sizeof(bom_options[0]), bom_cookie, 0); + + /* when called from the export() command this field may be uninitialized yet */ + if (bom_options[HA_format].enumerations == NULL) + bom_get_export_options(hid, NULL, NULL, NULL); + return rnd_hid_parse_command_line(argc, argv); } +#include "../../src_3rd/rnd_inclib/lib_bom/lib_bom.c" + rnd_hid_t bom_hid; int pplg_check_ver_export_bom(int ver_needed) { return 0; } @@ -265,6 +189,9 @@ void pplg_uninit_export_bom(void) { rnd_export_remove_opts_by_cookie(bom_cookie); + rnd_conf_unreg_file(CONF_FN, export_bom_conf_internal); + rnd_conf_unreg_fields("plugins/export_bom/"); + bom_fmt_uninit(); rnd_hid_remove_hid(&bom_hid); } @@ -272,13 +199,19 @@ { RND_API_CHK_VER; + rnd_conf_reg_file(CONF_FN, export_bom_conf_internal); + memset(&bom_hid, 0, sizeof(rnd_hid_t)); +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + rnd_conf_reg_field(conf_bom, field,isarray,type_name,cpath,cname,desc,flags); +#include "bom_conf_fields.h" + rnd_hid_nogui_init(&bom_hid); bom_hid.struct_size = sizeof(rnd_hid_t); bom_hid.name = "bom"; - bom_hid.description = "Exports a Bill of Materials"; + bom_hid.description = "Exports a BoM (Bill of Material) using templates"; bom_hid.exporter = 1; bom_hid.get_export_options = bom_get_export_options; @@ -291,5 +224,6 @@ rnd_hid_register_hid(&bom_hid); rnd_hid_load_defaults(&bom_hid, bom_options, NUM_OPTIONS); + bom_fmt_init(); return 0; } Index: trunk/src_plugins/export_bom/bom_conf.h =================================================================== --- trunk/src_plugins/export_bom/bom_conf.h (nonexistent) +++ trunk/src_plugins/export_bom/bom_conf.h (revision 38023) @@ -0,0 +1,14 @@ +#ifndef PCB_BOM_CONF_H +#define PCB_BOM_CONF_H + +#include + +typedef struct { + const struct { + const struct { + RND_CFT_LIST templates; + } export_bom; + } plugins; +} conf_bom_t; + +#endif Index: trunk/src_plugins/export_bom/export_bom.conf =================================================================== --- trunk/src_plugins/export_bom/export_bom.conf (nonexistent) +++ trunk/src_plugins/export_bom/export_bom.conf (revision 38023) @@ -0,0 +1,25 @@ +### conf file header (compacted) +li:pcb-rnd-conf-v1 { ha:overwrite { ha:plugins { ha:export_bom { li:templates { + +### tempalates + +# classic gEDA/PCB BoM ######################################################### +geda.name = gEDA/PCB BoM +geda.header = {# $Id$ +# PcbBOM Version 1.0 +# Date: %UTC% +# Author: %author% +# Title: %title% - PCB BOM +# Quantity, Description, Value, RefDes +# -------------------------------------------- +} +geda.sort_id = {%subc.prefix%__%subc.a.footprint%__%subc.a.value%} +geda.item = {%count%,"%escape.subc.a.footprint%","%escape.subc.a.value|(unknown)%",%names% +} +geda.footer = {} +geda.needs_escape = {"} +geda.escape = {\\} + + +### conf file footer (compacted) +} } } } } Index: trunk/src_plugins/export_bom/export_bom.pup =================================================================== --- trunk/src_plugins/export_bom/export_bom.pup (revision 38022) +++ trunk/src_plugins/export_bom/export_bom.pup (revision 38023) @@ -1,9 +1,9 @@ $class export -$short bom pcb_exporter -$long Export bom (Bill of Materials) +$short Bill of Materials export +$long Export BoM (Bill of Materials) with configurable templates $state works $fmt-native no -$fmt-feature-w bom (Bill of Materials, text) +$fmt-feature-w bom (Bill of Materials, text, templated) $package export default buildin autoload 1 Index: trunk/src_plugins/export_xy/xy.c =================================================================== --- trunk/src_plugins/export_xy/xy.c (revision 38022) +++ trunk/src_plugins/export_xy/xy.c (revision 38023) @@ -40,8 +40,6 @@ conf_xy_t conf_xy; -extern char *pcb_bom_clean_str(const char *in); - const char *xy_cookie = "XY HID"; /* Maximum length of a template name (in the config file, in the enum) */ @@ -88,6 +86,31 @@ static rnd_hid_attr_val_t xy_values[NUM_OPTIONS]; +static char *pcb_bom_clean_str(const char *in) +{ + char *out; + int i; + + if ((out = malloc((strlen(in) + 1) * sizeof(char))) == NULL) { + fprintf(stderr, "Error: pcb_bom_clean_str() malloc() failed\n"); + exit(1); + } + + /* copy over in to out with some character conversions. + Go all the way to then end to get the terminating \0 */ + for (i = 0; i <= strlen(in); i++) { + switch (in[i]) { + case '"': + out[i] = '\''; + break; + default: + out[i] = in[i]; + } + } + + return out; +} + static const char *xy_filename; static const rnd_unit_t *xy_unit; vts0_t fmt_names; /* array of const char * long name of each format, pointing into the conf database */ Index: trunk/src_plugins/plugins_ALL.tmpasm =================================================================== --- trunk/src_plugins/plugins_ALL.tmpasm (revision 38022) +++ trunk/src_plugins/plugins_ALL.tmpasm (revision 38023) @@ -22,7 +22,6 @@ include {../src_plugins/drc_query/Plug.tmpasm} include {../src_plugins/expfeat/Plug.tmpasm} include {../src_plugins/export_bom/Plug.tmpasm} -include {../src_plugins/export_bom2/Plug.tmpasm} include {../src_plugins/export_c_draw/Plug.tmpasm} include {../src_plugins/export_debug/Plug.tmpasm} include {../src_plugins/export_dxf/Plug.tmpasm} Index: trunk/tests/RTT/ref/elem_pads.bom =================================================================== --- trunk/tests/RTT/ref/elem_pads.bom (revision 38022) +++ trunk/tests/RTT/ref/elem_pads.bom (revision 38023) @@ -5,5 +5,5 @@ # Title: pads with different geometry - PCB BOM # Quantity, Description, Value, RefDes # -------------------------------------------- -1,"Standard SMT resistor, capacitor etc","1206",R1 -1,"SMT transistor, 5 pins","SOT325",U1 +1,"Standard SMT resistor, capacitor etc","1206",R1 +1,"SMT transistor, 5 pins","SOT325",U1 Index: trunk/tests/RTT/ref/elem_pads_ds.bom =================================================================== --- trunk/tests/RTT/ref/elem_pads_ds.bom (revision 38022) +++ trunk/tests/RTT/ref/elem_pads_ds.bom (revision 38023) @@ -5,4 +5,4 @@ # Title: element with pads on both sides - PCB BOM # Quantity, Description, Value, RefDes # -------------------------------------------- -1,"(unknown)","(unknown)",E1 +1,"","(unknown)",E1 Index: trunk/tests/RTT/ref/elem_pins.bom =================================================================== --- trunk/tests/RTT/ref/elem_pins.bom (revision 38022) +++ trunk/tests/RTT/ref/elem_pins.bom (revision 38023) @@ -5,4 +5,4 @@ # Title: pins with different shapes - PCB BOM # Quantity, Description, Value, RefDes # -------------------------------------------- -2,"dip(2)","2*300",U1 U2 +2,"dip(2)","2*300",U1 U2 Index: trunk/tests/RTT/ref/elem_sides_smd.bom =================================================================== --- trunk/tests/RTT/ref/elem_sides_smd.bom (revision 38022) +++ trunk/tests/RTT/ref/elem_sides_smd.bom (revision 38023) @@ -5,4 +5,4 @@ # Title: smd elements on both sides - PCB BOM # Quantity, Description, Value, RefDes # -------------------------------------------- -2,"Standard SMT resistor, capacitor etc","1206",R1 R2 +2,"Standard SMT resistor, capacitor etc","1206",R1 R2 Index: trunk/tests/RTT/ref/elem_sides_trh.bom =================================================================== --- trunk/tests/RTT/ref/elem_sides_trh.bom (revision 38022) +++ trunk/tests/RTT/ref/elem_sides_trh.bom (revision 38023) @@ -5,4 +5,4 @@ # Title: thru-hole elements on both sides - PCB BOM # Quantity, Description, Value, RefDes # -------------------------------------------- -2,"dip(2)","2*300",U1 U2 +2,"dip(2)","2*300",U1 U2 Index: trunk/tests/RTT/ref/flag_colors.bom =================================================================== --- trunk/tests/RTT/ref/flag_colors.bom (revision 38022) +++ trunk/tests/RTT/ref/flag_colors.bom (revision 38023) @@ -5,4 +5,4 @@ # Title: (unknown) - PCB BOM # Quantity, Description, Value, RefDes # -------------------------------------------- -4,"0402 Standard SMT resistor, capacitor etc","(unknown)",(unknown) (unknown) (unknown) (unknown) +4,"0402 Standard SMT resistor, capacitor etc","(unknown)",(unknown) (unknown) (unknown) (unknown) Index: trunk/tests/RTT/ref/netlist.bom =================================================================== --- trunk/tests/RTT/ref/netlist.bom (revision 38022) +++ trunk/tests/RTT/ref/netlist.bom (revision 38023) @@ -5,4 +5,4 @@ # Title: board with minimal netlist - PCB BOM # Quantity, Description, Value, RefDes # -------------------------------------------- -1,"dip(4)","4*300",U1 +1,"dip(4)","4*300",U1 Index: trunk/tests/RTT/ref/netlist_ba.bom =================================================================== --- trunk/tests/RTT/ref/netlist_ba.bom (revision 38022) +++ trunk/tests/RTT/ref/netlist_ba.bom (revision 38023) @@ -5,4 +5,4 @@ # Title: board with minimal netlist and some back-annotation changes - PCB BOM # Quantity, Description, Value, RefDes # -------------------------------------------- -1,"dip(4)","4*300",U1 +1,"dip(4)","4*300",U1 Index: trunk/tests/RTT/ref/padrot.bom =================================================================== --- trunk/tests/RTT/ref/padrot.bom (revision 38022) +++ trunk/tests/RTT/ref/padrot.bom (revision 38023) @@ -5,4 +5,4 @@ # Title: Rotated round cap and square pads - PCB BOM # Quantity, Description, Value, RefDes # -------------------------------------------- -8,"(unknown)","(unknown)",R1 R3 R2 R6 R4 R5 R7 R8 +8,"","(unknown)",R1 R3 R2 R6 R4 R5 R7 R8