diff options
author | Steve Bennett <steveb@workware.net.au> | 2010-10-20 10:55:07 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2010-10-30 20:07:28 +1000 |
commit | 8016c1d53332b9ad2af8e49482f7848648995a89 (patch) | |
tree | e45d82799d638cdfcc2020e7cc05131b60049384 | |
parent | bbd43ee01fce3a2b5284154c50dfc9994c913a29 (diff) | |
download | jimtcl-8016c1d53332b9ad2af8e49482f7848648995a89.zip jimtcl-8016c1d53332b9ad2af8e49482f7848648995a89.tar.gz jimtcl-8016c1d53332b9ad2af8e49482f7848648995a89.tar.bz2 |
Allow extensions to be built/installed as modules
This includes C extensions and Tcl extensions
Also adds windows support (mingw32 and cygwin)
Now the sqlite*, readline and win32 extensions are supported
Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r-- | Makefile.in | 46 | ||||
-rw-r--r-- | Tcl_shipped.html | 2 | ||||
-rwxr-xr-x | configure | 527 | ||||
-rwxr-xr-x | configure.ac | 328 | ||||
-rw-r--r-- | glob.tcl | 1 | ||||
-rw-r--r-- | jim-load.c | 4 | ||||
-rw-r--r-- | jim-win32.c | 487 | ||||
-rw-r--r-- | jim-win32compat.c | 56 | ||||
-rw-r--r-- | jim-win32compat.h | 28 | ||||
-rw-r--r-- | jim.c | 2 | ||||
-rw-r--r-- | jim.h | 55 | ||||
-rw-r--r-- | jimautoconf.h.in | 16 | ||||
-rw-r--r-- | tests/Makefile | 1 |
13 files changed, 1217 insertions, 336 deletions
diff --git a/Makefile.in b/Makefile.in index 0483227..450a448 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,15 +7,15 @@ AR ?= $(CROSS)ar # Configuration jim_libtype := @JIM_LIBTYPE@ -SH_CFLAGS ?= @SH_CFLAGS@ -SH_LDFLAGS ?= @SH_LDFLAGS@ +SH_CFLAGS ?= @SH_CFLAGS@ +SH_LDFLAGS ?= @SH_LDFLAGS@ +SHOBJ_CFLAGS ?= @SHOBJ_CFLAGS@ +SHOBJ_LDFLAGS ?= @SHOBJ_LDFLAGS@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ +LDLIBS += @LIBS@ DESTDIR ?= @prefix@ -# Defines the extensions to include -EXTENSIONS := @JIM_EXTENSIONS@ - # Set an initial, default library and auto_path CPPFLAGS += -DTCL_LIBRARY=\"/lib/jim\" @@ -29,14 +29,19 @@ ifeq ($(jim_libtype),static) LIBJIM := libjim.a else LIBJIM := libjim.so + SH_LIBJIM := $(LIBJIM) CPPFLAGS += $(SH_CFLAGS) endif .EXPORT_ALL_VARIABLES: -OBJS := jim-subcmd.o jim-interactive.o jim.o +OBJS := jim-subcmd.o jim-interactive.o jim.o @EXTRA_OBJS@ + +JIMSH := jimsh@EXEEXT@ -EXTENSIONS_OBJS := $(patsubst %,jim-%.o,$(EXTENSIONS)) +EXTENSION_OBJS := $(patsubst %,jim-%.o,@JIM_EXTENSIONS@) +EXTENSION_MODS := $(patsubst %,%.so,@JIM_MOD_EXTENSIONS@) +EXTENSION_TCL := $(patsubst %,%.tcl,@JIM_TCL_EXTENSIONS@) .PRECIOUS: jim-%.c @@ -47,18 +52,19 @@ jim-%.c: %.tcl OBJS += jim-load-static-exts.o -all: jimsh +all: $(JIMSH) $(EXTENSION_MODS) docs: Tcl.html -jimsh: $(LIBJIM) jimsh.o - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ jimsh.o $(LIBJIM) $(LDLIBS) @LIBSOCK@ @LIBDL@ -lm +$(JIMSH): $(LIBJIM) jimsh.o + $(CC) $(CFLAGS) @LINKFLAGS@ $(LDFLAGS) -o $@ jimsh.o $(LIBJIM) $(LDLIBS) -lm -install: all docs +install: all docs $(EXTENSION_TCL) install -d $(DESTDIR)/bin - install jimsh $(DESTDIR)/bin - install -d $(DESTDIR)/lib + install $(JIMSH) $(DESTDIR)/bin + install -d $(DESTDIR)/lib/jim install $(LIBJIM) $(DESTDIR)/lib + install $(EXTENSION_MODS) $(EXTENSION_TCL) $(DESTDIR)/lib/jim install -d $(DESTDIR)/include install @SRCDIR@/jim.h @SRCDIR@/jim-*.h $(DESTDIR)/include install jimautoconfext.h $(DESTDIR)/include/jimautoconf.h @@ -71,25 +77,29 @@ test: $(OBJS) $(EXTENSION_OBJS): Makefile ifeq ($(jim_libtype),static) -$(LIBJIM): $(OBJS) $(EXTENSIONS_OBJS) +$(LIBJIM): $(OBJS) $(EXTENSION_OBJS) $(AR) cr $@ $^ $(RANLIB) $@ else -$(LIBJIM): $(OBJS) $(EXTENSIONS_OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) $(SH_LDFLAGS) -o $@ $^ +$(LIBJIM): $(OBJS) $(EXTENSION_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(SH_LDFLAGS) -o $@ $^ $(LDLIBS) endif +%.so: jim-%.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(SHOBJ_CFLAGS) -c -o $*.o $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ $*.o $(SH_LIBJIM) $(LDLIBS) + Tcl.html: jim_tcl.txt asciidoc -o $@ -d manpage $^ || cp @SRCDIR@/Tcl_shipped.html Tcl.html clean: - rm -f *.o lib*.a jimsh Tcl.html + rm -f *.o *.so lib*.a $(JIMSH) Tcl.html if [ -f .clean ]; then rm -f `cat .clean` .clean; fi distclean: clean rm -f jimautoconf.h jimautoconfext.h Makefile config.status config.log rm -rf autom4te.cache -ship: +ship: Tcl.html cp Tcl.html Tcl_shipped.html autoconf && autoheader diff --git a/Tcl_shipped.html b/Tcl_shipped.html index 9f144eb..158111a 100644 --- a/Tcl_shipped.html +++ b/Tcl_shipped.html @@ -6443,7 +6443,7 @@ official policies, either expressed or implied, of the Jim Tcl Project.</tt></pr <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2010-10-29 16:09:39 EST
+Last updated 2010-10-30 18:17:58 EST
</div>
</div>
</body>
@@ -606,12 +606,16 @@ LIBOBJS PLATFORM_PLATFORM PLATFORM_OS SRCDIR +EXTRA_OBJS EXTRA_CFLAGS +JIM_TCL_EXTENSIONS +JIM_MOD_EXTENSIONS JIM_EXTENSIONS -LIBSOCK -LIBDL JIM_LIBTYPE CROSS +LINKFLAGS +SHOBJ_LDFLAGS +SHOBJ_CFLAGS SH_LDFLAGS SH_CFLAGS host_os @@ -680,6 +684,7 @@ enable_math enable_ipv6 with_jim_ext with_out_jim_ext +with_jim_extmod with_jim_shared ' ac_precious_vars='build_alias @@ -1341,12 +1346,22 @@ Optional Packages: bio - Binary I/O, mostly for bio copy/file copy nvp - Name-value pairs C-only API tree - Similar to tcllib ::struct::tree using references + readline - Interface to libreadline + rlprompt - Tcl wrapper around the readline extension + sqlite - Interface to sqlite + sqlite3 - Interface to sqlite3 + win32 - Interface to win32 --with-out-jim-ext="default|ext1 ext2 ..." Specify jim extensions to exclude. If 'default' is given, the default extensions will not be added. + --with-jim-extmod="ext1 ext2 ..." + + Specify jim extensions to build as separate modules (either C or Tcl). + Note that not all extensions can be built as loadable modules. + --with-jim-shared build a shared library instead of a static library Some influential environment variables: @@ -3436,7 +3451,6 @@ else fi -# Shared library support. Because we don't believe in automake! ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then @@ -3537,41 +3551,73 @@ IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + +iswin=no +# Shared library support. Because we don't believe in automake! case $host in *-*-darwin*) - SH_CFLAGS=-dynamic + SH_CFLAGS=-dynamic + + SH_LDFLAGS="-dynamiclib -undefined suppress -flat_namespace" + + SHOBJ_CFLAGS="-dynamic -fno-common" + + SHOBJ_LDFLAGS="-bundle -undefined dynamic_lookup -flat_namespace" + + ;; +*-*-ming*) + # Use the built-in dlopen wrapper + have_dlopen=yes + iswin=yes + SHOBJ_LDFLAGS=-shared + + SH_LDFLAGS=-shared + + ;; +*-*-cygwin) + iswin=yes + SHOBJ_LDFLAGS=-shared + + SH_LDFLAGS=-shared - SH_LDFLAGS="-dynamiclib -undefined suppress -flat_namespace" -;; + ;; *) - SH_CFLAGS=-fPIC + # Generic Unix settings + LINKFLAGS=-rdynamic + + SH_CFLAGS=-fPIC + + SH_LDFLAGS=-shared + + SHOBJ_CFLAGS=-fPIC - SH_LDFLAGS=-shared -;; + SHOBJ_LDFLAGS="-shared -nostartfiles" + + ;; esac if test -n "$host_alias"; then - CROSS=$host_alias- + CROSS=$host_alias- fi # Check whether --enable-fork was given. if test "${enable_fork+set}" = set; then : enableval=$enable_fork; - if test "x$enableval" = "xno" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: * disabling fork" >&5 + if test "x$enableval" = "xno" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: * disabling fork" >&5 $as_echo "* disabling fork" >&6; } - EXTRA_CFLAGS="-DJIM_NOFORK" - fi + EXTRA_CFLAGS="-DJIM_NOFORK" + fi fi # Check whether --enable-math was given. if test "${enable_math+set}" = set; then : enableval=$enable_math; - if test "x$enableval" = "xyes" ; then - EXTRA_CFLAGS="$EXTRA_CFLAGS -DJIM_MATH_FUNCTIONS" - fi + if test "x$enableval" = "xyes" ; then + EXTRA_CFLAGS="$EXTRA_CFLAGS -DJIM_MATH_FUNCTIONS" + fi fi @@ -3579,19 +3625,35 @@ fi # Check whether --enable-ipv6 was given. if test "${enable_ipv6+set}" = set; then : enableval=$enable_ipv6; - if test "x$enableval" = "xyes" ; then - EXTRA_CFLAGS="$EXTRA_CFLAGS -DJIM_IPV6" - fi + if test "x$enableval" = "xyes" ; then + EXTRA_CFLAGS="$EXTRA_CFLAGS -DJIM_IPV6" + fi fi +# Is $1 in list $2? +in_list() +{ + echo "$2" | tr ' ' '\n' | grep "^$1\$" >/dev/null +} + +# Tcl extensions +ext_tcl="stdlib glob tclcompat tree rlprompt" +# C extensions +ext_c="load package readdir array clock exec file posix regexp signal aio bio eventloop syslog nvp readline sqlite sqlite3 win32" + +# Tcl extensions which can be modules +ext_tcl_mod="glob tree rlprompt" +# C extensions which can be modules +ext_c_mod="readdir array clock file posix regexp bio syslog readline sqlite sqlite3 win32" + # All extensions -ext_all=$(echo stdlib load package readdir glob array clock exec file posix regexp signal tclcompat aio bio eventloop syslog nvp tree | tr ' ' '\n' | sort) +ext_all="$ext_c $ext_tcl" -# Default extensions -ext_default=$(echo stdlib load package readdir glob array clock exec file posix regexp signal tclcompat aio eventloop syslog | tr ' ' '\n' | sort) +# Default static extensions +ext_default="stdlib load package readdir glob array clock exec file posix regexp signal tclcompat aio eventloop syslog" # Check whether --with-jim-ext was given. @@ -3606,15 +3668,21 @@ if test "${with_out_jim_ext+set}" = set; then : fi +# Check whether --with-jim-extmod was given. +if test "${with_jim_extmod+set}" = set; then : + withval=$with_jim_extmod; +fi + + if test "$with_out_jim_ext" = "default"; then - # but we always include stdlib - ext_default=stdlib - with_out_jim_ext= + # but we always include stdlib + ext_default=stdlib + with_out_jim_ext= fi # Check valid extension names -for i in $with_jim_ext $with_out_jim_ext; do - echo "$ext_all" | grep "^$i\$" >/dev/null || as_fn_error $? "Unknown extension: $i" "$LINENO" 5 +for i in $with_jim_ext $with_out_jim_ext $with_jim_extmod; do + in_list "$i" "$ext_all" || as_fn_error $? "Unknown extension: $i" "$LINENO" 5 done JIM_LIBTYPE=static @@ -3622,9 +3690,9 @@ JIM_LIBTYPE=static # Check whether --with-jim-shared was given. if test "${with_jim_shared+set}" = set; then : withval=$with_jim_shared; - if test "x$withval" = "xyes" ; then - JIM_LIBTYPE=shared - fi + if test "x$withval" = "xyes" ; then + JIM_LIBTYPE=shared + fi fi @@ -3632,12 +3700,13 @@ fi JIM_LIBTYPE=$JIM_LIBTYPE -for ac_header in sys/un.h +for ac_header in sys/un.h dlfcn.h do : - ac_fn_c_check_header_mongrel "$LINENO" "sys/un.h" "ac_cv_header_sys_un_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_un_h" = xyes; then : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF -#define HAVE_SYS_UN_H 1 +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi @@ -3747,21 +3816,187 @@ $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - LIBDL=${ac_cv_search_dlopen%none required} + have_dlopen=yes; +$as_echo "#define HAVE_DLOPEN 1" >>confdefs.h +fi -$as_echo "#define HAVE_DLOPEN 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing readline" >&5 +$as_echo_n "checking for library containing readline... " >&6; } +if ${ac_cv_search_readline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char readline (); +int +main () +{ +return readline (); + ; + return 0; +} +_ACEOF +for ac_lib in '' readline; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_readline=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_readline+:} false; then : + break +fi +done +if ${ac_cv_search_readline+:} false; then : + +else + ac_cv_search_readline=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_readline" >&5 +$as_echo "$ac_cv_search_readline" >&6; } +ac_res=$ac_cv_search_readline +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +$as_echo "#define HAVE_READLINE 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sqlite_open" >&5 +$as_echo_n "checking for library containing sqlite_open... " >&6; } +if ${ac_cv_search_sqlite_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sqlite_open (); +int +main () +{ +return sqlite_open (); + ; + return 0; +} +_ACEOF +for ac_lib in '' sqlite; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_sqlite_open=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_sqlite_open+:} false; then : + break +fi +done +if ${ac_cv_search_sqlite_open+:} false; then : + +else + ac_cv_search_sqlite_open=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sqlite_open" >&5 +$as_echo "$ac_cv_search_sqlite_open" >&6; } +ac_res=$ac_cv_search_sqlite_open +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +$as_echo "#define HAVE_SQLITE 1" >>confdefs.h fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sqlite3_open" >&5 +$as_echo_n "checking for library containing sqlite3_open... " >&6; } +if ${ac_cv_search_sqlite3_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -ac_fn_c_check_header_mongrel "$LINENO" "winsock.h" "ac_cv_header_winsock_h" "$ac_includes_default" -if test "x$ac_cv_header_winsock_h" = xyes; then : - LIBSOCK=-lwsock32 +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sqlite3_open (); +int +main () +{ +return sqlite3_open (); + ; + return 0; +} +_ACEOF +for ac_lib in '' sqlite3; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_sqlite3_open=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_sqlite3_open+:} false; then : + break +fi +done +if ${ac_cv_search_sqlite3_open+:} false; then : else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 + ac_cv_search_sqlite3_open=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sqlite3_open" >&5 +$as_echo "$ac_cv_search_sqlite3_open" >&6; } +ac_res=$ac_cv_search_sqlite3_open +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +$as_echo "#define HAVE_SQLITE3 1" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 $as_echo_n "checking for library containing socket... " >&6; } if ${ac_cv_search_socket+:} false; then : $as_echo_n "(cached) " >&6 @@ -3814,18 +4049,12 @@ $as_echo "$ac_cv_search_socket" >&6; } ac_res=$ac_cv_search_socket if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - LIBSOCK=${ac_cv_search_socket%none required} - fi -fi - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for environ in unistd.h" >&5 -$as_echo_n "checking for environ in unistd.h... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking environ declared in unistd.h?" >&5 +$as_echo_n "checking environ declared in unistd.h?... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -3838,52 +4067,17 @@ if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - has_environ=yes - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - - # Possibility #2: can environ be found in an available library? - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for extern environ" >&5 -$as_echo_n "checking for extern environ... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ +$as_echo "#define NO_ENVIRON_EXTERN 1" >>confdefs.h -extern char **environ; -int main(int argc, char **argv) { char **ep = environ; } - - -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - - -$as_echo "#define NEED_ENVIRON_EXTERN 1" >>confdefs.h - - has_environ=yes else - - has_environ=no - -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${has_environ}" >&5 -$as_echo "${has_environ}" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -if test "${has_environ}" != "yes" ; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "Could find 'environ' in unistd.h or available libraries. -See \`config.log' for more details" "$LINENO" 5; } -fi - # Now that we know what the platform supports: # For all known extensions: @@ -3891,73 +4085,144 @@ fi # - Otherwise, check to see if it's pre-requisites are met # - If yes, add it if it is enabled or is a default # - If no, error if it is enabled, or do nothing otherwise +# - Modules may be either C or Tcl needs_regexp="ac_cv_func_regcomp" needs_syslog="ac_cv_func_syslog" needs_exec="ac_cv_func_vfork" +needs_readdir="ac_cv_func_opendir" +dep_glob="readdir" needs_posix="ac_cv_func_waitpid" -needs_load="ac_cv_search_dlopen" +needs_load="have_dlopen" needs_signal="ac_cv_func_sigaction ac_cv_func_vfork" -needs_readdir="ac_cv_func_opendir" +needs_readline="ac_cv_search_readline" +dep_rlprompt="readline" +needs_sqlite="ac_cv_search_sqlite_open" +needs_sqlite3="ac_cv_search_sqlite3_open" +needs_win32="iswin" + +# First handle dependencies. If an extension is enabled, also enable its dependency +for i in $ext_default $with_jim_ext; do + in_list "$i" "$with_out_jim_ext" && continue + eval "dep=\$dep_$i" + test -z "$dep" && continue + with_jim_ext="$with_jim_ext $dep" +done +for i in $with_jim_extmod; do + eval "dep=\$dep_$i" + test -z "$dep" && continue + for d in $dep; do + in_list "$d" "$with_jim_ext" || with_jim_extmod="$with_jim_extmod $d" + done +done -ext_add=$(echo $with_jim_ext | tr ' ' '\n') -ext_del=$(echo $with_out_jim_ext | tr ' ' '\n') for i in $ext_all; do - { $as_echo "$as_me:${as_lineno-$LINENO}: checking extension $i" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking extension $i" >&5 $as_echo_n "checking extension $i... " >&6; } - echo "$ext_del" | grep "^$i\$" >/dev/null - if test $? -eq 0; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 + # Disabled? + in_list "$i" "$with_out_jim_ext" + if test $? -eq 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } - continue - fi - # Check dependencies - eval "dep=\$needs_$i" - met=1 - for d in $dep; do - eval "check=\$$d" - if test "$check" = "no" -o -z "$check" ; then - met=0 - break - fi - done - echo "$ext_add" | grep "^$i\$" >/dev/null - if test $? -eq 0; then - if test $met -eq 0; then - as_fn_error $? "dependencies not met" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 + continue + fi + # Check dependencies + eval "dep=\$needs_$i" + met=1 + for d in $dep; do + eval "check=\$$d" + if test "$check" == "no" -o -z "$check" ; then + met=0 + break + fi + done + # Selected as a module? + in_list "$i" "$with_jim_extmod" + if test $? -eq 0; then + in_list "$i" "$ext_tcl_mod" + if test $? -eq 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: tcl" >&5 +$as_echo "tcl" >&6; } + extmodtcl="$exmodtcl $i" + continue + fi + in_list "$i" "$ext_c_mod" + if test $? -ne 0; then + as_fn_error $? "not a module" "$LINENO" 5 + fi + if test $met -eq 0; then + as_fn_error $? "dependencies not met" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: module" >&5 +$as_echo "module" >&6; } + extmod="$extmod $i" + continue + fi + # Selected as a static extension? + in_list "$i" "$with_jim_ext" + if test $? -eq 0; then + if test $met -eq 0; then + as_fn_error $? "dependencies not met" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 $as_echo "enabled" >&6; } - ext="$ext $i" - continue - fi - echo "$ext_default" | grep "^$i\$" >/dev/null - if test $? -eq 0; then - if test $met -eq 0; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled (dependencies)" >&5 + ext="$ext $i" + continue + fi + # Enabled by default? + in_list "$i" "$ext_default" + if test $? -eq 0; then + if test $met -eq 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled (dependencies)" >&5 $as_echo "disabled (dependencies)" >&6; } - continue - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled (default)" >&5 + continue + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled (default)" >&5 $as_echo "enabled (default)" >&6; } - ext="$ext $i" - continue - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not enabled" >&5 + ext="$ext $i" + continue + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not enabled" >&5 $as_echo "not enabled" >&6; } done -ext=$(echo $ext | tr '\n' ' ') -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Jim extensions: $ext" >&5 -$as_echo "Jim extensions: $ext" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Jim static extensions:$ext" >&5 +$as_echo "Jim static extensions:$ext" >&6; } JIM_EXTENSIONS=$ext +if test -n "$extmod"; then +case "$iswin,$JIM_LIBTYPE" in +yes,static) + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cygwin/mingw require --with-jim-shared for dynamic modules +See \`config.log' for more details" "$LINENO" 5; } + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Jim dynamic extensions:$extmod" >&5 +$as_echo "Jim dynamic extensions:$extmod" >&6; } + JIM_MOD_EXTENSIONS=$extmod + +fi +if test -n "$extmodtcl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Jim Tcl extensions:$extmodtcl" >&5 +$as_echo "Jim Tcl extensions:$extmodtcl" >&6; } + JIM_TCL_EXTENSIONS=$extmodtcl + +fi for i in $ext; do - EXTRA_CFLAGS="$EXTRA_CFLAGS -Djim_ext_$i" + EXTRA_CFLAGS="$EXTRA_CFLAGS -Djim_ext_$i" done +if test $iswin = yes; then + in_list "aio" "$ext $extmod" && LIBS="$LIBS -lwsock32" + EXTRA_OBJS="$EXTRA_OBJS jim-win32compat.o" +fi + EXTRA_CFLAGS=$EXTRA_CFLAGS +EXTRA_OBJS=$EXTRA_OBJS + SRCDIR=`dirname $0` PLATFORM_OS=`uname -s` diff --git a/configure.ac b/configure.ac index 202aa41..b8b1705 100755 --- a/configure.ac +++ b/configure.ac @@ -12,52 +12,90 @@ AC_PROG_MAKE_SET # Checks for types AC_CHECK_TYPES(long long, AC_SUBST(DEFINE_HAVE_LONG_LONG,["#define HAVE_LONG_LONG 1"]),AC_SUBST(DEFINE_HAVE_LONG_LONG,["#undef HAVE_LONG_LONG"])) -# Shared library support. Because we don't believe in automake! AC_CANONICAL_HOST + +iswin=no +# Shared library support. Because we don't believe in automake! case $host in *-*-darwin*) - AC_SUBST(SH_CFLAGS,-dynamic) - AC_SUBST(SH_LDFLAGS,"-dynamiclib -undefined suppress -flat_namespace");; + AC_SUBST(SH_CFLAGS,-dynamic) + AC_SUBST(SH_LDFLAGS,"-dynamiclib -undefined suppress -flat_namespace") + AC_SUBST(SHOBJ_CFLAGS,"-dynamic -fno-common") + AC_SUBST(SHOBJ_LDFLAGS,"-bundle -undefined dynamic_lookup -flat_namespace") + ;; +*-*-ming*) + # Use the built-in dlopen wrapper + have_dlopen=yes + iswin=yes + AC_SUBST(SHOBJ_LDFLAGS,-shared) + AC_SUBST(SH_LDFLAGS,-shared) + ;; +*-*-cygwin) + iswin=yes + AC_SUBST(SHOBJ_LDFLAGS,-shared) + AC_SUBST(SH_LDFLAGS,-shared) + ;; *) - AC_SUBST(SH_CFLAGS,-fPIC) - AC_SUBST(SH_LDFLAGS,-shared);; + # Generic Unix settings + AC_SUBST(LINKFLAGS,-rdynamic) + AC_SUBST(SH_CFLAGS,-fPIC) + AC_SUBST(SH_LDFLAGS,-shared) + AC_SUBST(SHOBJ_CFLAGS,-fPIC) + AC_SUBST(SHOBJ_LDFLAGS,"-shared -nostartfiles") + ;; esac if test -n "$host_alias"; then - AC_SUBST(CROSS,$host_alias-) + AC_SUBST(CROSS,$host_alias-) fi AC_ARG_ENABLE(fork, - [ --disable-fork do not use fork (no exec, etc.)], - [ - if test "x$enableval" = "xno" ; then - AC_MSG_RESULT(* disabling fork) - EXTRA_CFLAGS="-DJIM_NOFORK" - fi - ], + [ --disable-fork do not use fork (no exec, etc.)], + [ + if test "x$enableval" = "xno" ; then + AC_MSG_RESULT(* disabling fork) + EXTRA_CFLAGS="-DJIM_NOFORK" + fi + ], ) AC_ARG_ENABLE(math, - [ --enable-math include support for math functions], - [ - if test "x$enableval" = "xyes" ; then - EXTRA_CFLAGS="$EXTRA_CFLAGS -DJIM_MATH_FUNCTIONS" - fi - ] + [ --enable-math include support for math functions], + [ + if test "x$enableval" = "xyes" ; then + EXTRA_CFLAGS="$EXTRA_CFLAGS -DJIM_MATH_FUNCTIONS" + fi + ] ) AC_ARG_ENABLE(ipv6, - [ --enable-ipv6 include ipv6 support in the aio extension], - [ - if test "x$enableval" = "xyes" ; then - EXTRA_CFLAGS="$EXTRA_CFLAGS -DJIM_IPV6" - fi - ] + [ --enable-ipv6 include ipv6 support in the aio extension], + [ + if test "x$enableval" = "xyes" ; then + EXTRA_CFLAGS="$EXTRA_CFLAGS -DJIM_IPV6" + fi + ] ) +# Is $1 in list $2? +in_list() +{ + echo "$2" | tr ' ' '\n' | grep "^$1\$" >/dev/null +} + +# Tcl extensions +ext_tcl="stdlib glob tclcompat tree rlprompt" +# C extensions +ext_c="load package readdir array clock exec file posix regexp signal aio bio eventloop syslog nvp readline sqlite sqlite3 win32" + +# Tcl extensions which can be modules +ext_tcl_mod="glob tree rlprompt" +# C extensions which can be modules +ext_c_mod="readdir array clock file posix regexp bio syslog readline sqlite sqlite3 win32" + # All extensions -ext_all=$(echo stdlib load package readdir glob array clock exec file posix regexp signal tclcompat aio bio eventloop syslog nvp tree | tr ' ' '\n' | sort) +ext_all="$ext_c $ext_tcl" -# Default extensions -ext_default=$(echo stdlib load package readdir glob array clock exec file posix regexp signal tclcompat aio eventloop syslog | tr ' ' '\n' | sort) +# Default static extensions +ext_default="stdlib load package readdir glob array clock exec file posix regexp signal tclcompat aio eventloop syslog" AC_ARG_WITH(jim-ext, [ --with-jim-ext="ext1 ext2 ..." @@ -87,6 +125,11 @@ AC_ARG_WITH(jim-ext, bio - Binary I/O, mostly for bio copy/file copy nvp - Name-value pairs C-only API tree - Similar to tcllib ::struct::tree using references + readline - Interface to libreadline + rlprompt - Tcl wrapper around the readline extension + sqlite - Interface to sqlite + sqlite3 - Interface to sqlite3 + win32 - Interface to win32 ]) AC_ARG_WITH(out-jim-ext, [ --with-out-jim-ext="default|ext1 ext2 ..." @@ -94,79 +137,62 @@ AC_ARG_WITH(out-jim-ext, Specify jim extensions to exclude. If 'default' is given, the default extensions will not be added. ]) +AC_ARG_WITH(jim-extmod, +[ --with-jim-extmod="ext1 ext2 ..." + + Specify jim extensions to build as separate modules (either C or Tcl). + Note that not all extensions can be built as loadable modules. +]) if test "$with_out_jim_ext" = "default"; then - # but we always include stdlib - ext_default=stdlib - with_out_jim_ext= + # but we always include stdlib + ext_default=stdlib + with_out_jim_ext= fi # Check valid extension names -for i in $with_jim_ext $with_out_jim_ext; do - echo "$ext_all" | grep "^$i\$" >/dev/null || AC_MSG_ERROR([Unknown extension: $i]) +for i in $with_jim_ext $with_out_jim_ext $with_jim_extmod; do + in_list "$i" "$ext_all" || AC_MSG_ERROR([Unknown extension: $i]) done JIM_LIBTYPE=static AC_ARG_WITH(jim-shared, - [ --with-jim-shared build a shared library instead of a static library], - [ - if test "x$withval" = "xyes" ; then - JIM_LIBTYPE=shared - fi - ] + [ --with-jim-shared build a shared library instead of a static library], + [ + if test "x$withval" = "xyes" ; then + JIM_LIBTYPE=shared + fi + ] ) AC_SUBST(JIM_LIBTYPE,$JIM_LIBTYPE) -AC_CHECK_HEADERS([sys/un.h]) +AC_CHECK_HEADERS([sys/un.h dlfcn.h]) AC_CHECK_FUNCS([ualarm sysinfo lstat fork vfork]) AC_CHECK_FUNCS([backtrace geteuid mkstemp realpath strptime]) AC_CHECK_FUNCS([regcomp waitpid sigaction sys_signame sys_siglist]) AC_CHECK_FUNCS([syslog opendir readlink sleep usleep pipe inet_ntop getaddrinfo]) -AC_SEARCH_LIBS(dlopen, dl, - AC_SUBST(LIBDL,${ac_cv_search_dlopen%none required}) - AC_DEFINE([HAVE_DLOPEN],[1],[Have the dlopen function]) -) +dnl XXX: Don't need to search for libs if the corresponding extensions aren't enabled +AC_SEARCH_LIBS(dlopen, dl, have_dlopen=yes; AC_DEFINE([HAVE_DLOPEN],[1],[Have the dlopen function])) +AC_SEARCH_LIBS(readline, readline, AC_DEFINE([HAVE_READLINE],[1],[Have libreadline])) +AC_SEARCH_LIBS(sqlite_open, sqlite, AC_DEFINE([HAVE_SQLITE],[1],[Have libsqlite])) +AC_SEARCH_LIBS(sqlite3_open, sqlite3, AC_DEFINE([HAVE_SQLITE3],[1],[Have libsqlite3])) -dnl AC_SEARCH_LIBS doesn't work for mingw, so check for winsock.h instead -AC_CHECK_HEADER(winsock.h,[AC_SUBST(LIBSOCK,-lwsock32)], - AC_SEARCH_LIBS(socket, socket, - AC_SUBST(LIBSOCK,${ac_cv_search_socket%none required}) - ) -) +AC_SEARCH_LIBS(socket, socket) -dnl Look for environ alternatives. Possibility #1: is environ in unistd.h? -AC_MSG_CHECKING([for environ in unistd.h]) +dnl Look for environ. If it is declared in unistd, no need to declare it +AC_MSG_CHECKING([environ declared in unistd.h?]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #define _GNU_SOURCE #include <unistd.h> int main(int argc, char **argv) { char **ep = environ; } ]])], [ AC_MSG_RESULT([yes]) - has_environ=yes - ], [ - AC_MSG_RESULT([no]) - - # Possibility #2: can environ be found in an available library? - AC_MSG_CHECKING([for extern environ]) - AC_LINK_IFELSE([ - AC_LANG_SOURCE([[ -extern char **environ; -int main(int argc, char **argv) { char **ep = environ; } - ]]) - ], [ - AC_DEFINE(NEED_ENVIRON_EXTERN, [1], [Must declare 'environ' to use it.]) - has_environ=yes - ], [ - has_environ=no - ]) - AC_MSG_RESULT([${has_environ}]) -]) - -if test "${has_environ}" != "yes" ; then - AC_MSG_FAILURE([Could find 'environ' in unistd.h or available libraries.]) -fi + AC_DEFINE(NO_ENVIRON_EXTERN, [1], [No need to declare extern 'environ'.]) + ], + AC_MSG_RESULT([no]) +) # Now that we know what the platform supports: @@ -175,64 +201,128 @@ fi # - Otherwise, check to see if it's pre-requisites are met # - If yes, add it if it is enabled or is a default # - If no, error if it is enabled, or do nothing otherwise +# - Modules may be either C or Tcl needs_regexp="ac_cv_func_regcomp" needs_syslog="ac_cv_func_syslog" needs_exec="ac_cv_func_vfork" +needs_readdir="ac_cv_func_opendir" +dep_glob="readdir" needs_posix="ac_cv_func_waitpid" -needs_load="ac_cv_search_dlopen" +needs_load="have_dlopen" needs_signal="ac_cv_func_sigaction ac_cv_func_vfork" -needs_readdir="ac_cv_func_opendir" +needs_readline="ac_cv_search_readline" +dep_rlprompt="readline" +needs_sqlite="ac_cv_search_sqlite_open" +needs_sqlite3="ac_cv_search_sqlite3_open" +needs_win32="iswin" + +# First handle dependencies. If an extension is enabled, also enable its dependency +for i in $ext_default $with_jim_ext; do + in_list "$i" "$with_out_jim_ext" && continue + eval "dep=\$dep_$i" + test -z "$dep" && continue + with_jim_ext="$with_jim_ext $dep" +done +for i in $with_jim_extmod; do + eval "dep=\$dep_$i" + dnl Theoretically, a mod could depend upon something which must be static + test -z "$dep" && continue + dnl If already configured static, don't make it a module + for d in $dep; do + in_list "$d" "$with_jim_ext" || with_jim_extmod="$with_jim_extmod $d" + done +done -ext_add=$(echo $with_jim_ext | tr ' ' '\n') -ext_del=$(echo $with_out_jim_ext | tr ' ' '\n') for i in $ext_all; do - AC_MSG_CHECKING(extension $i) - echo "$ext_del" | grep "^$i\$" >/dev/null - if test $? -eq 0; then - AC_MSG_RESULT(disabled) - continue - fi - # Check dependencies - eval "dep=\$needs_$i" - met=1 - for d in $dep; do - eval "check=\$$d" - if test "$check" = "no" -o -z "$check" ; then - met=0 - break - fi - done - echo "$ext_add" | grep "^$i\$" >/dev/null - if test $? -eq 0; then - if test $met -eq 0; then - AC_MSG_ERROR(dependencies not met) - fi - AC_MSG_RESULT(enabled) - ext="$ext $i" - continue - fi - echo "$ext_default" | grep "^$i\$" >/dev/null - if test $? -eq 0; then - if test $met -eq 0; then - AC_MSG_RESULT(disabled (dependencies)) - continue - fi - AC_MSG_RESULT(enabled (default)) - ext="$ext $i" - continue - fi - AC_MSG_RESULT(not enabled) + AC_MSG_CHECKING(extension $i) + # Disabled? + in_list "$i" "$with_out_jim_ext" + if test $? -eq 0; then + AC_MSG_RESULT(disabled) + continue + fi + # Check dependencies + eval "dep=\$needs_$i" + met=1 + for d in $dep; do + eval "check=\$$d" + if test "$check" == "no" -o -z "$check" ; then + met=0 + break + fi + done + # Selected as a module? + in_list "$i" "$with_jim_extmod" + if test $? -eq 0; then + in_list "$i" "$ext_tcl_mod" + if test $? -eq 0; then + dnl Easy, a Tcl module + AC_MSG_RESULT(tcl) + extmodtcl="$exmodtcl $i" + continue + fi + in_list "$i" "$ext_c_mod" + if test $? -ne 0; then + AC_MSG_ERROR(not a module) + fi + if test $met -eq 0; then + AC_MSG_ERROR(dependencies not met) + fi + AC_MSG_RESULT(module) + extmod="$extmod $i" + continue + fi + # Selected as a static extension? + in_list "$i" "$with_jim_ext" + if test $? -eq 0; then + if test $met -eq 0; then + AC_MSG_ERROR(dependencies not met) + fi + AC_MSG_RESULT(enabled) + ext="$ext $i" + continue + fi + # Enabled by default? + in_list "$i" "$ext_default" + if test $? -eq 0; then + if test $met -eq 0; then + AC_MSG_RESULT(disabled (dependencies)) + continue + fi + AC_MSG_RESULT(enabled (default)) + ext="$ext $i" + continue + fi + AC_MSG_RESULT(not enabled) done - -ext=$(echo $ext | tr '\n' ' ') -AC_MSG_RESULT(Jim extensions: $ext) + +AC_MSG_RESULT(Jim static extensions:$ext) AC_SUBST(JIM_EXTENSIONS,$ext) +if test -n "$extmod"; then +case "$iswin,$JIM_LIBTYPE" in +yes,static) + AC_MSG_FAILURE([cygwin/mingw require --with-jim-shared for dynamic modules]) + ;; +esac + AC_MSG_RESULT(Jim dynamic extensions:$extmod) + AC_SUBST(JIM_MOD_EXTENSIONS,$extmod) +fi +if test -n "$extmodtcl"; then + AC_MSG_RESULT(Jim Tcl extensions:$extmodtcl) + AC_SUBST(JIM_TCL_EXTENSIONS,$extmodtcl) +fi for i in $ext; do - EXTRA_CFLAGS="$EXTRA_CFLAGS -Djim_ext_$i" + EXTRA_CFLAGS="$EXTRA_CFLAGS -Djim_ext_$i" done +if test $iswin = yes; then + in_list "aio" "$ext $extmod" && LIBS="$LIBS -lwsock32" + EXTRA_OBJS="$EXTRA_OBJS jim-win32compat.o" +fi + AC_SUBST(EXTRA_CFLAGS,$EXTRA_CFLAGS) +AC_SUBST(EXTRA_OBJS,$EXTRA_OBJS) AC_SUBST(SRCDIR,`dirname $0`) AC_SUBST(PLATFORM_OS,`uname -s`) AC_SUBST(PLATFORM_PLATFORM,unix) @@ -4,6 +4,7 @@ # # See LICENCE in this directory for licensing. +package require readdir # Implements the Tcl glob command # @@ -5,9 +5,11 @@ * Dynamic libraries support (WIN32 not supported) * ---------------------------------------------------------------------------*/ -#ifdef JIM_DYNLIB +#if defined(HAVE_DLOPEN) || defined(HAVE_DLOPEN_COMPAT) +#ifdef HAVE_DLFCN_H #include <dlfcn.h> +#endif int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) { diff --git a/jim-win32.c b/jim-win32.c new file mode 100644 index 0000000..2925fb5 --- /dev/null +++ b/jim-win32.c @@ -0,0 +1,487 @@ +/* WIN32 extension + * + * Copyright (C) 2005 Pat Thoyts <patthoyts@users.sourceforge.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * A copy of the license is also included in the source distribution + * of Jim, as a TXT file name called LICENSE. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <jim.h> +#include <shellapi.h> +#include <lmcons.h> +#include <psapi.h> +#include <ctype.h> + +#if _MSC_VER >= 1000 +#pragma comment(lib, "shell32") +#pragma comment(lib, "user32") +#pragma comment(lib, "advapi32") +#pragma comment(lib, "psapi") +#endif /* _MSC_VER >= 1000 */ + +static Jim_Obj * +Win32ErrorObj(Jim_Interp *interp, const char * szPrefix, DWORD dwError) +{ + Jim_Obj *msgObj = NULL; + char * lpBuffer = NULL; + DWORD dwLen = 0; + + dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, LANG_NEUTRAL, + (char *)&lpBuffer, 0, NULL); + if (dwLen < 1) { + dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, + "code 0x%1!08X!%n", 0, LANG_NEUTRAL, + (char *)&lpBuffer, 0, (va_list *)&dwError); + } + + msgObj = Jim_NewStringObj(interp, szPrefix, -1); + if (dwLen > 0) { + char *p = lpBuffer + dwLen - 1; /* remove cr-lf at end */ + for ( ; p && *p && isspace((unsigned)*p); p--) + ; + *++p = 0; + Jim_AppendString(interp, msgObj, ": ", 2); + Jim_AppendString(interp, msgObj, lpBuffer, -1); + } + LocalFree((HLOCAL)lpBuffer); + return msgObj; +} + +/* win32.ShellExecute verb file args */ +static int +Win32_ShellExecute(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + int r; + const char *verb, *file, *parm = NULL; + char cwd[MAX_PATH + 1]; + + if (objc < 3 || objc > 4) { + Jim_WrongNumArgs(interp, 1, objv, "verb path ?parameters?"); + return JIM_ERR; + } + verb = Jim_GetString(objv[1], NULL); + file = Jim_GetString(objv[2], NULL); + GetCurrentDirectoryA(MAX_PATH + 1, cwd); + if (objc == 4) + parm = Jim_GetString(objv[3], NULL); + r = (int)ShellExecuteA(NULL, verb, file, parm, cwd, SW_SHOWNORMAL); + if (r < 33) + Jim_SetResult(interp, + Win32ErrorObj(interp, "ShellExecute", GetLastError())); + return (r < 33) ? JIM_ERR : JIM_OK; +} + + +/* win32.FindWindow title ?class? */ +static int +Win32_FindWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + const char *title = NULL, *class = NULL; + HWND hwnd = NULL; + int r = JIM_OK; + + if (objc < 2 || objc > 3) { + Jim_WrongNumArgs(interp, 1, objv, "title ?class?"); + return JIM_ERR; + } + title = Jim_GetString(objv[1], NULL); + if (objc == 3) + class = Jim_GetString(objv[2], NULL); + hwnd = FindWindowA(class, title); + + if (hwnd == NULL) { + Jim_SetResult(interp, + Win32ErrorObj(interp, "FindWindow", GetLastError())); + r = JIM_ERR; + } else { + Jim_SetResult(interp, Jim_NewIntObj(interp, (long)hwnd)); + } + return r; +} + +/* win32.CloseWindow windowHandle */ +static int +Win32_CloseWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + long hwnd; + + if (objc != 2) { + Jim_WrongNumArgs(interp, 1, objv, "?windowHandle?"); + return JIM_ERR; + } + if (Jim_GetLong(interp, objv[1], &hwnd) != JIM_OK) + return JIM_ERR; + if (!CloseWindow((HWND)hwnd)) { + Jim_SetResult(interp, + Win32ErrorObj(interp, "CloseWindow", GetLastError())); + return JIM_ERR; + } + return JIM_OK; +} + +static int +Win32_GetActiveWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + Jim_SetResult(interp, Jim_NewIntObj(interp, (DWORD)GetActiveWindow())); + return JIM_OK; +} + +static int +Win32_SetActiveWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + HWND hwnd, old; + int r = JIM_OK; + + if (objc != 2) { + Jim_WrongNumArgs(interp, 1, objv, "windowHandle"); + return JIM_ERR; + } + r = Jim_GetLong(interp, objv[1], (long *)&hwnd); + if (r == JIM_OK) { + old = SetActiveWindow(hwnd); + if (old == NULL) { + Jim_SetResult(interp, + Win32ErrorObj(interp, "SetActiveWindow", GetLastError())); + r = JIM_ERR; + } else { + Jim_SetResult(interp, Jim_NewIntObj(interp, (long)old)); + } + } + return r; +} + +static int +Win32_SetForegroundWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + HWND hwnd; + int r = JIM_OK; + + if (objc != 2) { + Jim_WrongNumArgs(interp, 1, objv, "windowHandle"); + return JIM_ERR; + } + r = Jim_GetLong(interp, objv[1], (long *)&hwnd); + if (r == JIM_OK) { + if (!SetForegroundWindow(hwnd)) { + Jim_SetResult(interp, + Win32ErrorObj(interp, "SetForegroundWindow", GetLastError())); + r = JIM_ERR; + } + } + return r; +} + +static int +Win32_Beep(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + long freq, duration; + int r = JIM_OK; + + if (objc != 3) { + Jim_WrongNumArgs(interp, 1, objv, "freq duration"); + return JIM_ERR; + } + r = Jim_GetLong(interp, objv[1], &freq); + if (r == JIM_OK) + r = Jim_GetLong(interp, objv[2], &duration); + if (freq < 0x25) freq = 0x25; + if (freq > 0x7fff) freq = 0x7fff; + if (r == JIM_OK) { + if (!Beep(freq, duration)) { + Jim_SetResult(interp, + Win32ErrorObj(interp, "Beep", GetLastError())); + r = JIM_ERR; + } + } + return r; +} + +static int +Win32_GetComputerName(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + char name[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD size = MAX_COMPUTERNAME_LENGTH; + int r = JIM_OK; + + if (objc != 1) { + Jim_WrongNumArgs(interp, 1, objv, ""); + return JIM_ERR; + } + + if (GetComputerNameA(name, &size)) { + Jim_Obj *nameObj = Jim_NewStringObj(interp, name, size); + Jim_SetResult(interp, nameObj); + } else { + Jim_SetResult(interp, + Win32ErrorObj(interp, "GetComputerName", GetLastError())); + r = JIM_ERR; + } + + return r; +} + +static int +Win32_GetUserName(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + char name[UNLEN + 1]; + DWORD size = UNLEN; + int r = JIM_OK; + + if (objc != 1) { + Jim_WrongNumArgs(interp, 1, objv, ""); + return JIM_ERR; + } + + if (GetUserNameA(name, &size)) { + Jim_Obj *nameObj = Jim_NewStringObj(interp, name, size); + Jim_SetResult(interp, nameObj); + } else { + Jim_SetResult(interp, + Win32ErrorObj(interp, "GetUserName", GetLastError())); + r = JIM_ERR; + } + + return r; +} + +static int +Win32_GetModuleFileName(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + HMODULE hModule = NULL; + char path[MAX_PATH]; + DWORD len = 0; + + if (objc > 2) { + Jim_WrongNumArgs(interp, 1, objv, "?moduleid?"); + return JIM_ERR; + } + + if (objc == 2) { + if (Jim_GetLong(interp, objv[1], (long *)&hModule) != JIM_OK) { + return JIM_ERR; + } + } + + len = GetModuleFileNameA(hModule, path, MAX_PATH); + if (len != 0) { + Jim_Obj *pathObj = Jim_NewStringObj(interp, path, len); + Jim_SetResult(interp, pathObj); + } else { + Jim_SetResult(interp, + Win32ErrorObj(interp, "GetModuleFileName", GetLastError())); + return JIM_ERR; + } + + return JIM_OK; +} + +static int +Win32_GetVersion(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + Jim_SetResult(interp, Jim_NewIntObj(interp, GetVersion())); + return JIM_OK; +} + +static int +Win32_GetTickCount(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + Jim_SetResult(interp, Jim_NewIntObj(interp, GetTickCount())); + return JIM_OK; +} + +static int +Win32_GetSystemTime(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + Jim_Obj *a[16]; + size_t n = 0; + SYSTEMTIME t; + GetSystemTime(&t); + +#define JIMADD(name) \ + a[n++] = Jim_NewStringObj(interp, #name, -1); \ + a[n++] = Jim_NewIntObj(interp, t.w ## name ) + + JIMADD(Year); + JIMADD(Month); + JIMADD(DayOfWeek); + JIMADD(Day); + JIMADD(Hour); + JIMADD(Minute); + JIMADD(Second); + JIMADD(Milliseconds); +#undef JIMADD + + Jim_SetResult(interp, Jim_NewListObj(interp, a, n)); + return JIM_OK; +} + +/* function not available on mingw or cygwin */ +#if !defined(__MINGW32__) && !defined(__CYGWIN__) +// FIX ME: win2k+ so should do version checks really. +static int +Win32_GetPerformanceInfo(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + Jim_Obj *a[26]; + size_t n = 0; + PERFORMANCE_INFORMATION pi; + + if (!GetPerformanceInfo(&pi, sizeof(pi))) { + Jim_SetResult(interp, + Win32ErrorObj(interp, "GetPerformanceInfo", GetLastError())); + return JIM_ERR; + } + +#define JIMADD(name) \ + a[n++] = Jim_NewStringObj(interp, #name, -1); \ + a[n++] = Jim_NewIntObj(interp, pi. name ) + + JIMADD(CommitTotal); + JIMADD(CommitLimit); + JIMADD(CommitPeak); + JIMADD(PhysicalTotal); + JIMADD(PhysicalAvailable); + JIMADD(SystemCache); + JIMADD(KernelTotal); + JIMADD(KernelPaged); + JIMADD(KernelNonpaged); + JIMADD(PageSize); + JIMADD(HandleCount); + JIMADD(ProcessCount); + JIMADD(ThreadCount); +#undef JIMADD + + Jim_SetResult(interp, Jim_NewListObj(interp, a, n)); + return JIM_OK; +} +#endif + +static int +Win32_SetComputerName(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + int r = JIM_OK; + const char *name; + if (objc != 2) { + Jim_WrongNumArgs(interp, 1, objv, "computername"); + return JIM_ERR; + } + name = Jim_GetString(objv[1], NULL); + if (!SetComputerNameA(name)) { + Jim_SetResult(interp, + Win32ErrorObj(interp, "SetComputerName", GetLastError())); + r = JIM_ERR; + } + return r; +} + +static int +Win32_GetModuleHandle(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + HMODULE hModule = NULL; + const char *name = NULL; + + if (objc < 1 || objc > 2) { + Jim_WrongNumArgs(interp, 1, objv, "?name?"); + return JIM_ERR; + } + if (objc == 2) + name = Jim_GetString(objv[1], NULL); + hModule = GetModuleHandleA(name); + if (hModule == NULL) { + Jim_SetResult(interp, + Win32ErrorObj(interp, "GetModuleHandle", GetLastError())); + return JIM_ERR; + } + Jim_SetResult(interp, Jim_NewIntObj(interp, (unsigned long)hModule)); + return JIM_OK; +} + +static int +Win32_LoadLibrary(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + HMODULE hLib = NULL; + if (objc != 2) { + Jim_WrongNumArgs(interp, 1, objv, "path"); + return JIM_ERR; + } + hLib = LoadLibraryA(Jim_GetString(objv[1], NULL)); + if (hLib == NULL) { + Jim_SetResult(interp, + Win32ErrorObj(interp, "LoadLibrary", GetLastError())); + return JIM_ERR; + } + Jim_SetResult(interp, Jim_NewIntObj(interp, (unsigned long)hLib)); + return JIM_OK; +} + +static int +Win32_FreeLibrary(Jim_Interp *interp, int objc, Jim_Obj * const *objv) +{ + HMODULE hModule = NULL; + int r = JIM_OK; + + if (objc != 2) { + Jim_WrongNumArgs(interp, 1, objv, "hmodule"); + return JIM_ERR; + } + + r = Jim_GetLong(interp, objv[1], (long *)&hModule); + if (r == JIM_OK) { + if (!FreeLibrary(hModule)) { + Jim_SetResult(interp, + Win32ErrorObj(interp, "FreeLibrary", GetLastError())); + r = JIM_ERR; + } + } + + return r; +} + + +/* ---------------------------------------------------------------------- */ + +int +Jim_win32Init(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "win32", "1.0", JIM_ERRMSG)) + return JIM_ERR; + +#define CMD(name) \ + Jim_CreateCommand(interp, "win32." #name , Win32_ ## name , NULL, NULL) + + CMD(ShellExecute); + CMD(FindWindow); + CMD(CloseWindow); + CMD(GetActiveWindow); + CMD(SetActiveWindow); + CMD(SetForegroundWindow); + CMD(Beep); + CMD(GetComputerName); + CMD(SetComputerName); + CMD(GetUserName); + CMD(GetModuleFileName); + CMD(GetVersion); + CMD(GetTickCount); + CMD(GetSystemTime); +#if !defined(__MINGW32__) && !defined(__CYGWIN__) + CMD(GetPerformanceInfo); +#endif + CMD(GetModuleHandle); + CMD(LoadLibrary); + CMD(FreeLibrary); + + return JIM_OK; +} diff --git a/jim-win32compat.c b/jim-win32compat.c index 76e7a96..bbda937 100644 --- a/jim-win32compat.c +++ b/jim-win32compat.c @@ -1,5 +1,34 @@ #include <jim.h> +#ifdef HAVE_DLOPEN_COMPAT +void *dlopen(const char *path, int mode) +{ + JIM_NOTUSED(mode); + + return (void *)LoadLibraryA(path); +} + +int dlclose(void *handle) +{ + FreeLibrary((HANDLE)handle); + return 0; +} + +void *dlsym(void *handle, const char *symbol) +{ + return GetProcAddress((HMODULE)handle, symbol); +} + +const char *dlerror(void) +{ + static char msg[121]; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), + LANG_NEUTRAL, msg, sizeof(msg) - 1, NULL); + return msg; +} +#endif + +#if !defined(__MINGW32__) && !defined(__CYGWIN__) /* POSIX gettimeofday() compatibility for WIN32 */ int gettimeofday(struct timeval *tv, void *unused) { @@ -88,29 +117,4 @@ struct dirent *readdir(DIR * dir) } return result; } - -void *dlopen(const char *path, int mode) -{ - JIM_NOTUSED(mode); - - return (void *)LoadLibraryA(path); -} - -int dlclose(void *handle) -{ - FreeLibrary((HANDLE)handle); - return 0; -} - -void *dlsym(void *handle, const char *symbol) -{ - return GetProcAddress((HMODULE)handle, symbol); -} - -const char *dlerror(void) -{ - static char msg[121]; - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), - LANG_NEUTRAL, msg, sizeof(msg) - 1, NULL); - return msg; -} +#endif diff --git a/jim-win32compat.h b/jim-win32compat.h index 21edaf2..12275ba 100644 --- a/jim-win32compat.h +++ b/jim-win32compat.h @@ -1,9 +1,7 @@ #ifndef JIM_WIN32COMPAT_H #define JIM_WIN32COMPAT_H -#ifndef WIN32 - #define WIN32 1 -#endif +#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) #ifndef STRICT #define STRICT #endif @@ -11,6 +9,25 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> +/* None of these is needed for cygwin */ +#if !defined(__CYGWIN__) + +#define JIM_ANSIC +#define MKDIR_ONE_ARG +#define rand_r(S) ((void)(S), rand()) +#define localtime_r(T,TM) ((void)(TM), localtime(T)) + +#define HAVE_DLOPEN_COMPAT + +#define RTLD_LAZY 0 +void *dlopen(const char *path, int mode); +int dlclose(void *handle); +void *dlsym(void *handle, const char *symbol); +const char *dlerror(void); + +#if !defined(__MINGW32__) +/* Most of these are really gcc vs msvc */ + #if _MSC_VER >= 1000 #pragma warning(disable:4146) #endif @@ -51,5 +68,10 @@ typedef struct DIR { DIR *opendir(const char *name); int closedir(DIR *dir); struct dirent *readdir(DIR *dir); +#endif /* MSC */ + +#endif /* __MINGW32__ */ + +#endif /* __CYGWIN__ */ #endif @@ -13304,7 +13304,7 @@ static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv const char *val; if (argc == 1) { -#ifdef NEED_ENVIRON_EXTERN +#ifndef NO_ENVIRON_EXTERN extern char **environ; #endif @@ -79,57 +79,44 @@ extern "C" { * System configuration * autoconf (configure) will set these * ---------------------------------------------------------------------------*/ -#if (defined(_WIN32) || defined(WIN32)) && !defined(__MINGW32__) #include <jim-win32compat.h> -#else - -#if defined(__MINGW32__) -#define JIM_ANSIC -#define MKDIR_ONE_ARG -#define rand_r(S) ((void)(S), rand()) -#define localtime_r(T,TM) ((void)(TM), localtime(T)) -#endif #ifndef HAVE_NO_AUTOCONF #include <jimautoconf.h> #endif -#if defined(HAVE_DLOPEN) -#define JIM_DYNLIB /* Dynamic library support */ -#endif - /* ----------------------------------------------------------------------------- * Compiler specific fixes. * ---------------------------------------------------------------------------*/ /* Long Long type and related issues */ -#ifdef HAVE_LONG_LONG -# define jim_wide long long -# ifndef LLONG_MAX -# define LLONG_MAX 9223372036854775807LL -# endif -# ifndef LLONG_MIN -# define LLONG_MIN (-LLONG_MAX - 1LL) +#ifndef jim_wide +# ifdef HAVE_LONG_LONG +# define jim_wide long long +# ifndef LLONG_MAX +# define LLONG_MAX 9223372036854775807LL +# endif +# ifndef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX - 1LL) +# endif +# define JIM_WIDE_MIN LLONG_MIN +# define JIM_WIDE_MAX LLONG_MAX +# else +# define jim_wide long +# define JIM_WIDE_MIN LONG_MIN +# define JIM_WIDE_MAX LONG_MAX +# define strtoull strtoul # endif -# define JIM_WIDE_MIN LLONG_MIN -# define JIM_WIDE_MAX LLONG_MAX -#else -# define jim_wide long -# define JIM_WIDE_MIN LONG_MIN -# define JIM_WIDE_MAX LONG_MAX -# define strtoull strtoul -#endif /* ----------------------------------------------------------------------------- * LIBC specific fixes * ---------------------------------------------------------------------------*/ -#ifdef HAVE_LONG_LONG -# define JIM_WIDE_MODIFIER "lld" -#else -# define JIM_WIDE_MODIFIER "ld" -#endif - +# ifdef HAVE_LONG_LONG +# define JIM_WIDE_MODIFIER "lld" +# else +# define JIM_WIDE_MODIFIER "ld" +# endif #endif /* ----------------------------------------------------------------------------- diff --git a/jimautoconf.h.in b/jimautoconf.h.in index fbb871f..8e1acef 100644 --- a/jimautoconf.h.in +++ b/jimautoconf.h.in @@ -3,6 +3,9 @@ /* Define to 1 if you have the `backtrace' function. */ #undef HAVE_BACKTRACE +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + /* Have the dlopen function */ #undef HAVE_DLOPEN @@ -39,6 +42,9 @@ /* Define to 1 if you have the `pipe' function. */ #undef HAVE_PIPE +/* Have libreadline */ +#undef HAVE_READLINE + /* Define to 1 if you have the `readlink' function. */ #undef HAVE_READLINK @@ -54,6 +60,12 @@ /* Define to 1 if you have the `sleep' function. */ #undef HAVE_SLEEP +/* Have libsqlite */ +#undef HAVE_SQLITE + +/* Have libsqlite3 */ +#undef HAVE_SQLITE3 + /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H @@ -105,8 +117,8 @@ /* Define to 1 if you have the `waitpid' function. */ #undef HAVE_WAITPID -/* Must declare 'environ' to use it. */ -#undef NEED_ENVIRON_EXTERN +/* No need to declare extern 'environ'. */ +#undef NO_ENVIRON_EXTERN /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT diff --git a/tests/Makefile b/tests/Makefile index d9d3a7c..0efd6fc 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,4 +1,5 @@ JIMSH ?= ../jimsh +LD_LIBRARY_PATH := ..:$(LD_LIBRARY_PATH) test: $(JIMSH) @set -e; for i in *.test; do $(JIMSH) $$i; done |