Re: [tcljava-dev] PATCH: Jacl
Brought to you by:
mdejong
|
From: Tom P. <tpo...@ny...> - 2003-03-14 04:28:50
|
On Thu, Mar 13, 2003 at 02:35:48PM -0800, Mo DeJong wrote:
> On Sun, 4 Aug 2002 14:06:28 -0600
> Tom Poindexter <tpo...@ny...> wrote:
>
> ...
>
> > 8. TCL.java: change scope of OK to public, for use by Swank.
>
> I still don't get why folks keep asking for this change. The TCL.OK
> value should not be needed outside the Jacl package.
>
Well, I understand the design principles involved, but for me, it boils down
to a choice: being right, or running Swank. I'd rather run Swank.
Also required is the patch to src/jacl/tcl/lang/Interp.java, making
allowExceptions() public, also used by Swank.
I think Swank is too important NOT to make run 'out of the box' with Jacl.
Bruce, perhaps you can update us all on any Swank changes that we might be
so lucky to see in the near term? Bruce and Mo - perhaps there is another
resolution that amiable to all? I confess that I haven't studied Swank
internals much, so I can't make suggestions at this point.
Here are the few 'trouble' spots I see:
TCL.OK:
BindCmd.java: return TCL.OK;
BindCmd.java: return TCL.OK;
SwkCell.java: return TCL.OK;
SwkTableModel.java: return TCL.OK;
allowExceptions():
BindCmd.java: interp.allowExceptions();
BindCmd.java: interp.allowExceptions();
SwkTableModel.java: interp.allowExceptions();
Mo, *thanks* for all of your hard work in the new IO package, etc. Jacl is
certainly due for a release to get it on the minds of users again.
There are a few things I been looking at since your announcement, and it boils
done to one bug and several convenience factors. First, the bug that I see.
This has to to with my Hyde package, still not generally released because I
never found a good work around for the binary file IO problem (see my message
to the list on 2002-07-24.) It looks like the binary-ness for fconfigure
is working to expectation now. The remaining problem seems to be in
the actual 'binary' command. Here's some test code:
---- cut here -----------------------------------------------------------------
package require java
puts "system encoding is $env(file.encoding)"
array set cacheCode [list multtwoCmd [binary format H* cafebabe0000002e000f0a0003000c07000d07000e0100063c696e69743e010003282956010004436f646501000f4c696e654e756d6265725461626c650100076d756c7474776f010005284949294901000a536f7572636546696c6501000f6d756c7474776f436d642e6a6176610c0004000501000f687964652f6d756c7474776f436d640100106a6176612f6c616e672f4f626a656374002100020003000000000002000100040005000100060000001d00010001000000052ab70001b100000001000700000006000100000002000900080009000100060000002200020003000000061a1b683d1cac0000000100070000000a000200000008000400090001000a00000002000b]]
set byteCode $cacheCode(multtwoCmd)
set defobj [java::defineclass $byteCode]
if {[string equal $defobj [java::null]]} {
puts "failed defineclass"
} else {
proc multtwo {a b} {return [java::call hyde.multtwoCmd multtwo $a $b]}
puts "int result: multtwo 4 11 = [multtwo 4 11]"
}
---- cut here -----------------------------------------------------------------
This bit of code is the basis for my Hyde package. Compile a class on the fly,
read the byte codes back in, save in a cache (a Tcl string converted back to
binary), use the java::defineclass to give it to the JVM, then a little
extra glue to make it look like a Tcl procedure.
Here's the code as it looks with hyde:
hyde::jproc int multtwo {int x int y} {
int result;
result = x * y;
return result;
}
puts stderr "int result: multtwo 4 11 = [multtwo 4 11]"
To demostrate the bug, try running:
$ LANG=en_US jaclsh testbinary.tcl
system encoding is ISO-8859-1
int result: multtwo 4 11 = 44
$ LANG=en_US.iso885915 jaclsh testbinary.tcl
system encoding is ISO-8859-15
failed defineclass
I put some debugging code in src/tcljava/tcl/lang/JavaDefineClassCmd.java:
line 47:
if (argv.length != 2) {
throw new TclNumArgsException(interp, 1, argv,
"classbytes");
}
classData = argv[1].toString().getBytes();
// print out the bytes codes as ints
for (int i = 0; i < classData.length; i++) {
Byte b = new Byte(classData[i]);
System.out.print( b.intValue() );
System.out.print(" ");
if ((i % 16) == 0 && i > 0) {
System.out.println("");
}
}
tclClassLoader = new TclClassLoader(interp, null);
result = tclClassLoader.defineClass(null, classData);
It turns out the with the LANG=en_US.iso885915, the fourth byte in the
class 'cafebabe' signature gets corrupted. If the class file was
longer, there would probably be additional mangling.
With LANG=en_US, the first 16 bytes are:
-54 -2 -70 -66 0 0 0 46 0 15 10 0 3 0 12 7 0
With LANG=en_US.iso885915:
-54 -2 -70 63 0 0 0 46 0 15 10 0 3 0 12 7 0
To note, the LANG=en_US.iso885915 was set on some Linux machine, for some
version of RedHat. I shorten it to 'en_US' in the /etc/sysconfig/i18n
file.
Perhaps there is some magic to coerce the bytes to be in the right order with
the 'encoding' command, but I haven't found it yet.
Ok, on to the nice to haves, it boils down to two patches and a wishlist.
The first patch is to jaclsh.in. My version adds the following:
-the ability to use some shell parameters set outside the shell
-run jaclsh or wisk, by checking the $0 variable, and adding the
swank.jar to CLASSPATH and using the correct Shell class.
-set a JACL_LIBRARY path to use as the library.
-use an alternate JDK/JRE than the one Jacl was built with.
-pass additional -D properties to the JVM.
The companion patch is to init.tcl to add the JACL_LIBRARY to auto_path.
My shell script does several things I find invaluable, the first and
foremost is using alternate JDK and Jacl flag settings. I'm doing a lot of
EJB testing with Jacl. Running IBM WebSphere is happiest when using the
IBM JDK. I also need to pass other -Dxx=yy properties to make Jacl connect
as an EJB client, e.g.:
# run test script under WebSphere
JAVA_HOME=$WAS_HOME/java
CLASSPATH=<way long class path omitted>
WAS_PROPS="-Dws.ext.dirs=$WAS_HOME/classes:$WAS_HOME/lib/ext:$WAS_HOME/lib:$WAS_
HOME/web/help:$WAS_HOME/properties:$DBDRIVER_PATH:$WAS_USER_DIRS -Dserver.root=$
WAS_HOME"
export JACL_FLAGS="-ms5m -mx22m"
export JACL_PROPS="$WAS_PROPS"
jaclsh blah.tcl
My patch file, which also includes the TCL.OK and allowExceptions() patches,
is below.
Ok, and now for my wish list, three things: 1. fileevent, 2. lset, 3. jacllib.
Adding fileevent might be ugly until Jacl is fully converted to use 1.4's
NIO package. Lset would be nice, keeping in pace with Tcl 8.4.2.
'Jacllib' should be able to steal much of the same code has tcllib, at least
the code that isn't doing socket things with fileevent. I'm also looking for
a home for my hyde pacakge, so I have ulterior motives. I might be willing
to invest some time to put together some code.
My current patch:
--- ../tcljava.cvs/jaclsh.in 2002-07-23 09:07:17.000000000 -0600
+++ jaclsh.in 2003-03-12 13:20:08.000000000 -0700
@@ -11,6 +11,13 @@
# Copyright (c) 1998, 1999, 2000 Moses DeJong
# All Rights Reserved, see license.terms for license information.
+# User environment variables that affect this script:
+# JAVA_HOME path to java home, in order to use alternate jvm
+# CLASSPATH additional classpaths
+# JACL_LIBRARY path to package library dir, defaults to Jacl jar library dir
+# JACL_FLAGS java jvm flags for jacl
+# JACL_PROPS extra -Dxxx=yyy properties to pass to jvm
+
# Install prefix for jacl package, defaults to /usr/local
prefix=@prefix@
@@ -21,21 +28,43 @@
# includes the .jar files and any .tcl files
XP_TCLJAVA_INSTALL_DIR=${prefix}/lib/tcljava${TCLJAVA_VERSION}
+# Directory where swank jar lives
+XP_SWANK_INSTALL_DIR=${XP_TCLJAVA_INSTALL_DIR}
+
+# Set jacl.tcllibpath from JACL_LIBRARY or default
+JACL_LIBPATH="-Djacl.tcllibpath=${JACL_LIBRARY:-$XP_TCLJAVA_INSTALL_DIR}"
+
# Add the .jar library files to the CLASSPATH
-JACL_CLASSPATH=@JAVA_CLASSPATH@:${XP_TCLJAVA_INSTALL_DIR}/tcljava.jar:${XP_TCLJAVA_INSTALL_DIR}/jacl.jar:
+# Check if running jaclsh or wisk, use the corresponding shell and classpath
+if [ `basename $0` = "wisk" ] ; then
+ JACL_SHELL=tcl.lang.SwkShell
+ JACL_CLASSPATH=@JAVA_CLASSPATH@:${XP_SWANK_INSTALL_DIR}/swank.jar:${XP_TCLJAVA_INSTALL_DIR}/tcljava.jar:${XP_TCLJAVA_INSTALL_DIR}/jacl.jar
+else
+ JACL_SHELL=tcl.lang.Shell
+ JACL_CLASSPATH=@JAVA_CLASSPATH@:${XP_TCLJAVA_INSTALL_DIR}/tcljava.jar:${XP_TCLJAVA_INSTALL_DIR}/jacl.jar
+fi
+
# Fully qualified path name of JVM executable
-JAVA=@JAVA@
+if [ "$JAVA_HOME" -a -x $JAVA_HOME/bin/java ] ; then
+ JAVA=$JAVA_HOME/bin/java
+else
+ JAVA=@JAVA@
+fi
+
# The arguments to the JAVA command
-JAVA_FLAGS="@JAVA_FLAGS@"
+DEFAULT_JACL_FLAGS="@JAVA_FLAGS@"
+JACL_FLAGS="${JACL_FLAGS:-$DEFAULT_JACL_FLAGS}"
# Run java with the args passed in from the calling environment
# We must set the CLASSPATH env var instead of using the -classpath
# argument because jacl might want to exec a program that also
# depends on the CLASSPATH setting and Java can not export env vars
-CLASSPATH=${JACL_CLASSPATH}:${CLASSPATH}
+CLASSPATH=${JACL_CLASSPATH}${CLASSPATH:+:${CLASSPATH}}
export CLASSPATH
-exec ${JAVA} ${JAVA_FLAGS} tcl.lang.Shell ${1+"$@"}
+# Allow other user specified properties to be passed via JACL_PROPS env variable
+
+exec ${JAVA} ${JACL_FLAGS} ${JACL_LIBPATH} ${JACL_PROPS} ${JACL_SHELL} ${1+"$@"}
--- ../tcljava.cvs/src/tcljava/tcl/lang/TCL.java 2002-07-23 09:07:17.000000000 -0600
+++ src/tcljava/tcl/lang/TCL.java 2003-03-12 11:47:01.000000000 -0700
@@ -59,7 +59,7 @@
// the completion code TCL.OK. If the desired completion code is TCL.OK, no
// exception should be thrown.
-static final int OK = 0;
+public static final int OK = 0;
// The following value is used by the Interp::commandComplete(). It's used
// to report that a script is not complete.
--- ../tcljava.cvs/src/jacl/tcl/lang/Interp.java 2003-03-10 16:35:39.000000000 -0700
+++ src/jacl/tcl/lang/Interp.java 2003-03-12 11:46:31.000000000 -0700
@@ -3749,7 +3749,7 @@
*----------------------------------------------------------------------
*/
-void
+public void
allowExceptions()
{
evalFlags |= Parser.TCL_ALLOW_EXCEPTIONS;
--- ../tcljava.cvs/src/jacl/tcl/lang/library/init.tcl 2002-07-23 09:07:17.000000000 -0600
+++ src/jacl/tcl/lang/library/init.tcl 2003-03-12 12:04:08.000000000 -0700
@@ -34,6 +34,12 @@
# }
#}
+# include jacl/tcljava library path if passed as a system property
+
+if {[info exists env(jacl.tcllibpath)]} {
+ lappend auto_path $env(jacl.tcllibpath)
+}
+
if {[lsearch -exact $auto_path [info library]] < 0} {
lappend auto_path [info library]
}
--
Tom Poindexter
tpo...@ny...
http://www.nyx.net/~tpoindex/
|