/* File: scheduler.c * * This file is part of XSCHEM, * a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit * simulation. * Copyright (C) 1998-2020 Stefan Frederik Schippers * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xschem.h" void statusmsg(char str[],int n) { static char s[2048]; if(!has_x) return; tclsetvar("infowindow_text", str); if(n==2) { dbg(3, "statusmsg(): n = 2, s = %s\n", s); tcleval("infowindow"); } else { my_snprintf(s, S(s), ".statusbar.1 configure -text $infowindow_text", str); dbg(3, "statusmsg(): n = %d, %s\n", n, s); dbg(3, " --> $infowindow_text = %s\n", tclgetvar("infowindow_text")); tcleval(s); } } int get_instance(const char *s) { int i, found=0; for(i=0;ixctx.instances) { Tcl_AppendResult(interp, "Index out of range", NULL); return -1; } return i; } /* can be used to reach C functions from the Tk shell. */ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * argv[]) { int i; char name[1024]; /* overflow safe 20161122 */ Tcl_ResetResult(interp); if(argc<2) { Tcl_AppendResult(interp, "Missing arguments.", NULL); return TCL_ERROR; } if(debug_var>=2) { int i; fprintf(errfp, "xschem():"); for(i=0; i=3) { int n = atoi(argv[2]); descend_schematic(n); } else { descend_schematic(0); } Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"descend_symbol")) { descend_symbol(); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"go_back")) { go_back(1); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"zoom_full")) { zoom_full(1, 0); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"zoom_selected")) { zoom_full(1, 1); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"zoom_hilighted")) { zoom_full(1, 2); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"zoom_box")) { double x1, y1, x2, y2, yy1, factor; dbg(1, "xschem zoom_box: argc=%d, argv[2]=%s\n", argc, argv[2]); if(argc==6 || argc == 7) { x1 = atof(argv[2]); y1 = atof(argv[3]); x2 = atof(argv[4]); y2 = atof(argv[5]); if(argc == 7) factor = atof(argv[6]); else factor = 1.; if(factor == 0.) factor = 1.; RECTORDER(x1,y1,x2,y2); xctx.xorigin=-x1;xctx.yorigin=-y1; xctx.zoom=(x2-x1)/(areaw-4*lw); yy1=(y2-y1)/(areah-4*lw); if(yy1>xctx.zoom) xctx.zoom=yy1; xctx.mooz=1/xctx.zoom; xctx.xorigin=xctx.xorigin+areaw*xctx.zoom*(1-1/factor)/2; xctx.yorigin=xctx.yorigin+areah*xctx.zoom*(1-1/factor)/2; xctx.zoom*= factor; xctx.mooz=1/xctx.zoom; change_linewidth(-1.); draw(); } else { ui_state |=MENUSTARTZOOM; } Tcl_ResetResult(interp); } else if(!strcmp(argv[1], "load_symbol")) { int save, missing = 0; if(argc > 2) { save = xctx.symbols; match_symbol(argv[2]); if( xctx.symbols != save && !strcmp( xctx.sym[xctx.symbols - 1].type, "missing") ) { missing = 1; remove_symbol( xctx.symbols - 1); } } Tcl_ResetResult(interp); Tcl_AppendResult(interp, missing ? "0" : "1", NULL); } else if(!strcmp(argv[1],"place_symbol")) { int ret; semaphore++; mx_double_save = mousex_snap; my_double_save = mousey_snap; if(argc == 4) { ret = place_symbol(-1,argv[2],mousex_snap, mousey_snap, 0, 0, argv[3], 4, 1); } else if(argc == 3) { ret = place_symbol(-1,argv[2],mousex_snap, mousey_snap, 0, 0, NULL, 4, 1); } else { ret = place_symbol(-1,NULL,mousex_snap, mousey_snap, 0, 0, NULL, 4, 1); } if(ret) { mousey_snap = my_double_save; mousex_snap = mx_double_save; move_objects(BEGIN,0,0,0); ui_state |= PLACE_SYMBOL; } semaphore--; Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"place_text")) { ui_state |= MENUSTARTTEXT; /* place_text(0,mousex_snap, mousey_snap); */ /* move_objects(BEGIN,0,0,0); */ Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"zoom_out")) { view_unzoom(0.0); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"line_width") && argc==3) { change_linewidth(atof(argv[2])); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"select_all")) { select_all(); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"zoom_in")) { view_zoom(0.0); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"copy_objects")) { copy_objects(BEGIN); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"move_objects")) { if(argc==4) { move_objects(BEGIN,0,0,0); move_objects( END,0,atof(argv[2]), atof(argv[3])); } else move_objects(BEGIN,0,0,0); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"log")) { static int opened=0; if(argc==3 && opened==0 ) { errfp = fopen(argv[2], "w");opened=1; } /* added check to avoid multiple open */ else if(argc==2 && opened==1) { fclose(errfp); errfp=stderr;opened=0; } Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"exit")) { if(modified && has_x) { tcleval("tk_messageBox -type okcancel -message {UNSAVED data: want to exit?}"); if(strcmp(tclresult(),"ok")==0) tcleval( "exit"); } else tcleval( "exit"); Tcl_ResetResult(interp); } else if(!strcmp(argv[1], "rebuild_connectivity")) { prepared_hash_instances=0; prepared_hash_wires=0; prepared_netlist_structs=0; prepared_hilight_structs=0; prepare_netlist_structs(0); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"clear")) { int cancel; cancel=save(1); if(!cancel){ char name[PATH_MAX]; struct stat buf; int i; xctx.currsch = 0; unselect_all(); remove_symbols(); clear_drawing(); if(argc>=3 && !strcmp(argv[2],"SYMBOL")) { netlist_type = CAD_SYMBOL_ATTRS; tclsetvar("netlist_type","symbol"); for(i=0;;i++) { if(i == 0) my_snprintf(name, S(name), "%s.sym", "untitled"); else my_snprintf(name, S(name), "%s-%d.sym", "untitled", i); if(stat(name, &buf)) break; } my_snprintf(xctx.sch[xctx.currsch], S(xctx.sch[xctx.currsch]), "%s/%s", pwd_dir, name); my_strncpy(xctx.current_name, name, S(xctx.current_name)); } else { netlist_type = CAD_SPICE_NETLIST; tclsetvar("netlist_type","spice"); for(i=0;;i++) { if(i == 0) my_snprintf(name, S(name), "%s.sch", "untitled"); else my_snprintf(name, S(name), "%s-%d.sch", "untitled", i); if(stat(name, &buf)) break; } my_snprintf(xctx.sch[xctx.currsch], S(xctx.sch[xctx.currsch]), "%s/%s", pwd_dir, name); my_strncpy(xctx.current_name, name, S(xctx.current_name)); } draw(); set_modify(0); prepared_hash_instances=0; prepared_hash_wires=0; prepared_netlist_structs=0; prepared_hilight_structs=0; if(has_x) { tcleval( "wm title . \"xschem - [file tail [xschem get schname]]\""); /* 20150417 set window and icon title */ tcleval( "wm iconname . \"xschem - [file tail [xschem get schname]]\""); } } Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"set_modify")) { set_modify(1); Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"reload")) { unselect_all(); remove_symbols(); load_schematic(1, xctx.sch[xctx.currsch], 1); if(argc >= 3 && !strcmp(argv[2], "zoom_full") ) { zoom_full(1, 0); } else { draw(); } Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"debug")) { if(argc==3) { debug_var=atoi(argv[2]); tclsetvar("tcl_debug",argv[2]); } Tcl_ResetResult(interp); } else if(!strcmp(argv[1], "bbox")) { if(argc == 3) { if(!strcmp(argv[2], "end")) { bbox(SET , 0.0 , 0.0 , 0.0 , 0.0); draw(); bbox(END , 0.0 , 0.0 , 0.0 , 0.0); } else if(!strcmp(argv[2], "begin")) { bbox(BEGIN,0.0, 0.0, 0.0, 0.0); } } Tcl_ResetResult(interp); } else if(!strcmp(argv[1], "setprop")) { int inst, fast=0; if(argc >= 6) { if(!strcmp(argv[5], "fast")) { fast = 1; argc = 5; } } else if(argc >= 5) { if(!strcmp(argv[4], "fast")) { fast = 1; argc = 4; } } if(argc < 4) { Tcl_AppendResult(interp, "xschem setprop needs 2 or 3 additional arguments", NULL); return TCL_ERROR; } if( (inst = get_instance(argv[2])) < 0 ) { Tcl_AppendResult(interp, "xschem setprop: instance not found", NULL); return TCL_ERROR; } else { bbox(BEGIN,0.0,0.0,0.0,0.0); symbol_bbox(inst, &xctx.inst[inst].x1, &xctx.inst[inst].y1, &xctx.inst[inst].x2, &xctx.inst[inst].y2); bbox(ADD, xctx.inst[inst].x1, xctx.inst[inst].y1, xctx.inst[inst].x2, xctx.inst[inst].y2); push_undo(); set_modify(1); if(!fast) { prepared_hash_instances=0; prepared_netlist_structs=0; prepared_hilight_structs=0; } hash_all_names(inst); if(argc >= 5) { new_prop_string(inst, subst_token(xctx.inst[inst].prop_ptr, argv[3], argv[4]),0, dis_uniq_names); } else {/* assume argc == 4 */ new_prop_string(inst, subst_token(xctx.inst[inst].prop_ptr, argv[3], NULL),0, dis_uniq_names); } my_strdup2(367, &xctx.inst[inst].instname, get_tok_value(xctx.inst[inst].prop_ptr, "name",0)); /* new symbol bbox after prop changes (may change due to text length) */ symbol_bbox(inst, &xctx.inst[inst].x1, &xctx.inst[inst].y1, &xctx.inst[inst].x2, &xctx.inst[inst].y2); bbox(ADD, xctx.inst[inst].x1, xctx.inst[inst].y1, xctx.inst[inst].x2, xctx.inst[inst].y2); /* redraw symbol with new props */ bbox(SET,0.0,0.0,0.0,0.0); draw(); bbox(END,0.0,0.0,0.0,0.0); } Tcl_ResetResult(interp); } else if(!strcmp(argv[1], "replace_symbol")) { int inst, fast = 0; if(argc == 6) { if(!strcmp(argv[5], "fast")) { fast = 1; argc = 5; } } if(argc!=5) { Tcl_AppendResult(interp, "xschem replace_symbol needs 3 additional arguments", NULL); return TCL_ERROR; } if(!strcmp(argv[2],"instance")) { if( (inst = get_instance(argv[3])) < 0 ) { Tcl_AppendResult(interp, "xschem replace_symbol: instance not found", NULL); return TCL_ERROR; } else { char symbol[PATH_MAX]; int sym_number, prefix, cond; char *type; char *name=NULL; char *ptr=NULL; bbox(BEGIN,0.0,0.0,0.0,0.0); my_strncpy(symbol, argv[4], S(symbol)); push_undo(); set_modify(1); if(!fast) { prepared_hash_instances=0; prepared_netlist_structs=0; prepared_hilight_structs=0; } sym_number=match_symbol(symbol); if(sym_number>=0) { prefix=(get_tok_value( (xctx.sym+sym_number)->templ , "name",0))[0]; /* get new symbol prefix */ } else prefix = 'x'; delete_inst_node(inst); /* 20180208 fix crashing bug: delete node info if changing symbol */ /* if number of pins is different we must delete these data *before* */ /* changing ysmbol, otherwise i might end up deleting non allocated data. */ my_strdup(369, &xctx.inst[inst].name,symbol); xctx.inst[inst].ptr=sym_number; bbox(ADD, xctx.inst[inst].x1, xctx.inst[inst].y1, xctx.inst[inst].x2, xctx.inst[inst].y2); my_strdup(370, &name, xctx.inst[inst].instname); if(name && name[0] ) { /* 20110325 only modify prefix if prefix not NUL */ if(prefix) name[0]=prefix; /* change prefix if changing symbol type; */ my_strdup(371, &ptr,subst_token(xctx.inst[inst].prop_ptr, "name", name) ); hash_all_names(inst); new_prop_string(inst, ptr,0, dis_uniq_names); /* set new prop_ptr */ my_strdup2(372, &xctx.inst[inst].instname, get_tok_value(xctx.inst[inst].prop_ptr, "name",0)); type=xctx.sym[xctx.inst[inst].ptr].type; cond= !type || !IS_LABEL_SH_OR_PIN(type); if(cond) xctx.inst[inst].flags|=2; else xctx.inst[inst].flags &=~2; my_free(922, &ptr); } my_free(923, &name); /* new symbol bbox after prop changes (may change due to text length) */ symbol_bbox(inst, &xctx.inst[inst].x1, &xctx.inst[inst].y1, &xctx.inst[inst].x2, &xctx.inst[inst].y2); bbox(ADD, xctx.inst[inst].x1, xctx.inst[inst].y1, xctx.inst[inst].x2, xctx.inst[inst].y2); /* redraw symbol */ bbox(SET,0.0,0.0,0.0,0.0); draw(); bbox(END,0.0,0.0,0.0,0.0); } } Tcl_ResetResult(interp); } else if( !strcmp(argv[1],"symbols")) { int i; char n[100]; Tcl_AppendResult(interp, "\n", NULL); for(i=0; i 2 && !strcmp(argv[2], "instance")) { int i; const char *tmp; if(argc!=5 && argc !=4) { Tcl_AppendResult(interp, "'xschem getprop instance' needs 1 or 2 additional arguments", NULL); return TCL_ERROR; } if( (i = get_instance(argv[3])) < 0 ) { Tcl_AppendResult(interp, "xschem getprop: instance not found", NULL); return TCL_ERROR; } if(argc == 4) { Tcl_AppendResult(interp, xctx.inst[i].prop_ptr, NULL); } else if(!strcmp(argv[4],"cell::name")) { tmp = xctx.inst[i].name; Tcl_AppendResult(interp, tmp, NULL); } else if(strstr(argv[4], "cell::") ) { tmp = get_tok_value( (xctx.inst[i].ptr+ xctx.sym)->prop_ptr, argv[4]+6, 0); dbg(1, "xschem getprop: looking up instance %d prop cell::|%s| : |%s|\n", i, argv[4]+6, tmp); Tcl_AppendResult(interp, tmp, NULL); } else { Tcl_AppendResult(interp, get_tok_value(xctx.inst[i].prop_ptr, argv[4], 0), NULL); } } else if(argc > 2 && !strcmp(argv[2], "instance_pin")) { /* 0 1 2 3 4 5 */ /* xschem getprop instance_pin X10 PLUS pin_attr */ /* xschem getprop instance_pin X10 1 pin_attr */ int inst, n=-1, tmp; char *subtok=NULL; const char *value=NULL; if(argc != 6 && argc != 5) { Tcl_AppendResult(interp, "xschem getprop instance_pin needs 2 or 3 additional arguments", NULL); return TCL_ERROR; } if( (inst = get_instance(argv[3])) < 0 ) { Tcl_AppendResult(interp, "xschem getprop: instance not found", NULL); return TCL_ERROR; } if(isonlydigit(argv[4])) { n = atoi(argv[4]); } else { xSymbol *ptr = xctx.inst[inst].ptr+ xctx.sym; for(n = 0; n < ptr->rects[PINLAYER]; n++) { char *prop = ptr->rect[PINLAYER][n].prop_ptr; if(!strcmp(get_tok_value(prop, "name",0), argv[4])) break; } } if(n>=0 && n < (xctx.inst[inst].ptr+ xctx.sym)->rects[PINLAYER]) { if(argc == 5) { Tcl_AppendResult(interp, (xctx.inst[inst].ptr+ xctx.sym)->rect[PINLAYER][n].prop_ptr, NULL); } else { tmp = 100 + strlen(argv[4]) + strlen(argv[5]); subtok = my_malloc(83,tmp); my_snprintf(subtok, tmp, "%s(%s)", argv[5], argv[4]); value = get_tok_value(xctx.inst[inst].prop_ptr,subtok,0); if(!value[0]) { my_snprintf(subtok, tmp, "%s(%d)", argv[5], n); value = get_tok_value(xctx.inst[inst].prop_ptr,subtok,0); } if(!value[0]) { value = get_tok_value((xctx.inst[inst].ptr+ xctx.sym)->rect[PINLAYER][n].prop_ptr,argv[5],0); } if(value[0] != 0) { char *ss; int slot; if( (ss = strchr(xctx.inst[inst].instname, ':')) ) { sscanf(ss + 1, "%d", &slot); if(strstr(value, ":")) value = find_nth(value, ':', slot); } Tcl_AppendResult(interp, value, NULL); } my_free(924, &subtok); } } } else if( !strcmp(argv[2],"symbol")) { int i, found=0; if(argc!=5 && argc !=4) { Tcl_AppendResult(interp, "xschem getprop needs 2 or 3 additional arguments", NULL); return TCL_ERROR; } for(i=0; irects[PINLAYER]; for(p=0;prect[PINLAYER][p].prop_ptr, argv[3], 0), "} } ", NULL); } else { Tcl_AppendResult(interp, "{ {", s, "} {", (xctx.inst[i].ptr+ xctx.sym)->rect[PINLAYER][p].prop_ptr, "} } ", NULL); } } } else if(!strcmp(argv[1],"instance_net")) { int no_of_pins, i, p, mult; const char *str_ptr=NULL; if( argc <4) { Tcl_AppendResult(interp, "xschem instance_net needs 2 additional arguments", NULL); return TCL_ERROR; } if( (i = get_instance(argv[2])) < 0 ) { Tcl_AppendResult(interp, "xschem getprop: instance not found", NULL); return TCL_ERROR; } prepare_netlist_structs(0); no_of_pins= (xctx.inst[i].ptr+ xctx.sym)->rects[PINLAYER]; for(p=0;prect[PINLAYER][p].prop_ptr,"name",0), argv[3])) { str_ptr = net_name(i,p,&mult, 0); break; } } /* /20171029 */ if(p>=no_of_pins) { Tcl_AppendResult(interp, "Pin not found", NULL); return TCL_ERROR; } Tcl_AppendResult(interp, str_ptr, NULL); } else if(!strcmp(argv[1],"selected_set")) { int n, i; char *res = NULL; rebuild_selected_array(); for(n=0; n < lastselected; n++) { if(selectedgroup[n].type == ELEMENT) { i = selectedgroup[n].n; my_strcat(645, &res, xctx.inst[i].instname); if(n < lastselected-1) my_strcat(646, &res, " "); } } Tcl_AppendResult(interp, res, NULL); my_free(925, &res); } else if(!strcmp(argv[1],"select")) { if(argc<3) { Tcl_AppendResult(interp, "xschem select: missing arguments.", NULL); return TCL_ERROR; } if(!strcmp(argv[2],"instance") && argc==4) { char *endptr; int i,found=0; int n; n=strtol(argv[3], &endptr, 10); /* 20171006 find by instance name */ for(i=0;i= 0) { select_element(n, SELECTED, 0, 0); found = 1; } if(!found) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "xschem select instance: instance not found", NULL); return TCL_ERROR; } } else if(!strcmp(argv[2],"wire") && argc==4) { int n=atol(argv[3]); if(n= 0) select_wire(atol(argv[3]), SELECTED, 0); } else if(!strcmp(argv[2],"text") && argc==4) { int n=atol(argv[3]); if(n= 0) select_text(atol(argv[3]), SELECTED, 0); } drawtemparc(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0, 0.0); drawtemprect(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0); drawtempline(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0); } else if(!strcmp(argv[1],"instance")) { if(argc==7) place_symbol(-1, argv[2], atof(argv[3]), atof(argv[4]), atoi(argv[5]), atoi(argv[6]),NULL, 3, 1); else if(argc==8) place_symbol(-1, argv[2], atof(argv[3]), atof(argv[4]), atoi(argv[5]), atoi(argv[6]), argv[7], 3, 1); else if(argc==9) { int x = !(atoi(argv[8])); place_symbol(-1, argv[2], atof(argv[3]), atof(argv[4]), atoi(argv[5]), atoi(argv[6]), argv[7], 0, x); } } else if(!strcmp(argv[1],"arc")) { ui_state |= MENUSTARTARC; } else if(!strcmp(argv[1],"circle")) { ui_state |= MENUSTARTCIRCLE; } else if(!strcmp(argv[1],"snap_wire")) { ui_state |= MENUSTARTSNAPWIRE; } else if(!strcmp(argv[1],"wire")) { double x1,y1,x2,y2; int pos, save; const char *prop; if(argc>=6) { x1=atof(argv[2]); y1=atof(argv[3]); x2=atof(argv[4]); y2=atof(argv[5]); ORDER(x1,y1,x2,y2); pos=-1; if(argc >= 7) pos=atol(argv[6]); if(argc == 8) prop = argv[7]; else prop = NULL; push_undo(); storeobject(pos, x1,y1,x2,y2,WIRE,0,0,prop); prepared_hilight_structs=0; prepared_netlist_structs=0; prepared_hash_wires=0; save = draw_window; draw_window = 1; drawline(WIRELAYER,NOW, x1,y1,x2,y2, 0); draw_window = save; } else ui_state |= MENUSTARTWIRE; } else if(!strcmp(argv[1],"line")) { double x1,y1,x2,y2; int pos, save; if(argc>=6) { x1=atof(argv[2]); y1=atof(argv[3]); x2=atof(argv[4]); y2=atof(argv[5]); ORDER(x1,y1,x2,y2); pos=-1; if(argc==7) pos=atol(argv[6]); storeobject(pos, x1,y1,x2,y2,LINE,rectcolor,0,NULL); save = draw_window; draw_window = 1; drawline(rectcolor,NOW, x1,y1,x2,y2, 0); draw_window = save; } else ui_state |= MENUSTARTLINE; } else if(!strcmp(argv[1],"rect")) { double x1,y1,x2,y2; int pos, save; if(argc>=6) { x1=atof(argv[2]); y1=atof(argv[3]); x2=atof(argv[4]); y2=atof(argv[5]); ORDER(x1,y1,x2,y2); pos=-1; if(argc==7) pos=atol(argv[6]); storeobject(pos, x1,y1,x2,y2,xRECT,rectcolor,0,NULL); save = draw_window; draw_window = 1; drawrect(rectcolor,NOW, x1,y1,x2,y2, 0); draw_window = save; } else ui_state |= MENUSTARTRECT; } else if(!strcmp(argv[1],"polygon")) { ui_state |= MENUSTARTPOLYGON; } else if(!strcmp(argv[1],"align")) { push_undo(); round_schematic_to_grid(cadsnap); set_modify(1); prepared_hash_instances=0; prepared_hash_wires=0; prepared_netlist_structs=0; prepared_hilight_structs=0; draw(); } else if(!strcmp(argv[1],"saveas")) { if(argc == 4) { const char *f; f = !strcmp(argv[2],"") ? NULL : argv[2]; if(!strcmp(argv[3], "SCHEMATIC")) saveas(f, SCHEMATIC); else if(!strcmp(argv[3], "SYMBOL")) saveas(f, SYMBOL); else saveas(f, SCHEMATIC); } else if(argc == 3) { const char *f; f = !strcmp(argv[2],"") ? NULL : argv[2]; saveas(f, SCHEMATIC); } else saveas(NULL, SCHEMATIC); } else if(!strcmp(argv[1],"save")) { dbg(1, "xschem(): saving: current schematic\n"); if(!strcmp(xctx.sch[xctx.currsch],"")) { /* 20170622 check if unnamed schematic, use saveas in this case... */ saveas(NULL, SCHEMATIC); } else { save(0); } } else if(!strcmp(argv[1],"windows")) { printf("top win:%lx\n", Tk_WindowId(Tk_Parent(Tk_MainWindow(interp)))); } else if(!strcmp(argv[1],"globals")) { printf("*******global variables:*******\n"); printf("netlist_dir=%s\n", netlist_dir? netlist_dir: ""); printf("lw=%d\n", lw); printf("wires=%d\n", xctx.wires); printf("instances=%d\n", xctx.instances); printf("symbols=%d\n", xctx.symbols); printf("lastselected=%d\n", lastselected); printf("texts=%d\n", xctx.texts); printf("maxt=%d\n", xctx.maxt); printf("maxw=%d\n", xctx.maxw); printf("maxi=%d\n", xctx.maxi); printf("max_selected=%d\n", max_selected); printf("zoom=%.16g\n", xctx.zoom); printf("xorigin=%.16g\n", xctx.xorigin); printf("yorigin=%.16g\n", xctx.yorigin); for(i=0;i<8;i++) { printf("rects[%d]=%d\n", i, xctx.rects[i]); printf("lines[%d]=%d\n", i, xctx.lines[i]); printf("maxr[%d]=%d\n", i, xctx.maxr[i]); printf("maxl[%d]=%d\n", i, xctx.maxl[i]); } printf("current_name=%s\n", xctx.current_name); printf("currsch=%d\n", xctx.currsch); for(i=0;i<=xctx.currsch;i++) { printf("previous_instance[%d]=%d\n",i,xctx.previous_instance[i]); printf("sch_path[%d]=%s\n",i,xctx.sch_path[i]? xctx.sch_path[i]:""); printf("sch[%d]=%s\n",i,xctx.sch[i]); } printf("modified=%d\n", modified); printf("color_ps=%d\n", color_ps); printf("a3page=%d\n", a3page); printf("hilight_nets=%d\n", hilight_nets); printf("need_rebuild_selected_array=%d\n", need_rebuild_selected_array); printf("******* end global variables:*******\n"); } else if(!strcmp(argv[1],"help")) { printf("xschem : function used to communicate with the C program\n"); printf("Usage:\n"); printf(" xschem callback X-event_type mousex mousey Xkeysym mouse_button Xstate\n"); printf(" can be used to send any event to the application\n"); printf(" xschem netlist\n"); printf(" generates a netlist in the selected format for the current schematic\n"); printf(" xschem simulate\n"); printf(" launches the currently set simulator on the generated netlist\n"); printf(" xschem redraw\n"); printf(" Redraw the window\n"); printf(" xschem new_window library/cell\n"); printf(" start a new window optionally with specified cell\n"); printf(" xschem schematic_in_new_window \n"); printf(" start a new window with selected element schematic\n"); printf(" xschem symbol_in_new_window \n"); printf(" start a new window with selected element schematic\n"); printf(" xschem globals\n"); printf(" print information about global variables\n"); printf(" xschem inst_ptr n\n"); printf(" return inst_ptr of inst[n]\n"); printf(" xschem netlist\n"); printf(" perform a global netlist on current schematic\n"); printf(" xschem netlist_type type\n"); printf(" set netlist type to , currently spice, vhdl, verilog or tedax\n"); printf(" xschem netlist_show yes|no\n"); printf(" show or not netlist in a window\n"); printf(" xschem save [library/name]\n"); printf(" save current schematic, optionally a lib/name can be given\n"); printf(" xschem saveas\n"); printf(" save current schematic, asking for a filename\n"); printf(" xschem load library/cell\n"); printf(" load specified cell from library\n"); printf(" xschem load_symbol library/cell\n"); printf(" load specified cell symbol view from library\n"); printf(" xschem reload\n"); printf(" reload current cell from library\n"); printf(" xschem instance library/cell x y rot flip [property string]\n"); printf(" place instance cell of the given library at x,y, rot, flip\n"); printf(" can also be given a property string\n"); printf(" xschem rect x1 y1 x2 y2 [pos]\n"); printf(" place rectangle, optionally at pos (position in database)\n"); printf(" xschem line x1 y1 x2 y2 [pos]\n"); printf(" place line, optionally at pos (position in database)\n"); printf(" xschem wire x1 y1 x2 y2 [pos]\n"); printf(" place wire, optionally at pos (position in database)\n"); printf(" xschem select instance|wire|text n\n"); printf(" select instance or text or wire number n\n"); printf(" xschem select_all\n"); printf(" select all objects\n"); printf(" xschem descend\n"); printf(" descend into schematic of selected element\n"); printf(" xschem descend_symbol\n"); printf(" descend into symbol of selected element\n"); printf(" xschem go_back\n"); printf(" back from selected element\n"); printf(" xschem unselect\n"); printf(" unselect selected objects\n"); printf(" xschem set_fill n\n"); printf(" set fill style of current layer (rectcolor) to fill pattern n (pixdata)\n"); printf(" xschem zoom_out\n"); printf(" zoom out\n"); printf(" xschem zoom_in\n"); printf(" zoom in\n"); printf(" xschem zoom_full\n"); printf(" zoom full\n"); printf(" xschem zoom_box\n"); printf(" zoom box\n"); printf(" xschem paste\n"); printf(" paste selection from clipboard\n"); printf(" xschem merge\n"); printf(" merge external file into current schematic\n"); printf(" xschem cut\n"); printf(" cut selection to clipboard\n"); printf(" xschem copy\n"); printf(" copy selection to clipboard\n"); printf(" xschem copy_objects\n"); printf(" duplicate selected objects\n"); printf(" xschem move_objects [deltax deltay]\n"); printf(" move selected objects\n"); printf(" xschem line_width n\n"); printf(" set line width to (float) n\n"); printf(" xschem delete\n"); printf(" delete selected objects\n"); printf(" xschem unhilight\n"); printf(" unlight selected nets/pins\n"); printf(" xschem hilight\n"); printf(" hilight selected nets/pins\n"); printf(" xschem clear_hilights\n"); printf(" unhilight all nets/pins\n"); printf(" xschem print [color]\n"); printf(" print schematic (optionally in color)\n"); printf(" xschem search regex|exact