Index: trunk/src/plug_footprint.c =================================================================== --- trunk/src/plug_footprint.c (revision 30819) +++ trunk/src/plug_footprint.c (revision 30820) @@ -118,13 +118,31 @@ { pcb_conf_listitem_t *ci; FILE *res = NULL; + char *sep = strstr(name, "::"); + if (sep != NULL) { + long offs = sep - name; + fctx->filename = pcb_strdup(name); + sep = (char *)fctx->filename + offs; + *sep = '\0'; + fctx->free_filename = 0; + fctx->subfpname = sep+2; + fctx->free_filename = 1; + } + else { + fctx->filename = name; + fctx->subfpname = NULL; + fctx->free_filename = 0; + } + for(ci = pcb_conflist_first((pcb_conflist_t *)path); ci != NULL; ci = pcb_conflist_next(ci)) { const char *curr = ci->val.string[0]; - PCB_HOOK_CALL(pcb_plug_fp_t, pcb_plug_fp_chain, fp_fopen, res, != NULL, (self, curr, name, fctx, dst)); + PCB_HOOK_CALL(pcb_plug_fp_t, pcb_plug_fp_chain, fp_fopen, res, != NULL, (self, curr, fctx->filename, fctx, dst)); if (res != NULL) return res; } + + fctx->backend = NULL; return NULL; } @@ -132,6 +150,10 @@ { if ((fctx->backend != NULL) && (fctx->backend->fp_fclose != NULL)) fctx->backend->fp_fclose(fctx->backend, f, fctx); + if (fctx->free_filename) + free((char *)fctx->filename); + fctx->filename = NULL; + fctx->free_filename = 0; } pcb_fplibrary_t *pcb_fp_append_entry(pcb_fplibrary_t *parent, const char *name, pcb_fptype_t type, void *tags[]) Index: trunk/src/plug_footprint.h =================================================================== --- trunk/src/plug_footprint.h (revision 30819) +++ trunk/src/plug_footprint.h (revision 30820) @@ -14,9 +14,13 @@ int i; void *p; } field[4]; + + const char *filename; /* basename of the footprint file, with possible sub footprint name truncated from "::" */ + const char *subfpname; /* if the file contains multiple footprints, this holds the footprint name to open */ + int free_filename; /* internal */ } pcb_fp_fopen_ctx_t; -/* hook bindings, see below */ +/* hook bindings, see below; pcb_fp_fclose() must be called even if pcb_fp_fopen() returned NULL! */ FILE *pcb_fp_fopen(const pcb_conflist_t *path, const char *name, pcb_fp_fopen_ctx_t *fctx, pcb_data_t *dst); void pcb_fp_fclose(FILE * f, pcb_fp_fopen_ctx_t *fctx); Index: trunk/src/plug_io.c =================================================================== --- trunk/src/plug_io.c (revision 30819) +++ trunk/src/plug_io.c (revision 30820) @@ -258,11 +258,11 @@ f = pcb_fp_fopen(&conf_core.rc.library_search_paths, Filename, &fctx, Ptr); if (f == PCB_FP_FOPEN_IN_DST) return 0; - len = pcb_test_parse_all(f, Filename, fmt, PCB_IOT_FOOTPRINT, available, accepts, &accept_total, sizeof(available)/sizeof(available[0]), 0, 0); - if (f != NULL) + len = pcb_test_parse_all(f, fctx.filename, fmt, PCB_IOT_FOOTPRINT, available, accepts, &accept_total, sizeof(available)/sizeof(available[0]), 0, 0); + if (len < 0) { pcb_fp_fclose(f, &fctx); - if (len < 0) return -1; + } Ptr->loader = NULL; @@ -270,7 +270,7 @@ for(n = 0; n < len; n++) { if ((available[n].plug->parse_footprint == NULL) || (!accepts[n])) /* can't parse or doesn't want to parse this file */ continue; - res = available[n].plug->parse_footprint(available[n].plug, Ptr, Filename); + res = available[n].plug->parse_footprint(available[n].plug, Ptr, fctx.filename); if (res == 0) { if (Ptr->loader == NULL) /* if the loader didn't set this (to some more fine grained, e.g. depending on file format version) */ Ptr->loader = available[n].plug; @@ -283,6 +283,7 @@ pcb_data_flag_change(Ptr, PCB_OBJ_CLASS_REAL, PCB_CHGFLG_CLEAR, PCB_FLAG_FOUND | PCB_FLAG_SELECTED); pcb_plug_io_err(&PCB->hidlib, res, "load footprint", Filename); + pcb_fp_fclose(f, &fctx); return res; } Index: trunk/src_plugins/diag/diag.c =================================================================== --- trunk/src_plugins/diag/diag.c (revision 30819) +++ trunk/src_plugins/diag/diag.c (revision 30820) @@ -521,7 +521,7 @@ /* print exrtas */ if (want_bbox || want_origin) { pcb_buffer_clear(PCB, &SCRATCH); - if (!pcb_buffer_load_footprint(&SCRATCH, fpn, NULL)) { + if (!pcb_buffer_load_footprint(&SCRATCH, fctx.filename, NULL)) { PCB_ACT_IRES(1); return 0; } @@ -535,6 +535,7 @@ PCB_ACT_IRES(0); } else { + pcb_fp_fclose(f, &fctx); printf(DLF_PREFIX "error file not found\n"); PCB_ACT_IRES(1); } Index: trunk/src_plugins/io_kicad/read.c =================================================================== --- trunk/src_plugins/io_kicad/read.c (revision 30819) +++ trunk/src_plugins/io_kicad/read.c (revision 30820) @@ -2805,6 +2805,7 @@ f = pcb_fp_fopen(&conf_core.rc.library_search_paths, name, &fpst, NULL); if (f == NULL) { + pcb_fp_fclose(f, &fpst); return -1; } @@ -2812,7 +2813,7 @@ memset(&st, 0, sizeof(st)); st.pcb = NULL; st.fp_data = Ptr; - st.Filename = name; + st.Filename = fpst.filename; st.settings_dest = CFR_invalid; st.auto_layers = 1; Index: trunk/src_plugins/io_lihata/read.c =================================================================== --- trunk/src_plugins/io_lihata/read.c (revision 30819) +++ trunk/src_plugins/io_lihata/read.c (revision 30820) @@ -2531,10 +2531,9 @@ f = pcb_fp_fopen(&conf_core.rc.library_search_paths, name, &st, NULL); - if (f != NULL) { - doc = lht_dom_load_stream(f, name, &errmsg); - pcb_fp_fclose(f, &st); - } + if (f != NULL) + doc = lht_dom_load_stream(f, st.filename, &errmsg); + pcb_fp_fclose(f, &st); if (doc == NULL) { if (!pcb_io_err_inhibit) Index: trunk/src_plugins/io_pcb/parse_l.c =================================================================== --- trunk/src_plugins/io_pcb/parse_l.c (revision 30819) +++ trunk/src_plugins/io_pcb/parse_l.c (revision 30820) @@ -2715,8 +2715,10 @@ yyElemFixLayers = 1; - if (f == NULL) + if (f == NULL) { + pcb_fp_fclose(f, &st); return -1; + } ret = Parse(f, NULL,NULL,NULL); Index: trunk/src_plugins/io_pcb/parse_l.l =================================================================== --- trunk/src_plugins/io_pcb/parse_l.l (revision 30819) +++ trunk/src_plugins/io_pcb/parse_l.l (revision 30820) @@ -332,8 +332,10 @@ yyElemFixLayers = 1; - if (f == NULL) + if (f == NULL) { + pcb_fp_fclose(f, &st); return -1; + } ret = Parse(f, NULL,NULL,NULL);