From f699d187e6d67bed369a882aba387be2f500a554 Mon Sep 17 00:00:00 2001 From: Stefan Schippers Date: Tue, 29 Sep 2020 11:17:10 +0200 Subject: [PATCH] save embedded components not only on first embeded instance but on all of them. This makes reloading easier and the overall thing much simpler. In LCC schematic allow get_sym_type() to read symbol data from folowing embedded tags "[...]" if any. Fix potential segfault in preview_window() --- src/save.c | 88 +++++++++++++++++--------- src/xinit.c | 1 + xschem_library/examples/bus_keeper.sch | 9 ++- xschem_library/examples/cmos_inv.sch | 2 +- 4 files changed, 67 insertions(+), 33 deletions(-) diff --git a/src/save.c b/src/save.c index 894cd102..a9e2eef4 100644 --- a/src/save.c +++ b/src/save.c @@ -284,8 +284,8 @@ void save_inst(FILE *fd) fprintf(fd, " %.16g %.16g %d %d ",ptr[i].x0, ptr[i].y0, ptr[i].rot, ptr[i].flip ); save_ascii_string(ptr[i].prop_ptr,fd); fputc('\n' ,fd); - if( !strcmp(get_tok_value(ptr[i].prop_ptr, "embed", 0), "true") && - !(instdef[ptr[i].ptr].flags & EMBEDDED)) { + if( !strcmp(get_tok_value(ptr[i].prop_ptr, "embed", 0), "true") ) { + /* && !(instdef[ptr[i].ptr].flags & EMBEDDED)) { */ fprintf(fd, "[\n"); save_embedded_symbol( instdef+ptr[i].ptr, fd); fprintf(fd, "]\n"); @@ -786,7 +786,6 @@ void read_xschem_file(FILE *fd) if(inst_ptr[lastinst-1].name) { char *str; - int dbg_level = 1; my_snprintf(name_embedded, S(name_embedded), "%s/.xschem_embedded_%d_%s", tclgetvar("XSCHEM_TMP_DIR"), getpid(), get_cell_w_ext(inst_ptr[lastinst-1].name, 0)); found=0; @@ -796,20 +795,12 @@ void read_xschem_file(FILE *fd) dbg(1, "read_xschem_file(): inst_ptr[lastinst-1].name=%s\n", inst_ptr[lastinst-1].name); /* symbol has already been loaded: skip [..] */ if(!strcmp(instdef[i].name, inst_ptr[lastinst-1].name)) { - if(netlist_count) - dbg_level = 1; /* when doing netlists symbols are not deleted when descending: perfectly normal - to have redundant embedded definitions */ - else - dbg_level = 0; /* this is an abnormal situation, so redundant [ ... ] should be skipped and reported */ - found=1; break; } /* if loading file coming back from embedded symbol delete temporary file */ if(!strcmp(name_embedded, instdef[i].name)) { my_strdup(325, &instdef[i].name, inst_ptr[lastinst-1].name); xunlink(name_embedded); - dbg_level = 1; /* when returning from embedded symbol, that symbol is already loaded in instdef[] by go_back() - so it's perfectly normal (and should not be logged) to skip these lines */ found=1;break; } } @@ -817,7 +808,7 @@ void read_xschem_file(FILE *fd) if(!found) load_sym_def(inst_ptr[lastinst-1].name, fd); else { while(1) { /* skip embedded [ ... ] */ - str = read_line(fd, dbg_level); + str = read_line(fd, 1); if(!str || !strncmp(str, "]", 1)) break; fscanf(fd, "%*1[\n]"); } @@ -1246,8 +1237,9 @@ void pop_undo(int redo) * first look in already loaded symbols else inspect symbol file * do not load all symname data, just get the type * return symbol type in type pointer or "" if no type or no symbol found - * if pintable given (!=NULL) hash all symbol pins */ -void get_sym_type(const char *symname, char **type, struct int_hashentry **pintable) + * if pintable given (!=NULL) hash all symbol pins + * if embed_fd is not NULL read symbol from embedded '[...]' tags using embed_fd file pointer */ +void get_sym_type(const char *symname, char **type, struct int_hashentry **pintable, FILE *embed_fd) { int i, c, n = 0; char name[PATH_MAX]; @@ -1275,8 +1267,11 @@ void get_sym_type(const char *symname, char **type, struct int_hashentry **pinta if( !found ) { dbg(1, "get_sym_type(): open file %s, pintable %s\n",name, pintable ? "set" : "null"); /* ... if not found open file and look for 'type' into the global attributes. */ - if((fd=fopen(name,"r"))==NULL) - { + + if(embed_fd) fd = embed_fd; + else fd=fopen(name,"r"); + + if(fd==NULL) { dbg(1, "get_sym_type(): Symbol not found: %s\n",name); my_strdup2(1162, type, ""); } else { @@ -1286,6 +1281,7 @@ void get_sym_type(const char *symname, char **type, struct int_hashentry **pinta box.prop_ptr = NULL; while(1) { if(fscanf(fd," %c",tag)==EOF) break; + if(embed_fd && tag[0] == ']') break; switch(tag[0]) { case 'G': load_ascii_string(&globalprop,fd); @@ -1322,7 +1318,7 @@ void get_sym_type(const char *symname, char **type, struct int_hashentry **pinta } my_free(1166, &globalprop); my_free(1167, &box.prop_ptr); - fclose(fd); + if(!embed_fd) fclose(fd); } } dbg(1, "get_sym_type(): symbol=%s --> type=%s\n", symname, *type); @@ -1344,7 +1340,7 @@ void align_sch_pins_with_sym(const char *name, int pos) my_strncpy(symname, add_ext(name, ".sym"), S(symname)); for(i = 0; i < HASHSIZE; i++) pintable[i] = NULL; /* hash all symbol pins with their position into pintable hash*/ - get_sym_type(symname, &symtype, pintable); + get_sym_type(symname, &symtype, pintable, NULL); if(symtype[0]) { /* found a .sym for current .sch LCC instance */ Box *box = NULL; box = (Box *) my_malloc(1168, sizeof(Box) * instdef[pos].rects[PINLAYER]); @@ -1504,7 +1500,6 @@ void calc_symbol_bbox(int pos) * instdef * lastinstdef * has_x - * lcc (static global) */ int load_sym_def(const char *name, FILE *embed_fd) { @@ -1517,6 +1512,7 @@ int load_sym_def(const char *name, FILE *embed_fd) int incremented_level=0; int level = 0; int max_level; + long filepos; char sympath[PATH_MAX]; int i,c, k, poly_points; char *aux_ptr=NULL; @@ -1583,7 +1579,7 @@ int load_sym_def(const char *name, FILE *embed_fd) my_strdup(352, &instdef[lastinstdef].name,name); while(1) { - if(endfile && embed_fd) break; /* ']' line encountered --> exit */ + if(endfile && embed_fd && level == 0) break; /* ']' line encountered --> exit */ if(fscanf(lcc[level].fd," %c",tag)==EOF) { if (level) { dbg(1, "l_s_d(): fclose1, level=%d, fd=%p\n", level, lcc[level].fd); @@ -1879,10 +1875,25 @@ int load_sym_def(const char *name, FILE *embed_fd) endfile = 1; continue; } - dbg(1, "l_s_d(): call get_sym_type(), symname=%s\n", symname); - /* get symbol type by looking into list of loaded symbols or (if not found) by - * opening/closing the symbol file and getting the 'type' attribute from global symbol attributes */ - get_sym_type(symname, &symtype, NULL); + + { + char c; + filepos = ftell(lcc[level].fd); /* store file pointer position to inspect next line */ + fd_tmp = NULL; + read_line(lcc[level].fd, 1); + fscanf(lcc[level].fd, "%*1[\n]"); + if(fscanf(lcc[level].fd," %c",&c)!=EOF) { + if( c == '[') { + fd_tmp = lcc[level].fd; + } + } + /* get symbol type by looking into list of loaded symbols or (if not found) by + * opening/closing the symbol file and getting the 'type' attribute from global symbol attributes + * if fd_tmp set read symbol from embedded tags '[...]' */ + get_sym_type(symname, &symtype, NULL, fd_tmp); + fseek(lcc[level].fd, filepos, SEEK_SET); /* rewind file pointer */ + } + dbg(1, "l_s_d(): level=%d, symname=%s symtype=%s\n", level, symname, symtype); if( /* add here symbol types not to consider when loading schematic-as-symbol instances */ !strcmp(symtype, "logo") || @@ -1911,14 +1922,26 @@ int load_sym_def(const char *name, FILE *embed_fd) /* replace i/o/iopin.sym filename with better looking (for LCC symbol) pins */ use_lcc_pins(level, symtype, &sympath); + /* find out if symbol is in an external file or embedded, set fd_tmp accordingly */ if ((fd_tmp = fopen(sympath, "r")) == NULL) { + char c; fprintf(errfp, "l_s_d(): unable to open file to read schematic: %s\n", sympath); - } else { + filepos = ftell(lcc[level].fd); /* store file pointer position to inspect next char */ + read_line(lcc[level].fd, 1); + fscanf(lcc[level].fd, "%*1[\n]"); + if(fscanf(lcc[level].fd," %c",&c)!=EOF) { + if( c == '[') { + fd_tmp = lcc[level].fd; + } else { + fseek(lcc[level].fd, filepos, SEEK_SET); /* rewind file pointer */ + } + } + } + if(fd_tmp) { if (level+1 >= max_level) { my_realloc(653, &lcc, (max_level + 1) * sizeof(struct Lcc)); max_level++; } - dbg(1, "l_s_d(): fopen2(%s), level=%d, fd=%p\n", sympath, level, fd_tmp); ++level; incremented_level = 1; lcc[level].fd = fd_tmp; @@ -1949,14 +1972,19 @@ int load_sym_def(const char *name, FILE *embed_fd) break; case '[': while(1) { /* skip embedded [ ... ] */ - skip_line = read_line(lcc[level].fd, 0); + skip_line = read_line(lcc[level].fd, 1); if(!skip_line || !strncmp(skip_line, "]", 1)) break; fscanf(lcc[level].fd, "%*1[\n]"); } break; case ']': - read_line(lcc[level].fd, 0); - endfile=1; + if(level) { + my_free(0, &lcc[level].prop_ptr); + my_free(0, &lcc[level].symname); + --level; + } else { + endfile=1; + } break; default: if( tag[0] == '{' ) ungetc(tag[0], lcc[level].fd); @@ -2270,8 +2298,6 @@ void round_schematic_to_grid(double cadsnap) break; } } - - } /* what: */ diff --git a/src/xinit.c b/src/xinit.c index bf3d6579..fd3a01c8 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -806,6 +806,7 @@ void preview_window(const char *what, const char *tk_win_path, const char *filen remove_symbols(); my_strncpy(schematic[currentsch] , "", S(schematic[currentsch])); currentsch--; + clear_drawing(); pop_undo(0); modified = save_mod; set_modify(modified); diff --git a/xschem_library/examples/bus_keeper.sch b/xschem_library/examples/bus_keeper.sch index efdebbca..e003036b 100644 --- a/xschem_library/examples/bus_keeper.sch +++ b/xschem_library/examples/bus_keeper.sch @@ -1,4 +1,4 @@ -v {xschem version=2.9.7 file_version=1.2} +v {xschem version=2.9.8 file_version=1.2} G {} K {type=subcircuit format="@name @pinlist @symname WN_FB=@WN_FB WP_FB=@WP_FB" @@ -15,7 +15,14 @@ N 280 -680 280 -300 {lab=A} N 430 -300 450 -300 {lab=#net1} N 450 -680 450 -300 {lab=#net1} N 430 -680 450 -680 {lab=#net1} +N 350 -500 390 -500 { lab=GND} C {cmos_inv.sch} 240 -70 0 0 {name=X2 WN=15u WP=45u LLN=3u LLP=3u} C {cmos_inv.sch} 490 -450 0 1 {name=X1 WN=WN_FB WP=WP_FB LLN=3u LLP=3u} C {iopin.sym} 250 -300 0 1 {name=p1 lab=A} C {title.sym} 160 -30 0 0 {name=l1 author="Stefan Schippers"} +C {capa.sym} 420 -500 1 0 {name=C1 +m=1 +value=10f +footprint=1206 +device="ceramic capacitor"} +C {gnd.sym} 350 -500 0 0 {name=l2 lab=GND} diff --git a/xschem_library/examples/cmos_inv.sch b/xschem_library/examples/cmos_inv.sch index c12c9221..15b3b5c4 100644 --- a/xschem_library/examples/cmos_inv.sch +++ b/xschem_library/examples/cmos_inv.sch @@ -1,4 +1,4 @@ -v {xschem version=2.9.7 file_version=1.2} +v {xschem version=2.9.8 file_version=1.2} G {} K {type=subcircuit format="@name @pinlist @symname WN=@WN WP=@WP LLN=@LLN LLP=@LLP m=@m"