diff --git a/CMakeLists.txt b/CMakeLists.txt
index 39fd0ecd..f48f7480 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -65,7 +65,6 @@ set(STA_WRAP ${CMAKE_CURRENT_BINARY_DIR}/StaApp_wrap.cc)
set(STA_SOURCE
app/StaMain.cc
app/TclInitVar.cc
- ${STA_WRAP}
dcalc/ArcDelayCalc.cc
dcalc/ArnoldiDelayCalc.cc
@@ -699,7 +698,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${STA_HOME}/app)
# Note executable and lib name cannot be the same because
# on osx something is case insensitive. Using STA for the
# lib name results in "No rule to make target ../depend.
-add_executable(sta app/Main.cc)
+add_executable(sta app/Main.cc ${STA_WRAP})
+
target_link_libraries(sta
OpenSTA
${TCL_LIB}
diff --git a/app/Main.cc b/app/Main.cc
index c884275b..f7f927b9 100644
--- a/app/Main.cc
+++ b/app/Main.cc
@@ -15,32 +15,58 @@
// along with this program. If not, see .
#include
+#include
#include "Machine.hh"
#include "StaConfig.hh" // STA_VERSION
#include "StringUtil.hh"
#include "Sta.hh"
#include "StaMain.hh"
+
+namespace sta {
+extern const char *tcl_inits[];
+}
+
using sta::stringEq;
+using sta::findCmdLineFlag;
using sta::Sta;
-using sta::staMain;
-using sta::showUsage;
+using sta::initSta;
+using sta::evalTclInit;
+using sta::stringPrintTmp;
+using sta::sourceTclFile;
+using sta::parseThreadsArg;
+using sta::tcl_inits;
// Swig uses C linkage for init functions.
extern "C" {
extern int Sta_Init(Tcl_Interp *interp);
}
-namespace sta {
-extern const char *tcl_inits[];
-}
+static int cmd_argc;
+static char **cmd_argv;
+static const char *init_filename = ".sta";
+
+static void
+showUsage(const char *prog,
+ const char *init_filename);
+static int
+tclAppInit(Tcl_Interp *interp);
+static int
+staTclAppInit(int argc,
+ char *argv[],
+ const char *init_filename,
+ Tcl_Interp *interp);
+static void
+initStaApp(int argc,
+ char *argv[],
+ Tcl_Interp *interp);
int
main(int argc,
char *argv[])
{
if (argc == 2 && stringEq(argv[1], "-help")) {
- showUsage(argv[0]);
+ showUsage(argv[0], init_filename);
return 0;
}
else if (argc == 2 && stringEq(argv[1], "-version")) {
@@ -48,8 +74,102 @@ main(int argc,
return 0;
}
else {
- Sta *sta = new Sta;
- staMain(sta, argc, argv, ".sta", Sta_Init, sta::tcl_inits);
+ // Set argc to 1 so Tcl_Main doesn't source any files.
+ // Tcl_Main never returns.
+#if 0
+ // It should be possible to pass argc/argv to staTclAppInit with
+ // a closure but I couldn't get the signature to match Tcl_AppInitProc.
+ Tcl_Main(1, argv, [=](Tcl_Interp *interp)
+ { sta::staTclAppInit(argc, argv, interp);
+ return 1;
+ });
+#else
+ // Workaround.
+ cmd_argc = argc;
+ cmd_argv = argv;
+ Tcl_Main(1, argv, tclAppInit);
+#endif
return 0;
}
}
+
+static int
+tclAppInit(Tcl_Interp *interp)
+{
+ return staTclAppInit(cmd_argc, cmd_argv, init_filename, interp);
+}
+
+// Tcl init executed inside Tcl_Main.
+static int
+staTclAppInit(int argc,
+ char *argv[],
+ const char *init_filename,
+ Tcl_Interp *interp)
+{
+ // source init.tcl
+ Tcl_Init(interp);
+
+ initStaApp(argc, argv, interp);
+
+ if (!findCmdLineFlag(argc, argv, "-no_splash"))
+ Tcl_Eval(interp, "sta::show_splash");
+
+ if (!findCmdLineFlag(argc, argv, "-no_init")) {
+ char *init_path = stringPrintTmp("[file join $env(HOME) %s]",
+ init_filename);
+ sourceTclFile(init_path, true, true, interp);
+ }
+
+ bool exit_after_cmd_file = findCmdLineFlag(argc, argv, "-exit");
+
+ if (argc > 2 ||
+ (argc > 1 && argv[1][0] == '-'))
+ showUsage(argv[0], init_filename);
+ else {
+ if (argc == 2) {
+ char *cmd_file = argv[1];
+ if (cmd_file) {
+ sourceTclFile(cmd_file, false, false, interp);
+ if (exit_after_cmd_file)
+ exit(EXIT_SUCCESS);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+static void
+initStaApp(int argc,
+ char *argv[],
+ Tcl_Interp *interp)
+{
+ initSta();
+ Sta *sta = new Sta;
+ Sta::setSta(sta);
+ sta->makeComponents();
+ sta->setTclInterp(interp);
+ int thread_count = parseThreadsArg(argc, argv);
+ sta->setThreadCount(thread_count);
+
+ // Define swig TCL commands.
+ Sta_Init(interp);
+ // Eval encoded sta TCL sources.
+ evalTclInit(interp, tcl_inits);
+ // Import exported commands from sta namespace to global namespace.
+ Tcl_Eval(interp, "sta::define_sta_cmds");
+ Tcl_Eval(interp, "namespace import sta::*");
+}
+
+static void
+showUsage(const char *prog,
+ const char *init_filename)
+{
+ printf("Usage: %s [-help] [-version] [-no_init] [-exit] cmd_file\n", prog);
+ printf(" -help show help and exit\n");
+ printf(" -version show version and exit\n");
+ printf(" -no_init do not read %s init file\n", init_filename);
+ printf(" -threads count|max use count threads\n");
+ printf(" -no_splash do not show the license splash at startup\n");
+ printf(" -exit exit after reading cmd_file\n");
+ printf(" cmd_file source cmd_file\n");
+}
diff --git a/app/StaMain.cc b/app/StaMain.cc
index 2d96ae24..5b49f134 100644
--- a/app/StaMain.cc
+++ b/app/StaMain.cc
@@ -24,37 +24,6 @@
namespace sta {
-typedef sta::Vector SwigInitFuncSeq;
-
-// "Arguments" passed to staTclAppInit.
-static int sta_argc;
-static char **sta_argv;
-static const char *sta_init_filename;
-static const char **sta_tcl_inits;
-static SwigInitFunc sta_swig_init;
-
-void
-staMain(Sta *sta,
- int argc,
- char *argv[],
- const char *init_filename,
- SwigInitFunc swig_init,
- const char *tcl_inits[])
-{
- initSta();
-
- Sta::setSta(sta);
- sta->makeComponents();
-
- int thread_count = parseThreadsArg(argc, argv);
- sta->setThreadCount(thread_count);
-
- staSetupAppInit(argc, argv, init_filename, swig_init, tcl_inits);
- // Set argc to 1 so Tcl_Main doesn't source any files.
- // Tcl_Main never returns.
- Tcl_Main(1, argv, staTclAppInit);
-}
-
int
parseThreadsArg(int &argc,
char *argv[])
@@ -71,71 +40,6 @@ parseThreadsArg(int &argc,
return 1;
}
-// Set globals to pass to staTclAppInit.
-void
-staSetupAppInit(int argc,
- char *argv[],
- const char *init_filename,
- SwigInitFunc swig_init,
- const char *tcl_inits[])
-{
- sta_argc = argc;
- sta_argv = argv;
- sta_init_filename = init_filename;
- sta_tcl_inits = tcl_inits;
- sta_swig_init = swig_init;
-}
-
-// Tcl init executed inside Tcl_Main.
-int
-staTclAppInit(Tcl_Interp *interp)
-{
- int argc = sta_argc;
- char **argv = sta_argv;
-
- // source init.tcl
- Tcl_Init(interp);
-
- // Define swig commands.
- sta_swig_init(interp);
-
- Sta *sta = Sta::sta();
- sta->setTclInterp(interp);
-
- // Eval encoded sta TCL sources.
- evalTclInit(interp, sta_tcl_inits);
-
- if (!findCmdLineFlag(argc, argv, "-no_splash"))
- Tcl_Eval(interp, "sta::show_splash");
-
- // Import exported commands from sta namespace to global namespace.
- Tcl_Eval(interp, "sta::define_sta_cmds");
- Tcl_Eval(interp, "namespace import sta::*");
-
- if (!findCmdLineFlag(argc, argv, "-no_init")) {
- char *init_path = stringPrintTmp("[file join $env(HOME) %s]",
- sta_init_filename);
- sourceTclFile(init_path, true, true, interp);
- }
-
- bool exit_after_cmd_file = findCmdLineFlag(argc, argv, "-exit");
-
- if (argc > 2 ||
- (argc > 1 && argv[1][0] == '-'))
- showUsage(argv[0]);
- else {
- if (argc == 2) {
- char *cmd_file = argv[1];
- if (cmd_file) {
- sourceTclFile(cmd_file, false, false, interp);
- if (exit_after_cmd_file)
- exit(EXIT_SUCCESS);
- }
- }
- }
- return TCL_OK;
-}
-
bool
findCmdLineFlag(int &argc,
char *argv[],
@@ -220,17 +124,4 @@ evalTclInit(Tcl_Interp *interp,
delete [] unencoded;
}
-void
-showUsage(const char * prog)
-{
- printf("Usage: %s [-help] [-version] [-no_init] [-exit] cmd_file\n", prog);
- printf(" -help show help and exit\n");
- printf(" -version show version and exit\n");
- printf(" -no_init do not read .sta init file\n");
- printf(" -threads count|max use count threads\n");
- printf(" -no_splash do not show the license splash at startup\n");
- printf(" -exit exit after reading cmd_file\n");
- printf(" cmd_file source cmd_file\n");
-}
-
} // namespace
diff --git a/app/StaMain.hh b/app/StaMain.hh
index a9fa2d1c..2b188e89 100644
--- a/app/StaMain.hh
+++ b/app/StaMain.hh
@@ -22,28 +22,20 @@ struct Tcl_Interp;
namespace sta {
class Sta;
-typedef int (*SwigInitFunc)(Tcl_Interp *);
-
-// The swig_init function is called to define the swig interface
-// functions to the tcl interpreter.
-void
-staMain(Sta *sta,
- int argc,
- char *argv[],
- const char *init_filename,
- SwigInitFunc swig_init,
- const char *tcl_inits[]);
-
-// Set arguments passed to staTclAppInit inside the tcl interpreter.
-void
-staSetupAppInit(int argc,
- char *argv[],
- const char *init_filename,
- SwigInitFunc swig_init,
- const char *tcl_inits[]);
+// Parse command line argument
int
-staTclAppInit(Tcl_Interp *interp);
+staTclAppInit(int argc,
+ char *argv[],
+ const char *init_filename,
+ Tcl_Interp *interp);
+
+// Sta initialization.
+// Makes the Sta object and registers TCL commands.
+void
+initSta(int argc,
+ char *argv[],
+ Tcl_Interp *interp);
// TCL init files are encoded into the string init using the three
// digit decimal equivalent for each ascii character. This function
@@ -63,8 +55,6 @@ findCmdLineKey(int &argc,
char *argv[],
const char *key);
-void
-showUsage(const char *prog);
int
parseThreadsArg(int &argc,
char *argv[]);