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()

This commit is contained in:
Stefan Schippers 2020-09-29 11:17:10 +02:00
parent e7b0a5b9a3
commit f699d187e6
4 changed files with 67 additions and 33 deletions

View File

@ -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 ); 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); save_ascii_string(ptr[i].prop_ptr,fd);
fputc('\n' ,fd); fputc('\n' ,fd);
if( !strcmp(get_tok_value(ptr[i].prop_ptr, "embed", 0), "true") && if( !strcmp(get_tok_value(ptr[i].prop_ptr, "embed", 0), "true") ) {
!(instdef[ptr[i].ptr].flags & EMBEDDED)) { /* && !(instdef[ptr[i].ptr].flags & EMBEDDED)) { */
fprintf(fd, "[\n"); fprintf(fd, "[\n");
save_embedded_symbol( instdef+ptr[i].ptr, fd); save_embedded_symbol( instdef+ptr[i].ptr, fd);
fprintf(fd, "]\n"); fprintf(fd, "]\n");
@ -786,7 +786,6 @@ void read_xschem_file(FILE *fd)
if(inst_ptr[lastinst-1].name) { if(inst_ptr[lastinst-1].name) {
char *str; char *str;
int dbg_level = 1;
my_snprintf(name_embedded, S(name_embedded), 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)); "%s/.xschem_embedded_%d_%s", tclgetvar("XSCHEM_TMP_DIR"), getpid(), get_cell_w_ext(inst_ptr[lastinst-1].name, 0));
found=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); dbg(1, "read_xschem_file(): inst_ptr[lastinst-1].name=%s\n", inst_ptr[lastinst-1].name);
/* symbol has already been loaded: skip [..] */ /* symbol has already been loaded: skip [..] */
if(!strcmp(instdef[i].name, inst_ptr[lastinst-1].name)) { 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; found=1; break;
} }
/* if loading file coming back from embedded symbol delete temporary file */ /* if loading file coming back from embedded symbol delete temporary file */
if(!strcmp(name_embedded, instdef[i].name)) { if(!strcmp(name_embedded, instdef[i].name)) {
my_strdup(325, &instdef[i].name, inst_ptr[lastinst-1].name); my_strdup(325, &instdef[i].name, inst_ptr[lastinst-1].name);
xunlink(name_embedded); 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; found=1;break;
} }
} }
@ -817,7 +808,7 @@ void read_xschem_file(FILE *fd)
if(!found) load_sym_def(inst_ptr[lastinst-1].name, fd); if(!found) load_sym_def(inst_ptr[lastinst-1].name, fd);
else { else {
while(1) { /* skip embedded [ ... ] */ while(1) { /* skip embedded [ ... ] */
str = read_line(fd, dbg_level); str = read_line(fd, 1);
if(!str || !strncmp(str, "]", 1)) break; if(!str || !strncmp(str, "]", 1)) break;
fscanf(fd, "%*1[\n]"); fscanf(fd, "%*1[\n]");
} }
@ -1246,8 +1237,9 @@ void pop_undo(int redo)
* first look in already loaded symbols else inspect symbol file * first look in already loaded symbols else inspect symbol file
* do not load all symname data, just get the type * do not load all symname data, just get the type
* return symbol type in type pointer or "" if no type or no symbol found * return symbol type in type pointer or "" if no type or no symbol found
* if pintable given (!=NULL) hash all symbol pins */ * if pintable given (!=NULL) hash all symbol pins
void get_sym_type(const char *symname, char **type, struct int_hashentry **pintable) * 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; int i, c, n = 0;
char name[PATH_MAX]; char name[PATH_MAX];
@ -1275,8 +1267,11 @@ void get_sym_type(const char *symname, char **type, struct int_hashentry **pinta
if( !found ) { if( !found ) {
dbg(1, "get_sym_type(): open file %s, pintable %s\n",name, pintable ? "set" : "null"); 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 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); dbg(1, "get_sym_type(): Symbol not found: %s\n",name);
my_strdup2(1162, type, ""); my_strdup2(1162, type, "");
} else { } else {
@ -1286,6 +1281,7 @@ void get_sym_type(const char *symname, char **type, struct int_hashentry **pinta
box.prop_ptr = NULL; box.prop_ptr = NULL;
while(1) { while(1) {
if(fscanf(fd," %c",tag)==EOF) break; if(fscanf(fd," %c",tag)==EOF) break;
if(embed_fd && tag[0] == ']') break;
switch(tag[0]) { switch(tag[0]) {
case 'G': case 'G':
load_ascii_string(&globalprop,fd); 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(1166, &globalprop);
my_free(1167, &box.prop_ptr); 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); 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)); my_strncpy(symname, add_ext(name, ".sym"), S(symname));
for(i = 0; i < HASHSIZE; i++) pintable[i] = NULL; for(i = 0; i < HASHSIZE; i++) pintable[i] = NULL;
/* hash all symbol pins with their position into pintable hash*/ /* 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 */ if(symtype[0]) { /* found a .sym for current .sch LCC instance */
Box *box = NULL; Box *box = NULL;
box = (Box *) my_malloc(1168, sizeof(Box) * instdef[pos].rects[PINLAYER]); box = (Box *) my_malloc(1168, sizeof(Box) * instdef[pos].rects[PINLAYER]);
@ -1504,7 +1500,6 @@ void calc_symbol_bbox(int pos)
* instdef * instdef
* lastinstdef * lastinstdef
* has_x * has_x
* lcc (static global)
*/ */
int load_sym_def(const char *name, FILE *embed_fd) 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 incremented_level=0;
int level = 0; int level = 0;
int max_level; int max_level;
long filepos;
char sympath[PATH_MAX]; char sympath[PATH_MAX];
int i,c, k, poly_points; int i,c, k, poly_points;
char *aux_ptr=NULL; 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); my_strdup(352, &instdef[lastinstdef].name,name);
while(1) 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(fscanf(lcc[level].fd," %c",tag)==EOF) {
if (level) { if (level) {
dbg(1, "l_s_d(): fclose1, level=%d, fd=%p\n", level, lcc[level].fd); 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; endfile = 1;
continue; 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 */ char c;
get_sym_type(symname, &symtype, NULL); 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); 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 */ if( /* add here symbol types not to consider when loading schematic-as-symbol instances */
!strcmp(symtype, "logo") || !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 */ /* replace i/o/iopin.sym filename with better looking (for LCC symbol) pins */
use_lcc_pins(level, symtype, &sympath); 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) { if ((fd_tmp = fopen(sympath, "r")) == NULL) {
char c;
fprintf(errfp, "l_s_d(): unable to open file to read schematic: %s\n", sympath); 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) { if (level+1 >= max_level) {
my_realloc(653, &lcc, (max_level + 1) * sizeof(struct Lcc)); my_realloc(653, &lcc, (max_level + 1) * sizeof(struct Lcc));
max_level++; max_level++;
} }
dbg(1, "l_s_d(): fopen2(%s), level=%d, fd=%p\n", sympath, level, fd_tmp);
++level; ++level;
incremented_level = 1; incremented_level = 1;
lcc[level].fd = fd_tmp; lcc[level].fd = fd_tmp;
@ -1949,14 +1972,19 @@ int load_sym_def(const char *name, FILE *embed_fd)
break; break;
case '[': case '[':
while(1) { /* skip embedded [ ... ] */ 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; if(!skip_line || !strncmp(skip_line, "]", 1)) break;
fscanf(lcc[level].fd, "%*1[\n]"); fscanf(lcc[level].fd, "%*1[\n]");
} }
break; break;
case ']': case ']':
read_line(lcc[level].fd, 0); if(level) {
endfile=1; my_free(0, &lcc[level].prop_ptr);
my_free(0, &lcc[level].symname);
--level;
} else {
endfile=1;
}
break; break;
default: default:
if( tag[0] == '{' ) ungetc(tag[0], lcc[level].fd); if( tag[0] == '{' ) ungetc(tag[0], lcc[level].fd);
@ -2270,8 +2298,6 @@ void round_schematic_to_grid(double cadsnap)
break; break;
} }
} }
} }
/* what: */ /* what: */

View File

@ -806,6 +806,7 @@ void preview_window(const char *what, const char *tk_win_path, const char *filen
remove_symbols(); remove_symbols();
my_strncpy(schematic[currentsch] , "", S(schematic[currentsch])); my_strncpy(schematic[currentsch] , "", S(schematic[currentsch]));
currentsch--; currentsch--;
clear_drawing();
pop_undo(0); pop_undo(0);
modified = save_mod; modified = save_mod;
set_modify(modified); set_modify(modified);

View File

@ -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 {} G {}
K {type=subcircuit K {type=subcircuit
format="@name @pinlist @symname WN_FB=@WN_FB WP_FB=@WP_FB" 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 430 -300 450 -300 {lab=#net1}
N 450 -680 450 -300 {lab=#net1} N 450 -680 450 -300 {lab=#net1}
N 430 -680 450 -680 {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} 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 {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 {iopin.sym} 250 -300 0 1 {name=p1 lab=A}
C {title.sym} 160 -30 0 0 {name=l1 author="Stefan Schippers"} 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}

View File

@ -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 {} G {}
K {type=subcircuit K {type=subcircuit
format="@name @pinlist @symname WN=@WN WP=@WP LLN=@LLN LLP=@LLP m=@m" format="@name @pinlist @symname WN=@WN WP=@WP LLN=@LLN LLP=@LLP m=@m"