/* * Copyright (c) 1991,1993 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) $Header: /cvsroot/nsnam/nam-1/main.cc,v 1.57 2003/10/11 22:56:50 xuanc Exp $ (LBL) */ #include #ifndef WIN32 #include #else #include #endif #include "netview.h" #include "tclcl.h" #include "trace.h" #include "paint.h" #include "state.h" #include "parser.h" //#include "../tcl-debug-2.0/tcldbg.h" extern "C" { #include } static void usage() { fprintf(stderr, "\ Usage: nam [-a -S -s -f init_script -d display -j jump -r rate -k initPort] \ tracefiles\n\ \n\ -a: create a new nam instance\n\ -S: synchronize X\n\ -s: synchronize multiple traces\n\ -j: startup time\n\ -r: initial animation rate\n\ -f: initialization OTcl script\n\ -k: initial socket port number\n"); exit(1); } #ifdef WIN32 extern "C" int getopt(int, char**, char*); #endif extern "C" char *optarg; extern "C" int optind; const char* disparg(int argc, const char*const* argv, const char* optstr) { const char* display = 0; int op; while ((op = getopt(argc, (char**)argv, (char*)optstr)) != -1) { if (op == 'd') { display = optarg; break; } } optind = 1; return (display); } const char* namearg(int argc, const char*const* argv, const char* optstr) { const char* appname = 0; int op; while ((op = getopt(argc, (char**)argv, (char*)optstr)) != -1) { if (op == 'N') { appname = optarg; break; } } optind = 1; return (appname); } #include "bitmap/play.xbm" #include "bitmap/back.xbm" #include "bitmap/stop.xbm" #include "bitmap/eject.xbm" #include "bitmap/rew.xbm" #include "bitmap/ff.xbm" #include "bitmap/monitors.xbm" #include "bitmap/time.xbm" #include "bitmap/zoomin.xbm" #include "bitmap/zoomout.xbm" #include "bitmap/pullright.xbm" #include "bitmap/mark1.xbm" #include "bitmap/mark2.xbm" #include "bitmap/mark3.xbm" #include "bitmap/mark4.xbm" #include "bitmap/mark5.xbm" #include "bitmap/mark6.xbm" #include "bitmap/mark7.xbm" #include "bitmap/mark8.xbm" #include "bitmap/updir.xbm" //#include "bitmap/edit.xbm" #include "bitmap/nodeup.xbm" #include "bitmap/nodedown.xbm" #include "bitmap/select.xbm" #include "bitmap/addnode.xbm" #include "bitmap/addlink.xbm" #include "bitmap/cut.xbm" #include "bitmap/delete.xbm" #include "bitmap/netedit.xbm" #include "bitmap/netview.xbm" void loadbitmaps(Tcl_Interp* tcl) { // Tk_DefineBitmap(tcl, Tk_GetUid("edit"), // edit_bits, edit_width, edit_height); Tk_DefineBitmap(tcl, Tk_GetUid("netedit"), netedit_bits, netedit_width, netedit_height); Tk_DefineBitmap(tcl, Tk_GetUid("netview"), netview_bits, netview_width, netview_height); Tk_DefineBitmap(tcl, Tk_GetUid("nodeup"), nodeup_bits, nodeup_width, nodeup_height); Tk_DefineBitmap(tcl, Tk_GetUid("nodedown"), nodedown_bits, nodedown_width, nodedown_height); Tk_DefineBitmap(tcl, Tk_GetUid("play"), play_bits, play_width, play_height); Tk_DefineBitmap(tcl, Tk_GetUid("back"), back_bits, back_width, back_height); Tk_DefineBitmap(tcl, Tk_GetUid("stop"), stop_bits, stop_width, stop_height); Tk_DefineBitmap(tcl, Tk_GetUid("eject"), eject_bits, eject_width, eject_height); Tk_DefineBitmap(tcl, Tk_GetUid("rew"), rew_bits, rew_width, rew_height); Tk_DefineBitmap(tcl, Tk_GetUid("ff"), ff_bits, ff_width, ff_height); Tk_DefineBitmap(tcl, Tk_GetUid("monitors"), monitors_bits, monitors_width, monitors_height); Tk_DefineBitmap(tcl, Tk_GetUid("time"), time_bits, time_width, time_height); Tk_DefineBitmap(tcl, Tk_GetUid("zoomin"), zoomin_bits, zoomin_width, zoomin_height); Tk_DefineBitmap(tcl, Tk_GetUid("zoomout"), zoomout_bits, zoomout_width, zoomout_height); Tk_DefineBitmap(tcl, Tk_GetUid("pullright"), pullright_bits, pullright_width, pullright_height); // Used in nam editor toolbar Tk_DefineBitmap(tcl, Tk_GetUid("select"), select_bits, select_width, select_height); Tk_DefineBitmap(tcl, Tk_GetUid("addnode"), addnode_bits, addnode_width, addnode_height); Tk_DefineBitmap(tcl, Tk_GetUid("addlink"), addlink_bits, addlink_width, addlink_height); Tk_DefineBitmap(tcl, Tk_GetUid("cut"), cut_bits, cut_width, cut_height); Tk_DefineBitmap(tcl, Tk_GetUid("delete"), delete_bits, delete_width, delete_height); Tk_DefineBitmap(tcl, Tk_GetUid("mark1"), mark1_bits, mark1_width, mark1_height); Tk_DefineBitmap(tcl, Tk_GetUid("mark2"), mark2_bits, mark2_width, mark2_height); Tk_DefineBitmap(tcl, Tk_GetUid("mark3"), mark3_bits, mark3_width, mark3_height); Tk_DefineBitmap(tcl, Tk_GetUid("mark4"), mark4_bits, mark4_width, mark4_height); Tk_DefineBitmap(tcl, Tk_GetUid("mark5"), mark5_bits, mark5_width, mark5_height); Tk_DefineBitmap(tcl, Tk_GetUid("mark6"), mark6_bits, mark6_width, mark6_height); Tk_DefineBitmap(tcl, Tk_GetUid("mark7"), mark7_bits, mark7_width, mark7_height); Tk_DefineBitmap(tcl, Tk_GetUid("mark8"), mark8_bits, mark8_width, mark8_height); Tk_DefineBitmap(tcl, Tk_GetUid("updir"), updir_bits, updir_width, updir_height); } void adios() { exit(0); } static int cmd_adios(ClientData , Tcl_Interp* , int , CONST84 char **) { adios(); /*NOTREACHED*/ return (0); } extern "C" char version[]; static int cmd_version(ClientData , Tcl_Interp* tcl, int , CONST84 char **) { tcl->result = version; return (TCL_OK); } char* parse_assignment(char* cp) { cp = strchr(cp, '='); if (cp != 0) { *cp = 0; return (cp + 1); } else return ("true"); } static void process_geometry(Tk_Window tk, char* geomArg) { /* * Valid formats: * x[+-][+-] or * x or * [+-]x[+-]y */ Tcl &tcl = Tcl::instance(); // xxx: geomArg could have bogus stuff in it (security hole) // but nam doesn't run trusted, so no problem. tcl.evalf("wm geometry %s %s", Tk_PathName(tk), geomArg); // tclcl will report the error, if any. } // What is it used for??? // extern "C" void Blt_Init(Tcl_Interp*); #ifdef WIN32 EXTERN int platformInit(Tcl_Interp* interp); #endif /* TkPlatformInit was moved to tkUnixInit.c */ #if defined(WIN32) && defined(STATIC_LIB) #include #include extern "C" { extern BOOL APIENTRY Tk_LibMain(HINSTANCE hInstance, DWORD reason, LPVOID reserved); extern BOOL APIENTRY Tcl_LibMain(HINSTANCE hInstance, DWORD reason, LPVOID reserved); /* procedure to call before exiting to clean up */ void static_exit(void) { HINSTANCE hInstance = Tk_GetHINSTANCE(); Tcl_LibMain(hInstance, DLL_PROCESS_DETACH, NULL); Tk_LibMain(hInstance, DLL_PROCESS_DETACH, NULL); } } #endif /* defined(WIN32) && defined(STATIC_LIB) */ #ifdef HAVE_LIBTCLDBG extern "C" { extern int Tcldbg_Init(Tcl_Interp *); // hackorama } #endif void die(char *s) { fprintf(stderr, "%s", s); exit (1); } /*ARGSUSED*/ int main(int argc, char **argv) { const char* script = 0; // configurations to be loaded const char* optstr = "d:M:j:pG:r:u:X:t:i:P:g:N:c:S:f:asmk:zk:xp"; TraceEvent te; // Used to display parsetable ParseTable pt(&te); // Used to display parsetable /* * We have to initialize libtcl and libtk if we are under Win32 * and we are using static version of libtcl8.0p2 and libtk8.0p2. * Because in those distributions, Sun only supports DLL, but * not static lib. They require initializations in DllMain(). * The Berkeley folks (tecklee) built static versions by * forcing calls to DllMain() inside WinMain(). Because nam * is built as a console app in win32, we have to do those * initializations here, in main(). */ #if defined(WIN32) && defined(STATIC_LIB) HINSTANCE hInstance = GetModuleHandle(NULL); Tcl_LibMain(hInstance, DLL_PROCESS_ATTACH, NULL); Tk_LibMain(hInstance, DLL_PROCESS_ATTACH, NULL); atexit(static_exit); #endif /* * Process display option here before the rest of the options * because it's needed when creating the main application window. */ const char* display = disparg(argc, argv, optstr); // hold pointer to application name for send const char* appname = namearg(argc, argv, optstr); if (!appname) appname = "nam"; #ifdef notdef fprintf(stderr, "Application name is %s\n", appname); #endif Tcl_Interp *interp = Tcl_CreateInterp(); #if 0 if (Tcl_Init(interp) == TCL_ERROR) { printf("%s\n", interp->result); abort(); } #endif #if TCL_MAJOR_VERSION < 8 Tcl_SetVar(interp, "tcl_library", "./lib/tcl7.6", TCL_GLOBAL_ONLY); Tcl_SetVar(interp, "tk_library", "./lib/tk4.2", TCL_GLOBAL_ONLY); #else Tcl_SetVar(interp, "tcl_library", "", TCL_GLOBAL_ONLY); Tcl_SetVar(interp, "tk_library", "", TCL_GLOBAL_ONLY); // this seems just a hack, should NOT have hard-coded library path! // why there's no problem with old TCL/TK? // xuanc, 10/3/2003 //Tcl_SetVar(interp, "tcl_library", "./lib/tcl8.0", TCL_GLOBAL_ONLY); //Tcl_SetVar(interp, "tk_library", "./lib/tk8.0", TCL_GLOBAL_ONLY); #endif if (Otcl_Init(interp) == TCL_ERROR) { printf("%s\n", interp->result); abort(); } #ifdef HAVE_LIBTCLDBG if (Tcldbg_Init(interp) == TCL_ERROR) { return TCL_ERROR; } #endif Tcl::init(interp, appname); Tcl& tcl = Tcl::instance(); tcl.evalf(display? "set argv \"-name %s -display %s\"" : "set argv \"-name %s\"", appname, display, appname); Tk_Window tk = 0; #ifdef WIN32 Tcl_SetVar(interp, "tcl_library", ".", TCL_GLOBAL_ONLY); Tcl_SetVar(interp, "tk_library", ".", TCL_GLOBAL_ONLY); #endif if (Tk_Init(tcl.interp()) == TCL_OK) tk = Tk_MainWindow(tcl.interp()); if (tk == 0) { fprintf(stderr, "nam: %s\n", interp->result); exit(1); } tcl.tkmain(tk); extern EmbeddedTcl et_tk, et_nam; et_tk.load(); et_nam.load(); int op; int cacheSize = 100; char* graphInput = new char[256]; char* graphInterval = new char[256]; char* buf = new char[256]; char* args = new char[256]; graphInput[0] = graphInterval[0] = buf[0] = args[0] = 0; while ((op = getopt(argc, (char**)argv, (char*)optstr)) != -1) { switch (op) { default: usage(); case 'd': case 'N': /* already handled before */ break; /*XXX move to Tcl */ #ifdef notyet case 'M': tcl.add_option("movie", optarg); break; case 'p': tcl.add_option("pause", "1"); break; case 'G': tcl.add_option("granularity", optarg); break; case 'X': { const char* value = parse_assignment(optarg); tcl.add_option(optarg, value); } break; case 'P': /* Peer name, obsoleted */ sprintf(buf, "p %s ", optarg); strcat(args, buf); break; case 't': /* Use tkgraph. Must supply tkgraph input filename. */ sprintf(graphInput, "g %s ", optarg); strcat(args, graphInput); break; #endif case 'a': /* * Create a whole new instance. */ strcat(args, "a 1 "); break; case 'c': cacheSize = atoi(optarg); break; case 'f': case 'u': script = optarg; /* Also pass it to OTcl */ sprintf(buf, "f %s ", optarg); strcat(args, buf); break; case 'g': process_geometry(tk, optarg); break; case 'i': /* * Interval value for graph updates: default is * set by nam_init. */ sprintf(graphInterval, "i %s ", optarg); strcat(args, graphInterval); break; case 'j': /* Initial startup time */ sprintf(buf, "j %s ", optarg); strcat(args, buf); break; case 'k': /* Initial socket port number */ sprintf(buf, "k %s ", optarg); strcat(args, buf); break; case 'm': /* Multiple traces */ /* no longer needed, but option is still allowed */ /* for compatibility reasons */ break; case 'r': /* Initial animation rate */ sprintf(buf, "r %s ", optarg); strcat(args, buf); break; case 's': /* synchronize all windows together */ strcat(args, "s 1 "); break; case 'z': /* set nam validation test on */ strcat(args, "z 1 "); break; #ifndef WIN32 case 'S': XSynchronize(Tk_Display(tk), True); break; #endif case 'x': pt.printLatex(stdout); exit(0); break; case 'p': pt.print(stdout); exit(0); break; } } if (strlen(graphInterval) && !strlen(graphInput)) { fprintf(stderr, "nam: missing graph input file\n"); exit(1); } loadbitmaps(interp); char* tracename = NULL; /* trace file */ /* * Linux libc-5.3.12 has a bug where if no arguments are processed * optind stays at zero. Work around that problem here. * The work-around seems harmless in other OSes so it's not ifdef'ed. */ if ((optind == -1) || (optind == 0)) optind = 1; /* * Make sure the base name of the trace file * was specified. */ // if (argc - optind < 1) // usage(); tracename = argv[optind]; //XXX need to port this #ifndef WIN32 if ((tracename != NULL) ) { if (access(tracename, R_OK) < 0) { tracename = new char[strlen(argv[optind]) + 4]; sprintf(tracename, "%s.nam", argv[optind]); } } #endif tcl.CreateCommand("adios", cmd_adios); tcl.CreateCommand("version", cmd_version); #ifdef WIN32 platformInit(interp); #endif // XXX inappropriate to do initialization in this way? FILE *fp = fopen(".nam.tcl", "r"); if (fp != NULL) { fclose(fp); tcl.EvalFile(".nam.tcl"); } // User-supplied configuration files // option '-u' and '-f' are merged together // Evaluation is moved into OTcl // if (script != NULL) { // fp = fopen(script, "r"); // if (fp != NULL) { // fclose(fp); // tcl.EvalFile(script); // } else { // fprintf(stderr, "No configuration file %s\n", // script); // } // } Paint::init(); State::init(cacheSize); // -- Start TclDebugger //Tcldbg_Init(interp); tcl.eval("set nam_local_display 0"); if (tracename != NULL) { while (tracename) { // Any backslash characters in the filename must be // escaped before being passed to Tcl. char * new_tracename = (char*)malloc(2 * strlen(tracename) + 1); char * temp_tracename = new_tracename; while (*tracename) { if (*tracename == '\\') *(temp_tracename++) = '\\'; *(temp_tracename++) = *tracename; ++tracename; } *temp_tracename = 0; tracename= new_tracename; // Jump to nam-lib.tcl tcl.evalf("nam_init %s %s", tracename, args); tracename = argv[++optind]; } } else { // Jump to nam-lib.tcl tcl.evalf("nam_init \"\" %s", args); } tcl.eval("set nam_local_display"); if (strcmp(tcl.result(),"1") == 0) { Tk_MainLoop(); } return (0); }