Index: trunk/src/Makefile.dep =================================================================== --- trunk/src/Makefile.dep (revision 38021) +++ trunk/src/Makefile.dep (revision 38022) @@ -486,6 +486,15 @@ vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h change.h board.h \ vtroutestyle.h rats_patch.h undo.h ../src_3rd/libuundo/uundo.h \ undo_old.h +../src_plugins/export_bom/bom.o: ../src_plugins/export_bom/bom.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 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 \ @@ -495,12 +504,11 @@ 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 \ - obj_pstk_inlines.h thermal.h operation.h obj_subc_op.h layer.h netlist.h \ - operation.h ../src_plugins/export_bom2/bom2_conf.h hid_cam.h \ - ../src_plugins/lib_compat_help/elem_rot.h \ + ../src_plugins/export_bom2/bom2_conf.h hid_cam.h \ ../src_plugins/export_bom2/conf_internal.c \ - ../src_plugins/export_bom2/bom2_conf_fields.h \ - ../src_plugins/export_bom2/lib_bom.h ../src_plugins/export_bom2/lib_bom.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_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 (nonexistent) +++ trunk/src_3rd/rnd_inclib/lib_bom/lib_bom.c (revision 38022) @@ -0,0 +1,326 @@ + +/*** formats ***/ + +static void bom_free_fmts(void) +{ + int n; + for(n = 0; n < bom_fmt_ids.used; n++) { + free(bom_fmt_ids.array[n]); + bom_fmt_ids.array[n] = NULL; + } + bom_fmt_names.used = 0; + bom_fmt_ids.used = 0; +} + +static void bom_fmt_init(void) +{ + vts0_init(&bom_fmt_names); + vts0_init(&bom_fmt_ids); +} + +static void bom_fmt_uninit(void) +{ + vts0_uninit(&bom_fmt_names); + vts0_uninit(&bom_fmt_ids); +} + +static void bom_build_fmts(const rnd_conflist_t *templates) +{ + rnd_conf_listitem_t *li; + int idx; + + bom_free_fmts(); + + rnd_conf_loop_list(templates, li, idx) { + char id[MAX_TEMP_NAME_LEN]; + const char *sep = strchr(li->name, '.'); + int len; + + if (sep == NULL) { + rnd_message(RND_MSG_ERROR, "export_bom2: ignoring invalid template name (missing period): '%s'\n", li->name); + continue; + } + if (strcmp(sep+1, "name") != 0) + 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); + continue; + } + memcpy(id, li->name, len); + id[len] = '\0'; + vts0_append(&bom_fmt_names, (char *)li->payload); + vts0_append(&bom_fmt_ids, rnd_strdup(id)); + } +} + +static const char *get_templ(const rnd_conflist_t *templates, const char *tid, const char *type) +{ + char path[MAX_TEMP_NAME_LEN + 16]; + rnd_conf_listitem_t *li; + int idx; + + sprintf(path, "%s.%s", tid, type); /* safe: tid's length is checked before it was put in the vector, type is hardwired in code and is never longer than a few chars */ + rnd_conf_loop_list(templates, li, idx) + if (strcmp(li->name, path) == 0) + return li->payload; + return NULL; +} + +static void bom_init_template(bom_template_t *templ, const rnd_conflist_t *templates, const char *tid) +{ + templ->header = get_templ(templates, tid, "header"); + templ->item = get_templ(templates, tid, "item"); + templ->footer = get_templ(templates, tid, "footer"); + templ->sort_id = get_templ(templates, tid, "sort_id"); + templ->escape = get_templ(templates, tid, "escape"); + templ->needs_escape = get_templ(templates, tid, "needs_escape"); +} + +/*** subst ***/ + +typedef struct bom_item_s { + bom_obj_t *obj; /* one of the objects picked randomly, for the attributes */ + char *id; /* key for sorting */ + gds_t name_list; + long cnt; +} bom_item_t; + +static void append_clean(bom_subst_ctx_t *ctx, int escape, gds_t *dst, const char *text) +{ + const char *s; + + if (!escape) { + gds_append_str(dst, text); + return; + } + + for(s = text; *s != '\0'; s++) { + switch(*s) { + case '\n': gds_append_str(dst, "\\n"); break; + case '\r': gds_append_str(dst, "\\r"); break; + case '\t': gds_append_str(dst, "\\t"); break; + default: + if ((ctx->needs_escape != NULL) && (strchr(ctx->needs_escape, *s) != NULL)) { + if ((ctx->escape != NULL) && (*ctx->escape != '\0')) { + gds_append(dst, *ctx->escape); + gds_append(dst, *s); + } + else + gds_append(dst, '_'); + } + else + gds_append(dst, *s); + break; + } + } +} + +static int is_val_true(const char *val) +{ + if (val == NULL) return 0; + if (strcmp(val, "yes") == 0) return 1; + if (strcmp(val, "on") == 0) return 1; + if (strcmp(val, "true") == 0) return 1; + if (strcmp(val, "1") == 0) return 1; + return 0; +} + +static int subst_cb(void *ctx_, gds_t *s, const char **input) +{ + bom_subst_ctx_t *ctx = ctx_; + int escape = 0, ternary = 0; + char aname[1024], unk_buf[1024], *nope = NULL; + char tmp[32]; + const char *str, *end; + const char *unk = ""; /* what to print on empty/NULL string if there's no ? or | in the template */ + long len; + + if (strncmp(*input, "escape.", 7) == 0) { + *input += 7; + escape = 1; + } + + /* field print operators, e.g. for subc.a attribute: + subc.a.attribute - print the attribute if exists, "n/a" if not + subc.a.attribute|unk - print the attribute if exists, unk if not + subc.a.attribute?yes - print yes if attribute is true, "n/a" if not + subc.a.attribute?yes:nope - print yes if attribute is true, nope if not + (subc.a.attribute, unk,yes and nope are arbitrary strings in the template) + */ + 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); + return 1; + } + memcpy(aname, *input, len); + aname[len] = '\0'; + if (*end == '|') { /* "or unknown" */ + *input = end+1; + 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); + return 1; + } + memcpy(unk_buf, *input, len); + unk_buf[len] = '\0'; + unk = unk_buf; + *input = end+1; + } + else if (*end == '?') { /* trenary */ + *input = end+1; + ternary = 1; + 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); + return 1; + } + + memcpy(unk_buf, *input, len); + unk_buf[len] = '\0'; + *input = end+1; + + nope = strchr(unk_buf, ':'); + if (nope != NULL) { + *nope = '\0'; + nope++; + } + else /* only '?' is given, no ':' */ + nope = "n/a"; + } + else /* plain '%' */ + *input = end+1; + + /* get the actual string; first a few generic ones then the app-specific callback */ + if (strcmp(aname, "count") == 0) { + sprintf(tmp, "%ld", ctx->count); + str = tmp; + } + else if (strcmp(aname, "UTC") == 0) str = ctx->utcTime; + else if (strcmp(aname, "names") == 0) str = ctx->name; + else str = subst_user(ctx, aname); + + /* render output */ + if (ternary) { + if (is_val_true(str)) + append_clean(ctx, escape, s, unk_buf); + else + append_clean(ctx, escape, s, nope); + return 0; + } + + if ((str == NULL) || (*str == '\0')) + str = unk; + append_clean(ctx, escape, s, str); + + return 0; +} + +static void fprintf_templ(FILE *f, bom_subst_ctx_t *ctx, const char *templ) +{ + if (templ != NULL) { + char *tmp = rnd_strdup_subst(templ, subst_cb, ctx, RND_SUBST_PERCENT); + fprintf(f, "%s", tmp); + free(tmp); + } +} + +static char *render_templ(bom_subst_ctx_t *ctx, const char *templ) +{ + if (templ != NULL) + return rnd_strdup_subst(templ, subst_cb, ctx, RND_SUBST_PERCENT); + return NULL; +} + +static int item_cmp(const void *item1, const void *item2) +{ + const bom_item_t * const *i1 = item1; + const bom_item_t * const *i2 = item2; + return strcmp((*i1)->id, (*i2)->id); +} + +static void bom_print_begin(bom_subst_ctx_t *ctx, FILE *f, const bom_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(bom_subst_ctx_t *ctx, bom_obj_t *obj, const char *name) +{ + char *id, *freeme; + bom_item_t *i; + + ctx->obj = obj; + ctx->name = (char *)name; + + id = freeme = render_templ(ctx, ctx->templ->sort_id); + i = htsp_get(&ctx->tbl, id); + if (i == NULL) { + i = malloc(sizeof(bom_item_t)); + i->id = id; + i->obj = obj; + i->cnt = 1; + gds_init(&i->name_list); + + htsp_set(&ctx->tbl, id, i); + vtp0_append(&ctx->arr, i); + freeme = NULL; + } + else { + i->cnt++; + gds_append(&i->name_list, ' '); + } + + gds_append_str(&i->name_list, name); + rnd_trace("id='%s' %ld\n", id, i->cnt); + + free(freeme); +} + +static void bom_print_all(bom_subst_ctx_t *ctx) +{ + long n; + + /* clean up and sort the array */ + ctx->obj = NULL; + qsort(ctx->arr.array, ctx->arr.used, sizeof(bom_item_t *), item_cmp); + + /* produce the actual output from the sorted array */ + for(n = 0; n < ctx->arr.used; n++) { + bom_item_t *i = ctx->arr.array[n]; + ctx->obj = i->obj; + ctx->name = i->name_list.array; + ctx->count = i->cnt; + fprintf_templ(ctx->f, ctx, ctx->templ->item); + } +} + +static void bom_print_end(bom_subst_ctx_t *ctx) +{ + fprintf_templ(ctx->f, ctx, ctx->templ->footer); + + gds_uninit(&ctx->tmp); + + genht_uninit_deep(htsp, &ctx->tbl, { + bom_item_t *i = htent->value; + free(i->id); + gds_uninit(&i->name_list); + free(i); + }); + vtp0_uninit(&ctx->arr); +} + Index: trunk/src_3rd/rnd_inclib/lib_bom/lib_bom.h =================================================================== --- trunk/src_3rd/rnd_inclib/lib_bom/lib_bom.h (nonexistent) +++ trunk/src_3rd/rnd_inclib/lib_bom/lib_bom.h (revision 38022) @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*** formats & templates ***/ +typedef struct bom_template_s { + const char *header, *item, *footer, *sort_id; + const char *needs_escape; /* list of characters that need escaping */ + const char *escape; /* escape character */ +} bom_template_t; + +static vts0_t bom_fmt_names; /* array of const char * long name of each format, pointing into the conf database */ +static vts0_t bom_fmt_ids; /* array of strdup'd short name (ID) of each format */ + +/* Call these once on plugin init/uninit */ +static void bom_fmt_init(void); +static void bom_fmt_uninit(void); + +/* (re)build bom_fmt_* arrays from the config list; call this before + initializing plugin format options enum */ +static void bom_build_fmts(const rnd_conflist_t *templates); + +/* Choose one of the templates by name (tid) from the config list and + load fields of templ with the relevant template strings; call this + before starting an export for a specific format */ +static void bom_init_template(bom_template_t *templ, const rnd_conflist_t *templates, const char *tid); + + +/*** subst ***/ + +/* The caller needs to typedef bom_obj_t to the app-specific object type that + is used as input for bom listings */ + + +typedef struct { + char utcTime[64]; + char *name; + bom_obj_t *obj; + long count; + 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 bom_template_t *templ; + FILE *f; +} bom_subst_ctx_t; + +/* Export a file; call begin, then loop over all items and call _add, then call + _all and _end. */ +static void bom_print_begin(bom_subst_ctx_t *ctx, FILE *f, const bom_template_t *templ); /* init ctx, print header */ +static void bom_print_add(bom_subst_ctx_t *ctx, bom_obj_t *obj, const char *name); /* add an app_item */ +static void bom_print_all(bom_subst_ctx_t *ctx); /* sort and print all items */ +static void bom_print_end(bom_subst_ctx_t *ctx); /* print footer and uninit ctx */ Index: trunk/src_plugins/export_bom2/lib_bom.c =================================================================== --- trunk/src_plugins/export_bom2/lib_bom.c (revision 38021) +++ trunk/src_plugins/export_bom2/lib_bom.c (nonexistent) @@ -1,326 +0,0 @@ - -/*** formats ***/ - -static void bom_free_fmts(void) -{ - int n; - for(n = 0; n < bom_fmt_ids.used; n++) { - free(bom_fmt_ids.array[n]); - bom_fmt_ids.array[n] = NULL; - } - bom_fmt_names.used = 0; - bom_fmt_ids.used = 0; -} - -static void bom_fmt_init(void) -{ - vts0_init(&bom_fmt_names); - vts0_init(&bom_fmt_ids); -} - -static void bom_fmt_uninit(void) -{ - vts0_uninit(&bom_fmt_names); - vts0_uninit(&bom_fmt_ids); -} - -static void bom_build_fmts(const rnd_conflist_t *templates) -{ - rnd_conf_listitem_t *li; - int idx; - - bom_free_fmts(); - - rnd_conf_loop_list(templates, li, idx) { - char id[MAX_TEMP_NAME_LEN]; - const char *sep = strchr(li->name, '.'); - int len; - - if (sep == NULL) { - rnd_message(RND_MSG_ERROR, "export_bom2: ignoring invalid template name (missing period): '%s'\n", li->name); - continue; - } - if (strcmp(sep+1, "name") != 0) - 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); - continue; - } - memcpy(id, li->name, len); - id[len] = '\0'; - vts0_append(&bom_fmt_names, (char *)li->payload); - vts0_append(&bom_fmt_ids, rnd_strdup(id)); - } -} - -static const char *get_templ(const rnd_conflist_t *templates, const char *tid, const char *type) -{ - char path[MAX_TEMP_NAME_LEN + 16]; - rnd_conf_listitem_t *li; - int idx; - - sprintf(path, "%s.%s", tid, type); /* safe: tid's length is checked before it was put in the vector, type is hardwired in code and is never longer than a few chars */ - rnd_conf_loop_list(templates, li, idx) - if (strcmp(li->name, path) == 0) - return li->payload; - return NULL; -} - -static void bom_init_template(bom_template_t *templ, const rnd_conflist_t *templates, const char *tid) -{ - templ->header = get_templ(templates, tid, "header"); - templ->item = get_templ(templates, tid, "item"); - templ->footer = get_templ(templates, tid, "footer"); - templ->sort_id = get_templ(templates, tid, "sort_id"); - templ->escape = get_templ(templates, tid, "escape"); - templ->needs_escape = get_templ(templates, tid, "needs_escape"); -} - -/*** subst ***/ - -typedef struct bom_item_s { - bom_obj_t *obj; /* one of the objects picked randomly, for the attributes */ - char *id; /* key for sorting */ - gds_t name_list; - long cnt; -} bom_item_t; - -static void append_clean(bom_subst_ctx_t *ctx, int escape, gds_t *dst, const char *text) -{ - const char *s; - - if (!escape) { - gds_append_str(dst, text); - return; - } - - for(s = text; *s != '\0'; s++) { - switch(*s) { - case '\n': gds_append_str(dst, "\\n"); break; - case '\r': gds_append_str(dst, "\\r"); break; - case '\t': gds_append_str(dst, "\\t"); break; - default: - if ((ctx->needs_escape != NULL) && (strchr(ctx->needs_escape, *s) != NULL)) { - if ((ctx->escape != NULL) && (*ctx->escape != '\0')) { - gds_append(dst, *ctx->escape); - gds_append(dst, *s); - } - else - gds_append(dst, '_'); - } - else - gds_append(dst, *s); - break; - } - } -} - -static int is_val_true(const char *val) -{ - if (val == NULL) return 0; - if (strcmp(val, "yes") == 0) return 1; - if (strcmp(val, "on") == 0) return 1; - if (strcmp(val, "true") == 0) return 1; - if (strcmp(val, "1") == 0) return 1; - return 0; -} - -static int subst_cb(void *ctx_, gds_t *s, const char **input) -{ - bom_subst_ctx_t *ctx = ctx_; - int escape = 0, ternary = 0; - char aname[1024], unk_buf[1024], *nope = NULL; - char tmp[32]; - const char *str, *end; - const char *unk = ""; /* what to print on empty/NULL string if there's no ? or | in the template */ - long len; - - if (strncmp(*input, "escape.", 7) == 0) { - *input += 7; - escape = 1; - } - - /* field print operators, e.g. for subc.a attribute: - subc.a.attribute - print the attribute if exists, "n/a" if not - subc.a.attribute|unk - print the attribute if exists, unk if not - subc.a.attribute?yes - print yes if attribute is true, "n/a" if not - subc.a.attribute?yes:nope - print yes if attribute is true, nope if not - (subc.a.attribute, unk,yes and nope are arbitrary strings in the template) - */ - 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); - return 1; - } - memcpy(aname, *input, len); - aname[len] = '\0'; - if (*end == '|') { /* "or unknown" */ - *input = end+1; - 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); - return 1; - } - memcpy(unk_buf, *input, len); - unk_buf[len] = '\0'; - unk = unk_buf; - *input = end+1; - } - else if (*end == '?') { /* trenary */ - *input = end+1; - ternary = 1; - 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); - return 1; - } - - memcpy(unk_buf, *input, len); - unk_buf[len] = '\0'; - *input = end+1; - - nope = strchr(unk_buf, ':'); - if (nope != NULL) { - *nope = '\0'; - nope++; - } - else /* only '?' is given, no ':' */ - nope = "n/a"; - } - else /* plain '%' */ - *input = end+1; - - /* get the actual string; first a few generic ones then the app-specific callback */ - if (strcmp(aname, "count") == 0) { - sprintf(tmp, "%ld", ctx->count); - str = tmp; - } - else if (strcmp(aname, "UTC") == 0) str = ctx->utcTime; - else if (strcmp(aname, "names") == 0) str = ctx->name; - else str = subst_user(ctx, aname); - - /* render output */ - if (ternary) { - if (is_val_true(str)) - append_clean(ctx, escape, s, unk_buf); - else - append_clean(ctx, escape, s, nope); - return 0; - } - - if ((str == NULL) || (*str == '\0')) - str = unk; - append_clean(ctx, escape, s, str); - - return 0; -} - -static void fprintf_templ(FILE *f, bom_subst_ctx_t *ctx, const char *templ) -{ - if (templ != NULL) { - char *tmp = rnd_strdup_subst(templ, subst_cb, ctx, RND_SUBST_PERCENT); - fprintf(f, "%s", tmp); - free(tmp); - } -} - -static char *render_templ(bom_subst_ctx_t *ctx, const char *templ) -{ - if (templ != NULL) - return rnd_strdup_subst(templ, subst_cb, ctx, RND_SUBST_PERCENT); - return NULL; -} - -static int item_cmp(const void *item1, const void *item2) -{ - const bom_item_t * const *i1 = item1; - const bom_item_t * const *i2 = item2; - return strcmp((*i1)->id, (*i2)->id); -} - -static void bom_print_begin(bom_subst_ctx_t *ctx, FILE *f, const bom_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(bom_subst_ctx_t *ctx, bom_obj_t *obj, const char *name) -{ - char *id, *freeme; - bom_item_t *i; - - ctx->obj = obj; - ctx->name = (char *)name; - - id = freeme = render_templ(ctx, ctx->templ->sort_id); - i = htsp_get(&ctx->tbl, id); - if (i == NULL) { - i = malloc(sizeof(bom_item_t)); - i->id = id; - i->obj = obj; - i->cnt = 1; - gds_init(&i->name_list); - - htsp_set(&ctx->tbl, id, i); - vtp0_append(&ctx->arr, i); - freeme = NULL; - } - else { - i->cnt++; - gds_append(&i->name_list, ' '); - } - - gds_append_str(&i->name_list, name); - rnd_trace("id='%s' %ld\n", id, i->cnt); - - free(freeme); -} - -static void bom_print_all(bom_subst_ctx_t *ctx) -{ - long n; - - /* clean up and sort the array */ - ctx->obj = NULL; - qsort(ctx->arr.array, ctx->arr.used, sizeof(bom_item_t *), item_cmp); - - /* produce the actual output from the sorted array */ - for(n = 0; n < ctx->arr.used; n++) { - bom_item_t *i = ctx->arr.array[n]; - ctx->obj = i->obj; - ctx->name = i->name_list.array; - ctx->count = i->cnt; - fprintf_templ(ctx->f, ctx, ctx->templ->item); - } -} - -static void bom_print_end(bom_subst_ctx_t *ctx) -{ - fprintf_templ(ctx->f, ctx, ctx->templ->footer); - - gds_uninit(&ctx->tmp); - - genht_uninit_deep(htsp, &ctx->tbl, { - bom_item_t *i = htent->value; - free(i->id); - gds_uninit(&i->name_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 38021) +++ trunk/src_plugins/export_bom2/lib_bom.h (nonexistent) @@ -1,63 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/*** formats & templates ***/ -typedef struct bom_template_s { - const char *header, *item, *footer, *sort_id; - const char *needs_escape; /* list of characters that need escaping */ - const char *escape; /* escape character */ -} bom_template_t; - -static vts0_t bom_fmt_names; /* array of const char * long name of each format, pointing into the conf database */ -static vts0_t bom_fmt_ids; /* array of strdup'd short name (ID) of each format */ - -/* Call these once on plugin init/uninit */ -static void bom_fmt_init(void); -static void bom_fmt_uninit(void); - -/* (re)build bom_fmt_* arrays from the config list; call this before - initializing plugin format options enum */ -static void bom_build_fmts(const rnd_conflist_t *templates); - -/* Choose one of the templates by name (tid) from the config list and - load fields of templ with the relevant template strings; call this - before starting an export for a specific format */ -static void bom_init_template(bom_template_t *templ, const rnd_conflist_t *templates, const char *tid); - - -/*** subst ***/ - -/* The caller needs to typedef bom_obj_t to the app-specific object type that - is used as input for bom listings */ - - -typedef struct { - char utcTime[64]; - char *name; - bom_obj_t *obj; - long count; - 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 bom_template_t *templ; - FILE *f; -} bom_subst_ctx_t; - -/* Export a file; call begin, then loop over all items and call _add, then call - _all and _end. */ -static void bom_print_begin(bom_subst_ctx_t *ctx, FILE *f, const bom_template_t *templ); /* init ctx, print header */ -static void bom_print_add(bom_subst_ctx_t *ctx, bom_obj_t *obj, const char *name); /* add an app_item */ -static void bom_print_all(bom_subst_ctx_t *ctx); /* sort and print all items */ -static void bom_print_end(bom_subst_ctx_t *ctx); /* print footer and uninit ctx */ Index: trunk/src_plugins/export_bom2/bom2.c =================================================================== --- trunk/src_plugins/export_bom2/bom2.c (revision 38021) +++ trunk/src_plugins/export_bom2/bom2.c (revision 38022) @@ -53,7 +53,7 @@ static const char *bom2_filename; typedef pcb_subc_t bom_obj_t; -#include "lib_bom.h" +#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) { @@ -180,7 +180,7 @@ return rnd_hid_parse_command_line(argc, argv); } -#include "lib_bom.c" +#include "../../src_3rd/rnd_inclib/lib_bom/lib_bom.c" rnd_hid_t bom2_hid;