diff --git a/src/callback.c b/src/callback.c index fa27f385..ce1b4a80 100644 --- a/src/callback.c +++ b/src/callback.c @@ -4809,12 +4809,20 @@ int callback(const char *win_path, int event, int mx, int my, KeySym key, int bu break; case ConfigureNotify: + if(xctx->semaphore >= 2 && !redraw_only) { + xctx->semaphore--; + return 0; + } dbg(1,"callback(): ConfigureNotify event: %s %dx%d\n", win_path, button, aux); resetwin(1, 1, 0, 0, 0); draw(); break; case MotionNotify: + if(xctx->semaphore >= 2 && !redraw_only) { + xctx->semaphore--; + return 0; + } handle_motion_notify(event, key, state, rstate, button, mx, my, aux, draw_xhair, enable_stretch, tabbed_interface, win_path, snap_cursor, wire_draw_active); diff --git a/src/token.c b/src/token.c index 555c688f..57517718 100644 --- a/src/token.c +++ b/src/token.c @@ -60,19 +60,21 @@ const char *tcl_hook2(const char *cmd) { static char *result = NULL; static const char *empty=""; - char *unescaped_res; if(cmd == NULL) { my_free(_ALLOC_ID_, &result); return empty; } if(strstr(cmd, "tcleval(") == cmd) { - unescaped_res = str_replace(cmd, "\\}", "}", 0, -1); + char *unescaped_res = NULL; + my_strdup2(_ALLOC_ID_, &unescaped_res, str_replace(cmd, "\\}", "}", 0, -1)); tclvareval("tclpropeval2 {", unescaped_res, "}" , NULL); + my_free(_ALLOC_ID_, &unescaped_res); + dbg(1, "tcl_hook2: tclresult()=%s\n", tclresult()); my_strdup2(_ALLOC_ID_, &result, tclresult()); - /* dbg(0, "tcl_hook2: return: %s\n", result);*/ + dbg(1, "tcl_hook2: return 1: %s\n", result); } else { - /* dbg(0, "tcl_hook2: return: %s\n", cmd); */ + dbg(1, "tcl_hook2: return 2: %s\n", cmd); my_strdup2(_ALLOC_ID_, &result, cmd); } return result; @@ -4312,10 +4314,15 @@ static char *get_pin_attr(const char *token, int inst, int engineering) * caveats: only one @spice_get_node is allowed in a string for now. */ -const char *spice_get_node(const char *token) +char *spice_get_node(const char *token) { const char *pos; + static char *s = NULL; + if(token == NULL) { + my_free(_ALLOC_ID_, &s); + return NULL; + } if((pos = strstr(token, "@spice_get_node "))) { char *node = NULL; char *token2 = NULL; @@ -4325,7 +4332,6 @@ const char *spice_get_node(const char *token) size_t len; double val = 0.0; const char *valstr; - const char *s; dbg(1, "token=%s\n", token); node = my_malloc(_ALLOC_ID_, strlen(token) + 1); @@ -4352,13 +4358,14 @@ const char *spice_get_node(const char *token) node[len] = ' '; node[len + 1] = '\0'; } - s = str_replace(token2, node, valstr, 0, 1); + my_strdup2(_ALLOC_ID_, &s, str_replace(token2, node, valstr, 0, 1)); dbg(1, "s=%s\n", s); my_free(_ALLOC_ID_, &token2); my_free(_ALLOC_ID_, &node); return s; } else { - return token; + my_strdup2(_ALLOC_ID_, &s, token); + return s; } } @@ -4526,8 +4533,7 @@ const char *translate(int inst, const char* s) /* sim_is_xyce = tcleval("sim_is_xyce")[0] == '1' ? 1 : 0; */ level = xctx->currsch; lcc = xctx->hier_attr; - size=CADCHUNKALLOC; - my_realloc(_ALLOC_ID_, &result,size); + STR_ALLOC(&result, result_pos, &size); result[0]='\0'; dbg(1, "translate(): substituting props in <%s>, instance <%s>\n", s ? s : "" , instname); @@ -4549,7 +4555,6 @@ const char *translate(int inst, const char* s) ) ) state=TOK_SEP; - STR_ALLOC(&result, result_pos, &size); STR_ALLOC(&token, token_pos, &sizetok); if(state==TOK_TOKEN) token[token_pos++]=(char)c; else if(state==TOK_SEP) @@ -4612,9 +4617,10 @@ const char *translate(int inst, const char* s) if (!strcmp( get_tok_value(prop,"name",0), token+2)) { if(strboolcmp(get_tok_value(prop,"spice_ignore",0), "true")) { const char *str_ptr = net_name(inst,i, &multip, 0, 0); - tmp = strlen(str_ptr) +100 ; + tmp = strlen(str_ptr); STR_ALLOC(&result, tmp + result_pos, &size); - result_pos += my_snprintf(result + result_pos, tmp, "%s", str_ptr); + memcpy(result+result_pos,str_ptr, tmp+1); + result_pos+=tmp; } break; } @@ -4725,13 +4731,14 @@ const char *translate(int inst, const char* s) len = 3; } else if(idx < 0) { valstr = "-"; - xctx->tok_size = 5; - len = 5; + xctx->tok_size = 1; + len = 1; } else { valstr = engineering ? dtoa_eng(val, xctx->ev_precision) : dtoa(val); len = xctx->tok_size; } if(len) { + len = strlen(valstr); STR_ALLOC(&result, len + result_pos, &size); memcpy(result+result_pos, valstr, len+1); result_pos += len; @@ -4833,6 +4840,7 @@ const char *translate(int inst, const char* s) len = xctx->tok_size; } if(len) { + len = strlen(valstr); STR_ALLOC(&result, len + result_pos, &size); memcpy(result+result_pos, valstr, len+1); result_pos += len; @@ -4934,6 +4942,7 @@ const char *translate(int inst, const char* s) len = xctx->tok_size; } if(len) { + len = strlen(valstr); STR_ALLOC(&result, len + result_pos, &size); memcpy(result+result_pos, valstr, len+1); result_pos += len; @@ -5000,6 +5009,7 @@ const char *translate(int inst, const char* s) len = xctx->tok_size; } if(len) { + len = strlen(valstr); STR_ALLOC(&result, len + result_pos, &size); memcpy(result+result_pos, valstr, len+1); result_pos += len; @@ -5133,6 +5143,7 @@ const char *translate(int inst, const char* s) len = xctx->tok_size; } if(len) { + len = strlen(valstr); STR_ALLOC(&result, len + result_pos, &size); memcpy(result+result_pos, valstr, len+1); result_pos += len; @@ -5273,7 +5284,9 @@ const char *translate(int inst, const char* s) else result[result_pos++]=(char)c; state=TOK_BEGIN; } /* else if(state==TOK_SEP) */ - else if(state==TOK_BEGIN) result[result_pos++]=(char)c; + else if(state==TOK_BEGIN) { + result[result_pos++]=(char)c; + } if(c=='\0') { result[result_pos]='\0'; @@ -5285,7 +5298,10 @@ const char *translate(int inst, const char* s) /* resolve spice_get_node patterns. * if result is like: 'tcleval(some_string)' pass it thru tcl evaluation so expressions * can be calculated */ - my_strdup2(_ALLOC_ID_, &result, spice_get_node(tcl_hook2(result))); + + + my_strdup2(_ALLOC_ID_, &result, tcl_hook2(result)); + my_strdup2(_ALLOC_ID_, &result, spice_get_node(result)); if(is_expr(result) && inst >= 0) { dbg(1, "translate(): expr():%s\n", result); diff --git a/src/xinit.c b/src/xinit.c index 94722cb5..b22808a8 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -981,6 +981,7 @@ static void xwin_exit(void) find_nth(NULL, "", "", 0, 0); /* clear static data in function */ trim_chars(NULL, ""); /* clear static data in function */ tcl_hook2(NULL); /* clear static data in function */ + spice_get_node(NULL); /* clear static data in function */ save_ascii_string(NULL, NULL, 0); /* clear static data in function */ eval_expr_clear_table(); /* clear expression parser data */ dbg(1, "xwin_exit(): removing font\n"); diff --git a/src/xschem.h b/src/xschem.h index 3d7a2b9f..ba31d21b 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1655,7 +1655,7 @@ extern Ptr_hashentry *ptr_hash_lookup(Ptr_hashtable *hashtable, extern char *trim_chars(const char *str, const char *sep); extern char *find_nth(const char *str, const char *sep, const char *quote, int keep_quote, int n); extern int isonlydigit(const char *s); -extern const char *spice_get_node(const char *token); +extern char *spice_get_node(const char *token); extern char *get_fqdevice(const char *param, int modelparam, const char *instname); extern const char *translate(int inst, const char* s); extern const char* translate2(Lcc *lcc, int level, char* s); diff --git a/src/xschem.tcl b/src/xschem.tcl index 8338d692..9d6208b7 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -6924,8 +6924,7 @@ proc tclpropeval {s instname symname} { # this hook is called in translate() if whole string is contained in a tcleval(...) construct proc tclpropeval2 {s} { - global debug_tcleval env path debug_var sch_basename - + global debug_tcleval env path debug_var sch_basename xschem_execute_scripts has_x set raw_level [xschem get raw_level] set netlist_type [xschem get netlist_type] # puts "tclpropeval2: s=|$s|" @@ -6956,9 +6955,43 @@ proc tclpropeval2 {s} { regsub {\)([ \n\t]*)$} $s {\1} s # puts "tclpropeval2: s=|$s|" # puts "tclpropeval2: subst $s=|[subst $s]|" - if { [catch {uplevel #0 "subst \{$s\}"} res] } { - if { $debug_tcleval > 0} { puts "tclpropeval2 warning: $s --> $res"} + if { $xschem_execute_scripts eq {no} } { set res ?\n + return $res + } elseif { $xschem_execute_scripts eq {ask}} { + if {[info exists has_x]} { + xschem set semaphore [expr {[xschem get semaphore] +1}] + set msg " Allow xschem to execute scripts embedded in schematics?\n\n" + append msg " WARNING:\n" + append msg " Allowing script execution is a potential security vulnerability,\n" + append msg " Do it only for schematics obtained from trusted sources.\n\n" + append msg " To avoid this message look for variable 'xschem_execute_scripts'\n" + append msg " in your xschemrc file,\n" + append msg " set it to 'yes' to permanently ENABLE scripts,\n" + append msg " or set it to 'no' to permanently DISABLE scripts.\n" + append msg " Current (default) setting is 'ask'." + + set answer [alert_ $msg {} 0 1] + xschem set semaphore [expr {[xschem get semaphore] -1}] + # set answer [tk_messageBox -parent [xschem get topwindow] -message $msg -type yesno] + if {$answer eq {1}} { + set xschem_execute_scripts yes + } elseif {$answer eq {0}} { + set xschem_execute_scripts no + } + } else { + set xschem_execute_scripts yes + } + } + if { $xschem_execute_scripts eq {yes} } { + focus [xschem get top_path].drw + if { [catch {uplevel #0 "subst \{$s\}"} res] } { + if { $debug_tcleval > 0} { puts "tclpropeval2 warning: $s --> $res"} + set res ?\n + } + } else { + set res ?\n + return $res } # puts "tclpropeval2: res=|$res|" return $res @@ -9731,7 +9764,8 @@ set tctx::global_list { top_is_subckt transparent_svg undo_type unselect_partial_sel_wires uppercase_subckt use_cursor_for_selection use_lab_wire use_label_prefix use_tclreadline user_wants_copy_cell verilog_2001 verilog_bitblast - viewdata_fileid viewdata_filename viewdata_w xschem_libs xschem_listen_port zoom_full_center + viewdata_fileid viewdata_filename viewdata_w xschem_execute_scripts xschem_libs + xschem_listen_port zoom_full_center } ## list of global arrays to save/restore on context switching @@ -11551,6 +11585,7 @@ set_ne terminal xterm # xschem tcp port number (listen to port and execute commands from there if set) # set a port number in xschemrc if you want accept remote connections. set_ne xschem_listen_port {} +set_ne xschem_execute_scripts ask # server for bespice waveform connection (listen to port and send commands to bespice if set) # set a port number in xschemrc if you want xschem to be able to cross-probe to bespice diff --git a/src/xschemrc b/src/xschemrc index 9295cfcc..21833d7a 100644 --- a/src/xschemrc +++ b/src/xschemrc @@ -535,6 +535,17 @@ #### set xschem listening port; default: not enabled # set xschem_listen_port 2021 +########################################################################### +#### EXECUTE SCRIPTS WITH 'tcleval(...)' or '@tcleval(...)' +########################################################################### +#### possible values: +#### yes: allow scripts. +#### no: do not allow scripts, always return empty result. +#### ask: (default) ask to the user if GUI is present. If no GUI is present +#### then allow scripts. +#### Default: ask +# set xschem_execute_scripts yes + ########################################################################### #### BESPICE WAVE SOCKET CONNECTION ########################################################################### diff --git a/tests/xschemtest.tcl b/tests/xschemtest.tcl index 83359879..df8a85d6 100644 --- a/tests/xschemtest.tcl +++ b/tests/xschemtest.tcl @@ -190,12 +190,12 @@ proc test_xschem_simulation {{f simulate_ff.sch}} { proc netlist_test {} { global netlist_dir foreach {f t h} { - rom8k.sch spice 834970168 + rom8k.sch spice 33778382 greycnt.sch verilog 1945914565 autozero_comp.sch spice 4088769413 test_generators.sch spice 2372200619 inst_sch_select.sch spice 1842909154 - test_bus_tap.sch spice 3363212799 + test_bus_tap.sch spice 1953773013 loading.sch vhdl 2975204502 mos_power_ampli.sch spice 2505489310 hierarchical_tedax.sch tedax 998070173