Index: trunk/src_plugins/export_bom2/bom2.c =================================================================== --- trunk/src_plugins/export_bom2/bom2.c (revision 38004) +++ trunk/src_plugins/export_bom2/bom2.c (revision 38005) @@ -152,90 +152,29 @@ static int PrintBOM(const template_t *templ, const char *format_name) { - FILE *fp; + FILE *f; subst_ctx_t ctx = {0}; - htsp_t tbl; - vtp0_t arr = {0}; - long n; - fp = rnd_fopen_askovr(&PCB->hidlib, bom2_filename, "w", NULL); - if (!fp) { + 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; } - gds_init(&ctx.tmp); + bom_print_begin(&ctx, f, templ); - rnd_print_utc(ctx.utcTime, sizeof(ctx.utcTime), 0); - - fprintf_templ(fp, &ctx, templ->header); - - htsp_init(&tbl, strhash, strkeyeq); - - ctx.escape = templ->escape; - ctx.needs_escape = templ->needs_escape; - /* For each subcircuit calculate an ID and count recurring IDs in a hash table and an array (for sorting) */ PCB_SUBC_LOOP(PCB->Data); { - char *id, *freeme; - item_t *i; const char *refdes = RND_UNKNOWN(pcb_attribute_get(&subc->Attributes, "refdes")); - - ctx.subc = subc; - ctx.name = (char *)refdes; - - id = freeme = render_templ(&ctx, templ->subc2id); - i = htsp_get(&tbl, id); - if (i == NULL) { - i = malloc(sizeof(item_t)); - i->id = id; - i->subc = subc; - i->cnt = 1; - gds_init(&i->refdes_list); - - htsp_set(&tbl, id, i); - vtp0_append(&arr, i); - freeme = NULL; - } - else { - i->cnt++; - gds_append(&i->refdes_list, ' '); - } - - gds_append_str(&i->refdes_list, refdes); - rnd_trace("id='%s' %ld\n", id, i->cnt); - - free(freeme); + bom_print_add(&ctx, subc, refdes); } PCB_END_LOOP; - /* clean up and sort the array */ - ctx.subc = NULL; - qsort(arr.array, arr.used, sizeof(item_t *), item_cmp); + bom_print_all(&ctx); + bom_print_end(&ctx); + fclose(f); - /* produce the actual output from the sorted array */ - for(n = 0; n < arr.used; n++) { - item_t *i = arr.array[n]; - ctx.subc = i->subc; - ctx.name = i->refdes_list.array; - ctx.count = i->cnt; - fprintf_templ(fp, &ctx, templ->item); - } - - fprintf_templ(fp, &ctx, templ->footer); - - fclose(fp); - gds_uninit(&ctx.tmp); - - genht_uninit_deep(htsp, &tbl, { - item_t *i = htent->value; - free(i->id); - gds_uninit(&i->refdes_list); - free(i); - }); - vtp0_uninit(&arr); - return 0; } Index: trunk/src_plugins/export_bom2/lib_bom.c =================================================================== --- trunk/src_plugins/export_bom2/lib_bom.c (revision 38004) +++ trunk/src_plugins/export_bom2/lib_bom.c (revision 38005) @@ -206,3 +206,86 @@ const item_t * const *i2 = item2; return strcmp((*i1)->id, (*i2)->id); } + +static void bom_print_begin(subst_ctx_t *ctx, FILE *f, const template_t *templ) +{ + gds_init(&ctx->tmp); + + rnd_print_utc(ctx->utcTime, sizeof(ctx->utcTime), 0); + + fprintf_templ(f, ctx, templ->header); + + htsp_init(&ctx->tbl, strhash, strkeyeq); + vtp0_init(&ctx->arr); + + ctx->escape = templ->escape; + ctx->needs_escape = templ->needs_escape; + ctx->templ = templ; + ctx->f = f; +} + +static void bom_print_add(subst_ctx_t *ctx, pcb_subc_t *subc, const char *name) +{ + char *id, *freeme; + item_t *i; + + ctx->subc = subc; + ctx->name = (char *)name; + + id = freeme = render_templ(ctx, ctx->templ->subc2id); + i = htsp_get(&ctx->tbl, id); + if (i == NULL) { + i = malloc(sizeof(item_t)); + i->id = id; + i->subc = subc; + i->cnt = 1; + gds_init(&i->refdes_list); + + htsp_set(&ctx->tbl, id, i); + vtp0_append(&ctx->arr, i); + freeme = NULL; + } + else { + i->cnt++; + gds_append(&i->refdes_list, ' '); + } + + gds_append_str(&i->refdes_list, name); + rnd_trace("id='%s' %ld\n", id, i->cnt); + + free(freeme); +} + +static void bom_print_all(subst_ctx_t *ctx) +{ + long n; + + /* clean up and sort the array */ + ctx->subc = NULL; + qsort(ctx->arr.array, ctx->arr.used, sizeof(item_t *), item_cmp); + + /* produce the actual output from the sorted array */ + for(n = 0; n < ctx->arr.used; n++) { + item_t *i = ctx->arr.array[n]; + ctx->subc = i->subc; + ctx->name = i->refdes_list.array; + ctx->count = i->cnt; + fprintf_templ(ctx->f, ctx, ctx->templ->item); + } +} + +static void bom_print_end(subst_ctx_t *ctx) +{ + fprintf_templ(ctx->f, ctx, ctx->templ->footer); + + gds_uninit(&ctx->tmp); + + genht_uninit_deep(htsp, &ctx->tbl, { + item_t *i = htent->value; + free(i->id); + gds_uninit(&i->refdes_list); + free(i); + }); + vtp0_uninit(&ctx->arr); +} + Index: trunk/src_plugins/export_bom2/lib_bom.h =================================================================== --- trunk/src_plugins/export_bom2/lib_bom.h (revision 38004) +++ trunk/src_plugins/export_bom2/lib_bom.h (revision 38005) @@ -23,6 +23,12 @@ gds_t tmp; const char *needs_escape; /* list of characters that need escaping */ const char *escape; /* escape character or NULL for replacing with _*/ + + /* print/sort state */ + htsp_t tbl; + vtp0_t arr; + const template_t *templ; + FILE *f; } subst_ctx_t; @@ -34,8 +40,9 @@ } item_t; -static void fprintf_templ(FILE *f, subst_ctx_t *ctx, const char *templ); -static char *render_templ(subst_ctx_t *ctx, const char *templ); - -/* temporary */ -static int item_cmp(const void *item1, const void *item2); +/* Export a file; call begin, then loop over all items and call _add, then call + _all and _end. */ +static void bom_print_begin(subst_ctx_t *ctx, FILE *f, const template_t *templ); /* init ctx, print header */ +static void bom_print_add(subst_ctx_t *ctx, pcb_subc_t *subc, const char *name); /* add an app_item */ +static void bom_print_all(subst_ctx_t *ctx); /* sort and print all items */ +static void bom_print_end(subst_ctx_t *ctx); /* print footer and uninit ctx */