From 9eb4e9440cbc6480c3209bfb549d639be3cf2be2 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Fri, 21 Apr 2023 11:41:20 +0200 Subject: [PATCH] handle symbol_ref(param1,param2,...) symbol generator scripts, added some utility functions str_chars_replace(), is_symgen(), fix some quoting/backslash subst issues in get_sym_template() --- src/actions.c | 8 ++++- src/editprop.c | 18 +++++++++++ src/psprint.c | 21 ------------- src/save.c | 18 +++++++---- src/scheduler.c | 7 ----- src/token.c | 80 +++++++++++++++++++++++++++++++++++++++++-------- src/xinit.c | 1 + src/xschem.h | 2 ++ 8 files changed, 108 insertions(+), 47 deletions(-) diff --git a/src/actions.c b/src/actions.c index 428029ea..dd6ee636 100644 --- a/src/actions.c +++ b/src/actions.c @@ -221,7 +221,12 @@ int set_netlist_dir(int force, char *dir) const char *abs_sym_path(const char *s, const char *ext) { char c[PATH_MAX+1000]; - my_snprintf(c, S(c), "abs_sym_path {%s} {%s}", s, ext); + + if(is_symgen(s)) { + my_snprintf(c, S(c), "abs_sym_path [regsub {\\(.*} {%s} {}] {%s}", s, ext); + } else { + my_snprintf(c, S(c), "abs_sym_path {%s} {%s}", s, ext); + } tcleval(c); return tclresult(); } @@ -947,6 +952,7 @@ void attach_labels_to_inst(int interactive) /* offloaded from callback.c 201710 dbg(1, "attach_labels_to_inst(): %d %.16g %.16g %s\n", i, pinx0, piny0,labname); } } + if(first_call == 0) set_modify(1); my_free(_ALLOC_ID_, &prop); my_free(_ALLOC_ID_, &labname); my_free(_ALLOC_ID_, &type); diff --git a/src/editprop.c b/src/editprop.c index fc5432be..f05d3674 100644 --- a/src/editprop.c +++ b/src/editprop.c @@ -1546,6 +1546,24 @@ char *str_replace(const char *str, const char *rep, const char *with, int escape return result; } + +/* caller should free returned string */ +char *str_chars_replace(const char *str, const char *replace_set, const char with) +{ + char *res = NULL; + char *s; + my_strdup(_ALLOC_ID_, &res, str); + s = res; + dbg(0, "%s\n", res); + while( *s) { + if(strchr(replace_set, *s)) { + *s = with; + } + ++s; + } + return res; +} + /* x=0 use tcl text widget x=1 use vim editor x=2 only view data */ void edit_property(int x) { diff --git a/src/psprint.c b/src/psprint.c index 205c8ac5..381e81b7 100644 --- a/src/psprint.c +++ b/src/psprint.c @@ -24,27 +24,6 @@ #define X_TO_PS(x) ( (x+xctx->xorigin)* xctx->mooz ) #define Y_TO_PS(y) ( (y+xctx->yorigin)* xctx->mooz ) -#if 0 -* /* FIXME: overflow check. Not used, BTW */ -* static char *strreplace(char s[], char token[], char replace[]) -* { -* static char res[200]; -* char *p1, *p2; -* int l; -* -* res[0] = '\0'; -* l = strlen(token); -* p1 = p2 = s; -* while( (p2 = strstr(p1, token)) ) { -* strncat(res, p1, p2 - p1); -* strcat(res, replace); -* p1 = p2 = p2 + l; -* } -* strcat(res, p1); -* return res; -* } -#endif - char *utf8_enc[]={ "/recodedict 24 dict def\n", "/recode {recodedict begin /nco&na exch def\n", diff --git a/src/save.c b/src/save.c index 5c34091d..c54d5657 100644 --- a/src/save.c +++ b/src/save.c @@ -1639,12 +1639,17 @@ static void save_inst(FILE *fd, int select_only) } fprintf(fd, " %.16g %.16g %hd %hd ",inst[i].x0, inst[i].y0, inst[i].rot, inst[i].flip ); save_ascii_string(inst[i].prop_ptr,fd, 1); - if( embedded_saved && !embedded_saved[inst[i].ptr] && inst[i].embed) { - embedded_saved[inst[i].ptr] = 1; - fprintf(fd, "[\n"); - save_embedded_symbol( xctx->sym+inst[i].ptr, fd); - fprintf(fd, "]\n"); - xctx->sym[inst[i].ptr].flags |= EMBEDDED; + if(embedded_saved && !embedded_saved[inst[i].ptr]) { + if(is_symgen(inst[i].name)) { + embedded_saved[inst[i].ptr] = 1; + xctx->sym[inst[i].ptr].flags |= EMBEDDED; + } else if(inst[i].embed) { + embedded_saved[inst[i].ptr] = 1; + fprintf(fd, "[\n"); + save_embedded_symbol( xctx->sym+inst[i].ptr, fd); + fprintf(fd, "]\n"); + xctx->sym[inst[i].ptr].flags |= EMBEDDED; + } } } my_free(_ALLOC_ID_, &embedded_saved); @@ -3229,6 +3234,7 @@ int load_sym_def(const char *name, FILE *embed_fd, int embedded) case 'K': /* 1.2 file format: symbol attributes for schematics placed as symbols */ if (level==0) { load_ascii_string(&symbol[symbols].prop_ptr, lcc[level].fd); + dbg(1, "load_sym_def: K prop=\n%s\n", symbol[symbols].prop_ptr); if(!symbol[symbols].prop_ptr) break; my_strdup2(_ALLOC_ID_, &symbol[symbols].templ, get_tok_value(symbol[symbols].prop_ptr, "template", 0)); diff --git a/src/scheduler.c b/src/scheduler.c index dd8585c4..72662fab 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -3619,13 +3619,6 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg * testmode */ else if(!strcmp(argv[1], "test")) { - FILE *fp = fopen("/home/schippes/xschem-repo/trunk/xschem_library/examples/sr_flop.sym", "r"); - load_sym_def("sr_flop.sym", fp, 0); - fclose(fp); - - xctx->inst[xctx->instances -1].ptr = xctx->symbols - 1; - my_strdup(_ALLOC_ID_, &xctx->inst[xctx->instances -1].name, xctx->sym[xctx->symbols - 1].name); - Tcl_ResetResult(interp); } diff --git a/src/token.c b/src/token.c index b6574b62..0a287944 100644 --- a/src/token.c +++ b/src/token.c @@ -161,7 +161,30 @@ void check_unique_names(int rename) int_hash_free(&xctx->inst_table); } - +int is_symgen(const char *name) +{ + #ifdef __unix__ + int res = 0; + static regex_t *re = NULL; + + if(!name) { + if(re) { + regfree(re); + my_free(_ALLOC_ID_, &re); + } + return 0; + } + if(!re) { + re = my_malloc(_ALLOC_ID_, sizeof(regex_t)); + regcomp(re, "^[^ \\t()]+\\([^()]*\\)[ \\t]*$", REG_NOSUB | REG_EXTENDED); + } + if(!regexec(re, name, 0 , NULL, 0) ) res = 1; + /* regfree(&re); */ + return res; + #else + return 0; + #endif +} int match_symbol(const char *name) /* never returns -1, if symbol not found load systemlib/missing.sym */ { @@ -179,8 +202,42 @@ int match_symbol(const char *name) /* never returns -1, if symbol not found loa } if(!found) { - dbg(1, "match_symbol(): matching symbol not found:%s, loading\n",name); - load_sym_def(name, NULL, 0); /* append another symbol to the xctx->sym[] array */ + dbg(1, "match_symbol(): matching symbol not found:%s, loading\n",name); + + if(!is_symgen(name)) { + load_sym_def(name, NULL, 0); /* append another symbol to the xctx->sym[] array */ + } else { /* get symbol from generator script */ + FILE *fp; + char *cmd = NULL; + char *ss = NULL; + const char *s; + char *spc_idx; + struct stat buf; + + cmd = str_chars_replace(name, " (),", ' '); + spc_idx = strchr(cmd, ' '); + if(!spc_idx) goto end; + *spc_idx = '\0'; + s = abs_sym_path(cmd, ""); + if(stat(s, &buf)) { + load_sym_def(name, NULL, 0); + goto end; + } + my_strdup(_ALLOC_ID_, &ss, s); + *spc_idx = ' '; + my_strcat(_ALLOC_ID_, &ss, spc_idx); + fp = popen(ss, "r"); + dbg(0, "%p\n", fp); + dbg(0, "%s\n", s); + dbg(0, "%s\n", ss); + dbg(0, "is_symgen=%d\n", is_symgen(name)); + load_sym_def(name, fp, 1); + dbg(0, "%s\n", xctx->sym[xctx->symbols - 1].name); + pclose(fp); + my_free(_ALLOC_ID_, &ss); + end: + my_free(_ALLOC_ID_, &cmd); + } } dbg(1, "match_symbol(): returning %d\n",i); return i; @@ -482,19 +539,17 @@ const char *get_sym_template(char *s,char *extra) else if( state==TOK_VALUE && space && !quote) state=TOK_END; STR_ALLOC(&value, value_pos, &sizeval); STR_ALLOC(&token, token_pos, &sizetok); + if(c=='"') { + if(!escape) quote=!quote; + } if(state==TOK_BEGIN) { result[result_pos++] = (char)c; } else if(state==TOK_TOKEN) { - token[token_pos++]=(char)c; + /* token[token_pos++]=(char)c; */ + if( (with_quotes & 1) || escape || (c != '\\' && c != '"')) token[token_pos++]=(char)c; } else if(state==TOK_VALUE) { - if(c=='"') { - if(!escape) quote=!quote; - if((with_quotes & 1) || escape) value[value_pos++]=(char)c; - } - else if( (c=='\\') && (with_quotes & 2) ) ; /* dont store backslash */ - else value[value_pos++]=(char)c; - escape = (c=='\\' && !escape); - + /* if((with_quotes & 1) || escape) value[value_pos++]=(char)c; */ + if( (with_quotes & 1) || escape || (c != '\\' && c != '"')) value[value_pos++]=(char)c; } else if(state==TOK_END) { value[value_pos]='\0'; if((!extra || !strstr(extra, token)) && strcmp(token,"name") && strcmp(token,"spiceprefix")) { @@ -516,6 +571,7 @@ const char *get_sym_template(char *s,char *extra) token_pos=0; } } + escape = (c=='\\' && !escape); if(c=='\0') { break; } diff --git a/src/xinit.c b/src/xinit.c index 7d7239ef..3e05c554 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -666,6 +666,7 @@ static void delete_schematic_data(int delete_pixmap) remove_symbols(); str_replace(NULL, NULL, NULL, 0); escape_chars(NULL); + is_symgen(NULL); free_rawfile(0); free_xschem_data(); /* delete the xctx struct */ } diff --git a/src/xschem.h b/src/xschem.h index b7f4812e..2feb9c7b 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1479,6 +1479,8 @@ extern void hilight_parent_pins(void); extern void hilight_net_pin_mismatches(void); extern Node_hashentry **get_node_table_ptr(void); extern void change_elem_order(void); +extern int is_symgen(const char *name); +extern char *str_chars_replace(const char *str, const char *replace_set, const char with); extern char *str_replace(const char *str, const char *rep, const char *with, int escape); extern char *escape_chars(const char *source); extern int set_different_token(char **s,const char *new, const char *old);