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 );
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: */

View File

@ -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);

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 {}
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}

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