From b7a3951c0046491a62399fc51fe809e24e5eb8b7 Mon Sep 17 00:00:00 2001 From: Steve Bennett Date: Wed, 3 Nov 2010 20:52:27 +1000 Subject: Don't hardcode /lib/jim Instead, set TCL_LIBRARY based on where jim is installed. This defaults to /usr/local (thus /usr/local/lib/jim), or can be modified with either configure or make. e.g. ./configure --prefix=/usr or make prefix=/usr install Now auto_path is initialised only to TCL_LIBRARY, and doesn't include "." which could be undesirable. At the same time, simplify jimsh initialisation using a script instead of C code. Add the path to the executable to auto_path. Also, no longer use JIM_TCL_COMPAT. Always use the tcl-compatible names, $auto_path and $tcl_interactive. Signed-off-by: Steve Bennett --- Makefile.in | 8 ++-- README.extensions | 3 ++ configure | 3 ++ configure.ac | 1 + jim.c | 2 +- jim.h | 5 -- jim_tcl.txt | 8 ++-- jimsh.c | 134 +++++++++++------------------------------------------- stdlib.tcl | 17 +++++++ tclcompat.tcl | 15 ------ tests/Makefile | 3 +- 11 files changed, 63 insertions(+), 136 deletions(-) diff --git a/Makefile.in b/Makefile.in index 43af85e..697a1ad 100644 --- a/Makefile.in +++ b/Makefile.in @@ -14,13 +14,15 @@ SHOBJ_LDFLAGS ?= @SHOBJ_LDFLAGS@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ LDLIBS += @LIBS@ -DESTDIR ?= @prefix@ +exec_prefix ?= @exec_prefix@ +prefix ?= @prefix@ +DESTDIR ?= $(prefix) # Set an initial, default library and auto_path -CPPFLAGS += -DTCL_LIBRARY=\"/lib/jim\" +CPPFLAGS += -DTCL_LIBRARY=\"@TCL_LIBRARY@\" CPPFLAGS += -DTCL_PLATFORM_OS=\"@PLATFORM_OS@\" -DTCL_PLATFORM_PLATFORM=\"@PLATFORM_PLATFORM@\" -CPPFLAGS += -DJIM_TCL_COMPAT -DJIM_REFERENCES -D_GNU_SOURCE +CPPFLAGS += -DJIM_REFERENCES -D_GNU_SOURCE CPPFLAGS += -Wall $(OPTIM) -I@SRCDIR@ -I. @EXTRA_CFLAGS@ VPATH := @SRCDIR@ diff --git a/README.extensions b/README.extensions index cf3dd37..0eaca1c 100644 --- a/README.extensions +++ b/README.extensions @@ -10,3 +10,6 @@ abc can be loaded with: package require abc First abc.so will be tried, and then abc.tcl + +Note that this directory may be something like /lib/jim, /usr/lib/jim or +/usr/local/lib/jim, depending upon where jim was installed. diff --git a/configure b/configure index 4e8d758..4335968 100755 --- a/configure +++ b/configure @@ -606,6 +606,7 @@ LIBOBJS PLATFORM_PLATFORM PLATFORM_OS SRCDIR +TCL_LIBRARY EXTRA_OBJS EXTRA_CFLAGS JIM_TCL_EXTENSIONS @@ -4246,6 +4247,8 @@ EXTRA_CFLAGS=$EXTRA_CFLAGS EXTRA_OBJS=$EXTRA_OBJS +TCL_LIBRARY=$libdir/jim + SRCDIR=`dirname $0` PLATFORM_OS=`uname -s` diff --git a/configure.ac b/configure.ac index 41bfd79..c799a11 100755 --- a/configure.ac +++ b/configure.ac @@ -348,6 +348,7 @@ fi AC_SUBST(EXTRA_CFLAGS,$EXTRA_CFLAGS) AC_SUBST(EXTRA_OBJS,$EXTRA_OBJS) +AC_SUBST(TCL_LIBRARY,$libdir/jim) AC_SUBST(SRCDIR,`dirname $0`) AC_SUBST(PLATFORM_OS,`uname -s`) AC_SUBST(PLATFORM_PLATFORM,unix) diff --git a/jim.c b/jim.c index 985e148..8ca27cb 100644 --- a/jim.c +++ b/jim.c @@ -4665,7 +4665,7 @@ Jim_Interp *Jim_CreateInterp(void) Jim_IncrRefCount(i->falseObj); /* Initialize key variables every interpreter should contain */ - Jim_SetVariableStrWithStr(i, JIM_LIBPATH, ". /lib/jim"); + Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY); Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0"); Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS); diff --git a/jim.h b/jim.h index 6ef4f15..5f36eaa 100644 --- a/jim.h +++ b/jim.h @@ -171,13 +171,8 @@ extern "C" { #define JIM_NL "\n" #endif -#ifdef JIM_TCL_COMPAT #define JIM_LIBPATH "auto_path" #define JIM_INTERACTIVE "tcl_interactive" -#else -#define JIM_LIBPATH "jim_libpath" -#define JIM_INTERACTIVE "jim_interactive" -#endif #ifndef TCL_PLATFORM_OS #define TCL_PLATFORM_OS "unknown" diff --git a/jim_tcl.txt b/jim_tcl.txt index cea5bf8..7cff785 100644 --- a/jim_tcl.txt +++ b/jim_tcl.txt @@ -2930,8 +2930,6 @@ otherwise if '$name.tcl' exists it is loaded with the 'source' command. If 'load' or 'source' fails, 'package require' will fail immediately. No further attempt will be made to locate the file. -Typically '$::auto_path' contains the paths '.' and '/lib/jim'. - pid ~~~ +*pid*+ @@ -4305,7 +4303,11 @@ by the Tcl library. +*auto_path*+:: This variable contains a list of paths to search for packages. - It contains {. /lib/jim} by default. + It defaults to a location based on where jim is installed + (e.g. +/usr/local/lib/jim+), but may be changed by +jimsh+ + or the embedding application. Note that +jimsh+ will consider + the environment variable +$JIMLIB+ to be a list of colon-separated + list of paths to add to *auto_path*. +*errorCode*+:: This variable holds the value of the -errorcode return diff --git a/jimsh.c b/jimsh.c index 63569a7..9b69def 100644 --- a/jimsh.c +++ b/jimsh.c @@ -25,101 +25,25 @@ #include "jim.h" -/* JimGetExePath try to get the absolute path of the directory - * of the jim binary, in order to add this path to the library path. - * Likely shipped libraries are in the same path too. */ -#ifndef JIM_ANSIC - -/* A bit complex on POSIX */ -#include -static Jim_Obj *JimGetExePath(Jim_Interp *interp, const char *argv0) -{ - char *p; - - /* Check if the executable was called with an absolute pathname */ - if (argv0[0] == '/') { - p = strrchr(argv0, '/'); - return Jim_NewStringObj(interp, argv0, (p == argv0) ? 1 : p - argv0); - } - else { - int l; - char *path = Jim_Alloc(JIM_PATH_LEN + 1); - - if (getcwd(path, JIM_PATH_LEN) == NULL) { -default_path: - Jim_Free(path); - return Jim_NewStringObj(interp, "/usr/local/lib/jim/", -1); - } - - /* Need to add the directory component of argv0 to pwd (path) */ - - /* Strip any leading "./" off argv0 for cleanliness */ - while (argv0[0] == '.' && argv0[1] == '/') { - argv0 += 2; - } - - l = strlen(path); - - /* Strip the last component from argv0 */ - p = strrchr(argv0, '/'); - if (p) { - int argv0len = p - argv0; - - /* Need a trailing / on pwd */ - if (l > 0 && path[l - 1] != '/') - path[l++] = '/'; - - /* And append it to 'path' */ - if (l + argv0len > JIM_PATH_LEN) { - /* It won't fit. Don't both trying to realloc. */ - goto default_path; - } - memcpy(path + l, argv0, argv0len); - l += argv0len; - path[l] = '\0'; - } - - return Jim_NewStringObjNoAlloc(interp, path, l); - } -} -#else /* JIM_ANSIC */ - -/* ... and impossible with just ANSI C */ -static Jim_Obj *JimGetExePath(Jim_Interp *interp, const char *argv0) -{ - JIM_NOTUSED(argv0); - return Jim_NewStringObj(interp, "/usr/local/lib/jim/", -1); -} -#endif /* JIM_ANSIC */ - -static int JimLoadJimRc(Jim_Interp *interp) -{ - const char *home; - /* XXX: Move off stack */ - char buf[JIM_PATH_LEN + 1]; - const char *names[] = { ".jimrc", "jimrc.tcl", NULL }; - int i; - FILE *fp; - int retcode; - - if ((home = getenv("HOME")) == NULL) - return JIM_OK; - for (i = 0; names[i] != NULL; i++) { - if (strlen(home) + strlen(names[i]) + 1 > JIM_PATH_LEN) - continue; - sprintf(buf, "%s/%s", home, names[i]); - if ((fp = fopen(buf, "r")) != NULL) { - fclose(fp); - retcode = Jim_EvalFile(interp, buf); - if (retcode == JIM_ERR) { - Jim_MakeErrorMessage(interp); - fprintf(stderr, "%s\n", Jim_GetString(Jim_GetResult(interp), NULL)); - } - return retcode; - } - } - return JIM_OK; -} +/* Script to help initialise jimsh */ +static const char jimsh_init[] = \ +"proc _init {} {\n" +"\trename _init {}\n" +"\tlappend p {*}[split [env JIMLIB {}] :]\n" +"\tlappend p {*}$::auto_path\n" +"\tlappend p [file dirname [info nameofexecutable]]\n" +"\tset ::auto_path $p\n" +"\n" +"\tif {$::tcl_interactive && [env HOME {}] ne \"\"} {\n" +"\t\tforeach src {.jimrc jimrc.tcl} {\n" +"\t\t\tif {[file exists [env HOME]/$src]} {\n" +"\t\t\t\tuplevel #0 source [env HOME]/$src\n" +"\t\t\t\tbreak\n" +"\t\t\t}\n" +"\t\t}\n" +"\t}\n" +"}\n" +"_init\n"; static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[]) { @@ -141,7 +65,6 @@ int main(int argc, char *const argv[]) { int retcode; Jim_Interp *interp; - Jim_Obj *listObj; /* Create and initialize the interpreter */ interp = Jim_CreateInterp(); @@ -153,26 +76,21 @@ int main(int argc, char *const argv[]) fprintf(stderr, "%s\n", Jim_GetString(Jim_GetResult(interp), NULL)); } - /* Append the path where the executed Jim binary is contained - * in the jim_libpath list. */ - listObj = Jim_GetVariableStr(interp, JIM_LIBPATH, JIM_NONE); - if (Jim_IsShared(listObj)) - listObj = Jim_DuplicateObj(interp, listObj); - Jim_ListAppendElement(interp, listObj, JimGetExePath(interp, argv[0])); - Jim_SetVariableStr(interp, JIM_LIBPATH, listObj); - Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]); + Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); + retcode = Jim_Eval(interp, jimsh_init); if (argc == 1) { - Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); - JimSetArgv(interp, 0, NULL); - retcode = JimLoadJimRc(interp); + if (retcode == JIM_ERR) { + Jim_MakeErrorMessage(interp); + fprintf(stderr, "%s\n", Jim_GetString(Jim_GetResult(interp), NULL)); + } if (retcode != JIM_EXIT) { + JimSetArgv(interp, 0, NULL); retcode = Jim_InteractivePrompt(interp); } } else { - Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "0"); if (argc > 2 && strcmp(argv[1], "-e") == 0) { JimSetArgv(interp, argc - 3, argv + 3); retcode = Jim_Eval(interp, argv[2]); diff --git a/stdlib.tcl b/stdlib.tcl index 9727eb2..fe406ed 100644 --- a/stdlib.tcl +++ b/stdlib.tcl @@ -96,3 +96,20 @@ proc errorInfo {msg {stacktrace ""}} { # Remove the trailing newline string trim $result } + +# Finds the current executable by searching along the path +# Returns the empty string if not found. +proc {info nameofexecutable} {} { + if {[info exists ::jim_argv0]} { + if {[string first "/" $::jim_argv0] >= 0} { + return $::jim_argv0 + } + foreach path [split [env PATH ""] :] { + set exec [file join $path $::jim_argv0] + if {[file executable $exec]} { + return $exec + } + } + } + return "" +} diff --git a/tclcompat.tcl b/tclcompat.tcl index aa4907e..4589f56 100644 --- a/tclcompat.tcl +++ b/tclcompat.tcl @@ -101,21 +101,6 @@ proc parray {arrayname {pattern *} {puts puts}} { } } -proc {info nameofexecutable} {} { - if {[info exists ::jim_argv0]} { - if {[string first "/" $::jim_argv0] >= 0} { - return $::jim_argv0 - } - foreach path [split [env PATH ""] :] { - set exec [file join $path $::jim_argv0] - if {[file executable $exec]} { - return $exec - } - } - } - return "" -} - # Implements 'file copy' - single file mode only proc {file copy} {{force {}} source target} { try { diff --git a/tests/Makefile b/tests/Makefile index d717462..285fb9e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,5 +1,6 @@ jimsh ?= ../jimsh -LD_LIBRARY_PATH := ..:$(LD_LIBRARY_PATH) +export LD_LIBRARY_PATH := ..:$(LD_LIBRARY_PATH) +export JIMLIB := ..:. test: @set -e; for i in *.test; do $(jimsh) $$i; done -- cgit v1.1