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/ |