Your patch looks like a good start. To really fix things we need to have a
complete implementation of the fconfigure command. I am planning on
looking into this once I get more free time.
Mo DeJong
dejong@...
gimme multimedia group
On Mon, 4 Jan 1999, Christian Krone wrote:
> Hello,
>
> first I wrote:
> > - When reading from a file, the handling of a backslash at the end of a
> > line is wrong. (Only on Windows and only from a file!)
> > An example session follows:
> > % exec type test.jacl
> > puts \
> > -nonewline Hello
> > % source test.jacl
> > can not find channel named " -nonewline"
> > % puts \
> > -nonewline Hello
> > Hello% exit
>
> Then Moses DeJong answered:
> > Yes, this is a known problem. Only Unix style input is currently
> > accepted (\n at end of line). This problem also makes the Mac port
> > of jacl very hard to use. This is something that needs to be fixed
> > but I have not had time start on it yet. I did some funky junk
> > with the exec command to get it working under windows and I think it
> > does the \r\n conversion correctly but I would not bet my life on that.
>
> I don't know, if I hit all places, but with the attached patch applied to
> .../jacl1.1a1/src/jacl/tcl/lang/Interp.java all my tcl files run smoothly.
>
> I hope this helps, Krischan
> --
> Christian Krone, SQL Datenbanksysteme GmbH
> Mail mailto:krischan@...
>
> P.S. If you receive this mail three times (due to my full disk), sorry for
that.
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
By the way, I ran the second script below (Swing frame with tcl callback
that brings up a modal dialog) with Jacl 1.1a on the same platform and got
the same result - when invoking the callback, the modal dialog froze after
coming up.
However, what I neglected to state explicitly in the original report was
that changing the modal dialog to a non-modal dialog or another frame seems
to work, both in TclBlend and Jacl. Is this related to reported problems
about threading with TclBlend? Actually, I expect bringing up non-modal
dialogs or new frames would increase the number of threads, if anything.
Also, some of my coworkers told me that a combination of Swing and Tk is
not expected to work, but there appear to be at least a few exceptions to
that - are there any known reasons why Swing should not work with Tcl/Tk?
At 01:03 AM 12/29/98 -0800, Philip Chu wrote:
>I'm having problems using modal Swing dialogs with TclBlend 1.1a, JDK 1.2
>on NT.
>
>The first script below creates a tk button that pops up a Swing confirm
>dialog. The confirm dialog comes up OK, but if you drag it over the tk
>button, the latter does not repaint.
>
>A more serious problem is shown in the second script below, which creates a
>Swing frame and button, which has a tcl callback script that brings up a
>Swing confirm dialog. In this case, the whole app freezes when the confirm
>dialog pops up.
>
># test swing modal dialogs
>package require java
>set frame [java::new javax.swing.JFrame]
>button .b -text "Test" -command "java::call javax.swing.JOptionPane
>showConfirmDialog $frame Message"
>pack .b
>
># show JDialog from JFrame
>package require java
>set frame [java::new javax.swing.JFrame]
>set pane [$frame getContentPane]
>set button [java::new javax.swing.JButton "hello"]
>$pane add $button
>java::bind $button java.awt.event.ActionListener.actionPerformed \
>"java::call javax.swing.JOptionPane showConfirmDialog $frame hello"
>$frame setSize 200 200
>$frame show
>
>
>--
>Phil Chu
>philipchu@...http://www.technicat.com/
>
>----------------------------------------------------------------
>The TclJava mailing list is sponsored by WebNet Technologies.
>To subscribe: send mail to TclJava-request@...
> with the word SUBSCRIBE as the subject.
>To unsubscribe: send mail to TclJava-request@...
> with the word UNSUBSCRIBE as the subject.
>To send to the list, send email to 'TclJava@...'.
>A list archive is at: http://www.findmail.com/listsaver/tcldallas/
>
--
Phil Chu
philipchu@...http://www.technicat.com/
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Hello,
first I wrote:
> - When reading from a file, the handling of a backslash at the end of a
> line is wrong. (Only on Windows and only from a file!)
> An example session follows:
> % exec type test.jacl
> puts \
> -nonewline Hello
> % source test.jacl
> can not find channel named " -nonewline"
> % puts \
> -nonewline Hello
> Hello% exit
Then Moses DeJong answered:
> Yes, this is a known problem. Only Unix style input is currently
> accepted (\n at end of line). This problem also makes the Mac port
> of jacl very hard to use. This is something that needs to be fixed
> but I have not had time start on it yet. I did some funky junk
> with the exec command to get it working under windows and I think it
> does the \r\n conversion correctly but I would not bet my life on that.
I don't know, if I hit all places, but with the attached patch applied to
.../jacl1.1a1/src/jacl/tcl/lang/Interp.java all my tcl files run smoothly.
I hope this helps, Krischan
--
Christian Krone, SQL Datenbanksysteme GmbH
Mail mailto:krischan@...
P.S. If you receive this mail three times (due to my full disk), sorry for that.
*** Interp.java.org Mon Dec 28 13:33:25 1998
--- Interp.java Sat Jan 2 13:33:16 1999
***************
*** 1965,1971 ****
try {
byte charArray[] = new byte[fs.available()];
fs.read(charArray);
! return new String(charArray);
} catch (IOException e) {
return null;
} finally {
--- 1964,1998 ----
try {
byte charArray[] = new byte[fs.available()];
fs.read(charArray);
!
! String sep = System.getProperty("line.separator");
! if (sep.equals("\n")) {
! return new String(charArray);
! }
!
! /*
! * If we come to this place, a translation from "\r\n" (on Windows)
! * or "\r" (on Mac?) into "\n" is needed.
! */
!
! int sepLength = sep.length();
! String str = new String(charArray);
! char tmpArray[] = new char[charArray.length];
! int srcPos = 0;
! int dstPos = 0;
! int srcEnd;
! while ((srcEnd = str.indexOf(sep, srcPos)) >= 0) {
! str.getChars(srcPos, srcEnd, tmpArray, dstPos);
! dstPos += srcEnd-srcPos;
! tmpArray[dstPos++] = '\n';
! srcPos = srcEnd+sepLength;
! }
! srcEnd = str.length();
! str.getChars(srcPos, srcEnd, tmpArray, dstPos);
! dstPos += srcEnd-srcPos;
!
! return new String(tmpArray, 0, dstPos);
!
} catch (IOException e) {
return null;
} finally {
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Hi steve.
Three other people have reported bugs like yours so I think this now
counts as a "known problem". If you have the time you might want to
post a small example that shows the freeze you are running into. You
do not have to, but it will make it much easier to find out if changes
to TclBlend fix the problem you are running into. One other thing that
could help is if you could try your program in Jacl and see if it breaks
there too. If you can create an example that freezes in Jacl it is much
easier to track down the problem because multiple threads in Java are
a lot easier to debug then a combo of Tcl + JNI + Java.
later
mo
> I am creating a Java object that draws a graphical chart. This Java object
> uses a thread
> to update the data on the chart. The chart comes up fine, but as soon as a
> thread is created the
> application freezes. Is there a problem with using Java threads?
>
> I can run the Java application stand alone just fine, but not from tcl
> blend.
>
> Thanks,
>
> Steve
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
On Wed, 30 Dec 1998, Christian Krone wrote:
> Hello,
>
> > > over christmas I started to implement java::import
> > I thought about implementing this command but I decided not to
> > because I was not really sure how much help it would be.
>
> Let me cite the Tutorial given at the Tcl/Tk conference, 9/16/98
> "Tcl and Java Programming: Practice and Pitfalls"
> <cite
href="http://ptolemy.eecs.berkeley.edu/~johnr/tutorials/tcljava98/notes/swing.ht\
ml">
> The first few line sets a variable to the package path, to save some typing:
> set swing com.sun.java.swing
> (Wouldn't it be nice if Tcl Blend could "import" Java packages?)
> </cite>
> This paper was my first contact with TclJava, and I always thought, that
> everybody would like to have java::import.
>
> > > - Is there a chance, that this implementation will become
> > > part of Jacl and TclBlend?
> > There is always a chance. I guess it depened on how much help
> > this command will be and how much of the system it changes.
> > I really have no problems with changing tons of code but
> > christopher just hates "lots of changes".
>
> There are two small new classes (JavaImport and JavaImportCmd)
> and a really small patch to JavaInvoke (one else part will be modified).
>
> Since every command uses JavaInvoke to convert a classname from String
> into the corresponding class, I found no java::* command which doesn't
> react to java::import.
>
> > There is also an issue of "caching" names and how you will tell is
> > two packages has a class with the exact same name.
>
> JavaImport has a hitCache, so that every class is searched only once.
> The search doesn't stop after a class is found, but walks through all
> imported packages, so that another class with the same name leads to an
> error.
Right, this was impression of the main problem with the java::import
command. Perhaps a "java::import -remove com.myorg.*" would be in opder?
> *But*
> I think, one problem remains (which simply doesn't exist in Java):
> The import directive in Java is effective only during compilation and ends
> at the end of the compilation unit. In TclJava it works during execution,
> and so the "lifetime" is different: The sourcing of any tcl script may
> change the imported packages.
>
> I wonder if it is a good idea to integerate the
> java::import statements into the current namespace.
> If all library scripts only use java::import in their own namespace,
> the global one doesn't get filled with unwanted packages...
> Example: (Assume there exists a com.myorg.Date class...)
>
> File main.tcl:
> java::import com.myorg.*
> # The following will print methods of com.myorg.Date
> puts [java::methods Date]
> source datelib.tcl
> # The following will print methods of com.myorg.Date,
> # if java::import works just for the current namespace,
> # else it will work or fail dependend of the content of datelib.tcl
> puts [java::methods Date]
>
> File datelib.tcl:
> namespace eval datelib {java::import java.util.*}
> proc datelib::test {} {java::new Date} ;# Will find java.util.Date
You hit the nail on the head. The whole namespace thing is a problem in
jacl. I am still not sure if jacl really needs namespaces (people seemed
to be able to code in Tcl 7.X just fine without them). At any rate,
implementing namespaces in jacl might be a little much for this release.
> There is at least one problem with this approach:
> Jacl ignores the namespace command!
> So the java::import command of datelib.tcl will never be executed!
>
>
> *And now to something completely different*
That whole troff to HTML thing is a mess. When Tcl was at Sun they used
a nroff parsing script to generate the HTML for the docs. Once Tcl moved
over to scriptics they no longer had access to these tools. I think the
best approach is to just create the man pages in HTML and forget about
the unix man pages. Windows and Mac people can not read unix man pages
(without a lot of work). Everyone should be able to read HTML.
> Two more questions regarding TclJava documentation:
> - Is the html file in jacl1.1a1/doc/html/TclJava/java.htm the master
> or is it generated out of a xml/cgi/tcl/troff/whatever file, that isn't
> part of jacl1.1a1Src.tar.gz?
As long as we could also produce "regular" HTML for the webpages. Are you
interested in doing this? I would be willing to help out as much as I
could but to be honest I am a little more concerned with fixing some of
the bugs in Tcl Blend and Jacl right now.
> - Wouldn't it be a nice idea to convert the html into XML like Dr. Hipp
> did it for Tcl/Tk (See http://www.hwaci.com/sw/tcldoc)?
>
> Greetings, Krischan
> --
> Christian Krone, SQL Datenbanksysteme GmbH
later
mo
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
I am creating a Java object that draws a graphical chart. This Java object
uses a thread
to update the data on the chart. The chart comes up fine, but as soon as a
thread is created the
application freezes. Is there a problem with using Java threads?
I can run the Java application stand alone just fine, but not from tcl
blend.
Thanks,
Steve
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Hello,
> > over christmas I started to implement java::import
> I thought about implementing this command but I decided not to
> because I was not really sure how much help it would be.
Let me cite the Tutorial given at the Tcl/Tk conference, 9/16/98
"Tcl and Java Programming: Practice and Pitfalls"
<cite
href="http://ptolemy.eecs.berkeley.edu/~johnr/tutorials/tcljava98/notes/swing.ht\
ml">
The first few line sets a variable to the package path, to save some typing:
set swing com.sun.java.swing
(Wouldn't it be nice if Tcl Blend could "import" Java packages?)
</cite>
This paper was my first contact with TclJava, and I always thought, that
everybody would like to have java::import.
> > - Is there a chance, that this implementation will become
> > part of Jacl and TclBlend?
> There is always a chance. I guess it depened on how much help
> this command will be and how much of the system it changes.
> I really have no problems with changing tons of code but
> christopher just hates "lots of changes".
There are two small new classes (JavaImport and JavaImportCmd)
and a really small patch to JavaInvoke (one else part will be modified).
Since every command uses JavaInvoke to convert a classname from String
into the corresponding class, I found no java::* command which doesn't
react to java::import.
> There is also an issue of "caching" names and how you will tell is
> two packages has a class with the exact same name.
JavaImport has a hitCache, so that every class is searched only once.
The search doesn't stop after a class is found, but walks through all
imported packages, so that another class with the same name leads to an
error.
*But*
I think, one problem remains (which simply doesn't exist in Java):
The import directive in Java is effective only during compilation and ends
at the end of the compilation unit. In TclJava it works during execution,
and so the "lifetime" is different: The sourcing of any tcl script may
change the imported packages.
I wonder if it is a good idea to integerate the
java::import statements into the current namespace.
If all library scripts only use java::import in their own namespace,
the global one doesn't get filled with unwanted packages...
Example: (Assume there exists a com.myorg.Date class...)
File main.tcl:
java::import com.myorg.*
# The following will print methods of com.myorg.Date
puts [java::methods Date]
source datelib.tcl
# The following will print methods of com.myorg.Date,
# if java::import works just for the current namespace,
# else it will work or fail dependend of the content of datelib.tcl
puts [java::methods Date]
File datelib.tcl:
namespace eval datelib {java::import java.util.*}
proc datelib::test {} {java::new Date} ;# Will find java.util.Date
There is at least one problem with this approach:
Jacl ignores the namespace command!
So the java::import command of datelib.tcl will never be executed!
*And now to something completely different*
Two more questions regarding TclJava documentation:
- Is the html file in jacl1.1a1/doc/html/TclJava/java.htm the master
or is it generated out of a xml/cgi/tcl/troff/whatever file, that isn't
part of jacl1.1a1Src.tar.gz?
- Wouldn't it be a nice idea to convert the html into XML like Dr. Hipp
did it for Tcl/Tk (See http://www.hwaci.com/sw/tcldoc)?
Greetings, Krischan
--
Christian Krone, SQL Datenbanksysteme GmbH
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
On Tue, 29 Dec 1998, Philip Chu wrote:
> At 02:11 PM 12/28/98 -0600, Moses DeJong wrote:
> >You might be the first person to run tcl blend on windows 98. When you
> >get the "could not find class tcl/lang/Interp" message that means there is
> >something wrong with the CLASSPATH such that the JVM can not find the
> >tclblend.jar file. Try this.
> >
> >%javap tcl.lang.Interp
> >
> >If your CLASSPATH is set correctly you should see the public interface
> >of tcl.lang.Interp printed to your screen. If you get a message like
> >"can't find tcl.lang.Interp" then you need to make sure your CLASSPATH
> >includes the tclblend.jar file.
> >
> >Try that and tell us if it worked.
The "Classpath gets longer" thing is a minor bug that I have already fixed
in my tree. It will not break anything. Did you compile tcl from the
tcl8.0.4 and tclblend1.1a1 source releases or did you use the binary
releases? If you used the binary releases then you might want to try
and compile both tcl and tclblend from the source. Of course this means
you will have to own Visual C++. I remember there was some problem
with using tcl blend on a system that did not have a scriptics registry
key. I do not have access to a windows 98 box so I can not really test
your problem for myself. One other thing you might want to try is to
do the package require java and then run both of these commands from
the tcl shell.
exec javap -classpath $env(CLASSPATH) tcl.lanng.Interp
exec javap -classpath $env(CLASSPATH) tcl.lang.JavaNewCmd
This will make sure that both tclblend.jar and tcljava.jar are getting
found on the CLASSPATH. Email your results back to the list and we will
see what we can do.
> I performed "package require java", got the error, then "javap
> tcl.lang.Interp", and that worked. A subsequent "package require java"
> still didn't work (although each time I invoke it, the CLASSPATH gets longer!)
You will not need to set the CLASSPATH in autoexec.bat.
> Note that I've tried this with and without setting CLASSPATH myself
> explicitly in autoexec.bat.
>
> --
> Phil Chu
> philipchu@...http://www.technicat.com/
>
later
mo
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Hello,
> > - During an interactive session of jaclsh the input isn't echoed,
> > until a newline is entered. I already saw a report of this bug
> > in clt. It is indeed very strange to type something without echo...
>
> I think this is actually a java bug and not a jacl bug. The report
> I read on this was on a windows system that was not configured for
> us/english output (I think it was french or something). When I run
> jacl on my NT machine it works as expected. If it does not work on
> your machine then try this simple program and see what it prints.
>
> public class echo {
> public static void main(String[] argv) throws Exception {
> System.out.println("Please begin typing");
> while (true) {
> int avail = System.in.available();
> if (avail == 0) {
> Thread.currentThread().sleep(100);
> } else {
> byte[] buff = new byte[avail];
> System.in.read(buff);
>
> //echo back what was just typed
> System.out.println("-----ECHO BEGIN-----");
> System.out.write(buff);
> System.out.println("-----ECHO END-----");
> }
> }
> }
> }
I compiled it for JDK1.1.6 on different Windows and Linux systems and
with JDK1.2beta4 on a german Windows and there the echo program has the
expected output (comment is added by me):
Please begin typing
Hallo /* <== Characters appeared while I'm typing... */
-----ECHO BEGIN-----
Hallo
-----ECHO END-----
But when I used JDK1.2fcs (a rather new version) on a german and on an
english Windows system, echo worked like this:
Please begin typing
Hallo /* <== Characters appeared after hitting Return... */
-----ECHO BEGIN-----
-----ECHO END-----
-----ECHO BEGIN-----
-----ECHO END-----
So it is indeed a problem with Java1.2 on Windows and not with Jacl.
But it doesn't seem to depend on the language of NT.
For me the workaround is to use TclBlend on Windows (it's also faster...)
Thanks, Krischan
--
Christian Krone, SQL Datenbanksysteme GmbH
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
I'm having problems using modal Swing dialogs with TclBlend 1.1a, JDK 1.2
on NT.
The first script below creates a tk button that pops up a Swing confirm
dialog. The confirm dialog comes up OK, but if you drag it over the tk
button, the latter does not repaint.
A more serious problem is shown in the second script below, which creates a
Swing frame and button, which has a tcl callback script that brings up a
Swing confirm dialog. In this case, the whole app freezes when the confirm
dialog pops up.
# test swing modal dialogs
package require java
set frame [java::new javax.swing.JFrame]
button .b -text "Test" -command "java::call javax.swing.JOptionPane
showConfirmDialog $frame Message"
pack .b
# show JDialog from JFrame
package require java
set frame [java::new javax.swing.JFrame]
set pane [$frame getContentPane]
set button [java::new javax.swing.JButton "hello"]
$pane add $button
java::bind $button java.awt.event.ActionListener.actionPerformed \
"java::call javax.swing.JOptionPane showConfirmDialog $frame hello"
$frame setSize 200 200
$frame show
--
Phil Chu
philipchu@...http://www.technicat.com/
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
At 02:11 PM 12/28/98 -0600, Moses DeJong wrote:
>You might be the first person to run tcl blend on windows 98. When you
>get the "could not find class tcl/lang/Interp" message that means there is
>something wrong with the CLASSPATH such that the JVM can not find the
>tclblend.jar file. Try this.
>
>%javap tcl.lang.Interp
>
>If your CLASSPATH is set correctly you should see the public interface
>of tcl.lang.Interp printed to your screen. If you get a message like
>"can't find tcl.lang.Interp" then you need to make sure your CLASSPATH
>includes the tclblend.jar file.
>
>Try that and tell us if it worked.
I performed "package require java", got the error, then "javap
tcl.lang.Interp", and that worked. A subsequent "package require java"
still didn't work (although each time I invoke it, the CLASSPATH gets longer!)
Note that I've tried this with and without setting CLASSPATH myself
explicitly in autoexec.bat.
--
Phil Chu
philipchu@...http://www.technicat.com/
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Hello.
I am looking for feedback on the new java::try command that
I am working on. The java::try command is needed because there
is no way to manage multiple exception types in Jacl or Tcl Blend.
Here is the command usage.
java::try script ?catch exception_pair script? ?finally script?
Lets assume we have a Tcl proc called "bad" that raises an
exceptional condition. We could place a catch around an
invocation of bad to protect the script from errors.
if {[catch {bad} err]} {
puts "error in procedure bad: $err"
}
If we wanted to do the same thing using the java::try command
we could use the following code.
java::try {
bad
} catch {TclException err} {
puts "error in procedure bad: $err"
}
Now lets assume we wanted to handle multiple error conditions.
Suppose we wanted to call a Tcl command that was implemented with
a combination of Tcl and Java commands. For this example we assume
this "jcombo" command already exists in the interpreter. We could
then use the java::try command to manage exceptional conditions
that could be raised while processing the "jcombo" command.
java::try {
jcombo
} catch {TclException e} {
puts "a Tcl error occured"
} catch {IOException e} {
puts "a Java IOException occured"
} catch {NumberFormatException e} {
puts "a Java NumberFormatException occured"
}
You could also use a finally clause.
java::try {
set i 1
} finally {
set j 2
}
A couple of things to note.
1) the return value of the command would be the results of the last
command in the body script or the last command in a catch script but
the results would not be changed by a finally script.
The TclException type would be a "special" type that would be used
to catch all exceptional conditions generated by Tcl. The value of
the variable for a TclException catch block like catch {TclException err}
would be the error condition (just like catch {...} err). If the
catch block is set for a Java Exception like catch {NumberFormatException e}
then the error variable e would be set to java0x? which would be the
reflected Java exception object. This means that you could query the
exception object about its error message of do something and rethrow
the error.
java::try {
#some java code
} catch {Exception e} {
puts "caught Java error [$e getMessage]"
java::throw $e
} catch {TclException e} {
puts "caught Tcl error $e"
}
Also note that unlike the java try-catch-finally command the special
keyword TclException would not be a subclass of java.lang.Exception
so Tcl exceptions and Java exceptions can be handled differently.
Well, does that raise any red flags with anyone? I think this approach
will give us all the power of the Java's try-catch-finally construct
without losing the Tcl's dynamic scripting ability. Any comments?
thanks a bunch
mo dejong
dejong at cs.umn.edu
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
I have been thinking about the binary releases of jacl and tcl blend
for a bit now and I am really starting to think that we should get
rid of them. I am NOT talking about the binary release for Windows
or Mac, just the solaris-binary of Tcl Blend and the binary release
of jacl for unix systems. Here are a couple of reasons I think the
binary release should go.
1) they REALLY make life hard for the developers of jacl and tcl blend
because a ton of nasty makefile rules need to be kept up to date.
2) the binary only releases do not use ./configure and have no way to
check for problems with the installed JDK tools.
3) the source releases will install wrapper scripts on unix systems
so that people can type jaclsh or jtclsh instead of something
nasty like "java tcl.lang.Shell ...".
4) the source releases come with the regression test that people can
run by typing "make test". If there is something wrong with the
JVM or Tcl then these tests should show the problem.
5) the only unix binary for tcl blend we support is for solaris with
JDK1.1. If people wanted to use the JDK1.2 they would be out of
luck because the 1.1 binary will not work with 1.2.
I really can not think of any reasons why we should keep the binary
releases. Is there anyone out there that uses the binary releases or
thinks that they should stay? If you think the binary releases should
stay please post your arguments so we know what jacl and tcl blend
users think about this issue.
later
mo dejong
dejong at cs.umn.edu
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
ORO inc went under but the code seems to be back up on this site.
http://www.savarese.org
I don't think this really changes anything for jacl but I have no idea
what the binary license said so I could be wrong. We really should replace
the regexp stuff with a library like the gnu regexp package but I do not
know if there will be time before 1.1 goes final.
gnu regexp stuff should be at.
www.gnu.org/software/java/java.html
later
mo
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
On Mon, 28 Dec 1998, Christian Krone wrote:
> Hello,
>
> over christmas I started to implement java::import.
> Right now it looks fine, but there is still a test file
> and a man page to write...
There is always a chance. I guess it depened on how much help
this command will be and how much of the system it changes.
I really have no problems with changing tons of code but
christopher just hates "lots of changes".
> So before I continue to work on this, I have some questions:
> - Is there a chance, that this implementation will become
> part of Jacl and TclBlend?
I thought about implementing this command but I decided not to
because I was not really sure how much help it would be. Do you
intend to only change the java::new command so that short names
outside of the java.lang package can be provided?
> - Is there any other person currently working on the same topic?
Well, the "problem" is the need to be really clear about where
the short names will be accepted instead of the long names. It can
get really ugly if one is not careful and there are a bunch of
commands that could require changes. There is also an issue of
"caching" names and how you will tell is two packages has a class with
the exact same name.
> - Is there some known problem with java::import, which I don't see,
> but which is the reason for the fact, that it isn't implemented yet?
Not really. The way it has worked so far is that each person works
on a private tree. Then where we are ready for a "release" the trees
are merged to produce an "official" tree. Of course this merging takes
a long time and christopher and I get into long silly arguments over
little things like error output of commands. Then after a bunch or
these email arguments and name calling we settle on something and
"ship" it over to the folks at scriptics.
> - Is there a "standard" way to incorporate changes into TclJava, or
> should I send the sources to this mailing list?
>
> Thanks in advance for your answers,
> Krischan
> --
> Christian Krone, SQL Datenbanksysteme GmbH
later
mo
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
On Mon, 28 Dec 1998, Christian Krone wrote:
> Hello,
Yup, you came to the right place.
> I hope, this mailing list is the correct place for something like this:
Cool, I just tested your code under JDK1.1 and JDK1.2 and it works great!
I have already added it to my beta tree. Of course, I can not promise that
everything in my tree will get into the "official" beta release.
> In the attachment there is an implementation of the clock command
> based on the sources of Jacl1.1a1:
> There are:
> - ClockCmd.java (a new file belonging into .../jacl1.1a1/src/jacl/tcl/lang)
> - Interp.java.patch (a patch for
.../jacl1.1a1/src/jacl/tcl/lang/Interp.java)
> - all.patch (a patch for .../jacl1.1a1/tests/all)
I used the 8.0.4 clock.test. The 8.1b1 clock.test has some issues but
we will not worry about that as Tcl Blend does not work with tcl8.1b1 yet.
You might want to glance at the settimezone test if you have time.
> The modified jacl shell will NOT pass the clock.test, as it is found
> in .../jacl1.1a1/tests/tcl, since this doesn't seem to be up to date.
> It will pass the .../tcl8.0/tests/clock.test, which is attached also.
>
> I hope, this files will find their way into jacl1.1a2, jacl1.1b1 or
whatever...
>
> Have fun, Krischan
> --
> Christian Krone, SQL Datenbanksysteme GmbH
later
mo
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
On Mon, 28 Dec 1998, Christian Krone wrote:
> Hello,
>
> there are two bugs in the input handling of the jacl Shell,
> which only occur on Windows:
I think this is actually a java bug and not a jacl bug. The report
I read on this was on a windows system that was not configured for
us/english output (I think it was french or something). When I run
jacl on my NT machine it works as expected. If it does not work on
your machine then try this simple program and see what it prints.
public class echo {
public static void main(String[] argv) throws Exception {
System.out.println("Please begin typing");
while (true) {
int avail = System.in.available();
if (avail == 0) {
Thread.currentThread().sleep(100);
} else {
byte[] buff = new byte[avail];
System.in.read(buff);
//echo back what was just typed
System.out.println("-----ECHO BEGIN-----");
System.out.write(buff);
System.out.println("-----ECHO END-----");
}
}
}
}
> - During an interactive session of jaclsh the input isn't echoed,
> until a newline is entered. I already saw a report of this bug
> in clt. It is indeed very strange to type something without echo...
Yes, this is a known problem. Only Unix style input is currently
accepted (\n at end of line). This problem also makes the Mac port
of jacl very hard to use. This is something that needs to be fixed
but I have not had time start on it yet. I did some funky junk
with the exec command to get it working under windows and I think it
does the \r\n conversion correctly but I would not bet my life on that.
> - When reading from a file, the handling of a backslash at the end of a
> line is wrong. (Only on Windows and only from a file!)
> An example session follows:
> % exec type test.jacl
> puts \
> -nonewline Hello
> % source test.jacl
> can not find channel named " -nonewline"
> % puts \
> -nonewline Hello
> Hello% exit
>
> I hope, this helps to improve jacl,
> Krischan
> --
> Christian Krone, SQL Datenbanksysteme GmbH
>
> ----------------------------------------------------------------
> The TclJava mailing list is sponsored by WebNet Technologies.
> To subscribe: send mail to TclJava-request@...
> with the word SUBSCRIBE as the subject.
> To unsubscribe: send mail to TclJava-request@...
> with the word UNSUBSCRIBE as the subject.
> To send to the list, send email to 'TclJava@...'.
> A list archive is at: http://www.findmail.com/listsaver/tcldallas/
>
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
You might be the first person to run tcl blend on windows 98. When you
get the "could not find class tcl/lang/Interp" message that means there is
something wrong with the CLASSPATH such that the JVM can not find the
tclblend.jar file. Try this.
%javap tcl.lang.Interp
If your CLASSPATH is set correctly you should see the public interface
of tcl.lang.Interp printed to your screen. If you get a message like
"can't find tcl.lang.Interp" then you need to make sure your CLASSPATH
includes the tclblend.jar file.
Try that and tell us if it worked.
Mo DeJong
dejong@...
gimme multimedia group
On Mon, 28 Dec 1998, Philip Chu wrote:
> On my Windows 98 laptop (with JRE 1.2) I get the following message after
> "package require java". The CLASSPATH looks correct to me, but it seems the
> jvm is ignoring CLASSPATH. Is this a Windows 98 problem?
>
> Loading 'C:/Program Files/Tcl/lib/tcl8.0/../tclblend1.1/tclblend.dll' failed:
> could not find class tcl/lang/Interp.
> Check that your path includes the directory where tclblend.dll resides.
> Try looking in the directories under the value of tcl_library,
> currently: C:/PROGRA~1/TCL/lib/tcl8.0
> Currently, the CLASSPATH environment variable is set to:
> C:\Program Files\Tcl\lib\tcl8.0\..\tclblend1.1\tcljava.jar;C:\Program
> Files\Tcl\lib\tcl8.0\..\tclblend1.1\tclblend.jar;
> The JVM currently is using the following classpath:C:\PROGRAM
> FILES\JAVASOFT\JRE\1.2\lib\rt.jar;C:\PROGRAM
> FILES\JAVASOFT\JRE\1.2\lib\i18n.jar;C:\PROGRAM FILES\JAVASOFT\JRE\1.2\classes
>
> --
> Phil Chu
> philipchu@...http://www.technicat.com/
>
> ----------------------------------------------------------------
> The TclJava mailing list is sponsored by WebNet Technologies.
> To subscribe: send mail to TclJava-request@...
> with the word SUBSCRIBE as the subject.
> To unsubscribe: send mail to TclJava-request@...
> with the word UNSUBSCRIBE as the subject.
> To send to the list, send email to 'TclJava@...'.
> A list archive is at: http://www.findmail.com/listsaver/tcldallas/
>
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
On my Windows 98 laptop (with JRE 1.2) I get the following message after
"package require java". The CLASSPATH looks correct to me, but it seems the
jvm is ignoring CLASSPATH. Is this a Windows 98 problem?
Loading 'C:/Program Files/Tcl/lib/tcl8.0/../tclblend1.1/tclblend.dll' failed:
could not find class tcl/lang/Interp.
Check that your path includes the directory where tclblend.dll resides.
Try looking in the directories under the value of tcl_library,
currently: C:/PROGRA~1/TCL/lib/tcl8.0
Currently, the CLASSPATH environment variable is set to:
C:\Program Files\Tcl\lib\tcl8.0\..\tclblend1.1\tcljava.jar;C:\Program
Files\Tcl\lib\tcl8.0\..\tclblend1.1\tclblend.jar;
The JVM currently is using the following classpath:C:\PROGRAM
FILES\JAVASOFT\JRE\1.2\lib\rt.jar;C:\PROGRAM
FILES\JAVASOFT\JRE\1.2\lib\i18n.jar;C:\PROGRAM FILES\JAVASOFT\JRE\1.2\classes
--
Phil Chu
philipchu@...http://www.technicat.com/
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Hello,
over christmas I started to implement java::import.
Right now it looks fine, but there is still a test file
and a man page to write...
So before I continue to work on this, I have some questions:
- Is there a chance, that this implementation will become
part of Jacl and TclBlend?
- Is there any other person currently working on the same topic?
- Is there some known problem with java::import, which I don't see,
but which is the reason for the fact, that it isn't implemented yet?
- Is there a "standard" way to incorporate changes into TclJava, or
should I send the sources to this mailing list?
Thanks in advance for your answers,
Krischan
--
Christian Krone, SQL Datenbanksysteme GmbH
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Hello,
there are two bugs in the input handling of the jacl Shell,
which only occur on Windows:
- During an interactive session of jaclsh the input isn't echoed,
until a newline is entered. I already saw a report of this bug
in clt. It is indeed very strange to type something without echo...
- When reading from a file, the handling of a backslash at the end of a
line is wrong. (Only on Windows and only from a file!)
An example session follows:
% exec type test.jacl
puts \
-nonewline Hello
% source test.jacl
can not find channel named " -nonewline"
% puts \
-nonewline Hello
Hello% exit
I hope, this helps to improve jacl,
Krischan
--
Christian Krone, SQL Datenbanksysteme GmbH
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Hello,
I hope, this mailing list is the correct place for something like this:
In the attachment there is an implementation of the clock command
based on the sources of Jacl1.1a1:
There are:
- ClockCmd.java (a new file belonging into .../jacl1.1a1/src/jacl/tcl/lang)
- Interp.java.patch (a patch for .../jacl1.1a1/src/jacl/tcl/lang/Interp.java)
- all.patch (a patch for .../jacl1.1a1/tests/all)
The modified jacl shell will NOT pass the clock.test, as it is found
in .../jacl1.1a1/tests/tcl, since this doesn't seem to be up to date.
It will pass the .../tcl8.0/tests/clock.test, which is attached also.
I hope, this files will find their way into jacl1.1a2, jacl1.1b1 or whatever...
Have fun, Krischan
--
Christian Krone, SQL Datenbanksysteme GmbH
/*
* ClockCmd.java --
*
* Implements the built-in "clock" Tcl command.
*
* Copyright (c) 1998 Christian Krone.
* Copyright (c) 1997 Cornell University.
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL
* WARRANTIES.
*
* RCS: @(#) $Id$
*
*/
package tcl.lang;
import java.util.*;
import java.text.*;
/**
* This class implements the built-in "clock" command in Tcl.
*/
class ClockCmd implements Command {
static final private String validCmds[] = {
"clicks",
"format",
"scan",
"seconds"
};
static final private int CMD_CLICKS = 0;
static final private int CMD_FORMAT = 1;
static final private int CMD_SCAN = 2;
static final private int CMD_SECONDS = 3;
static final private String formatOpts[] = {
"-format",
"-gmt"
};
static final private int OPT_FORMAT_FORMAT = 0;
static final private int OPT_FORMAT_GMT = 1;
static final private String scanOpts[] = {
"-base",
"-gmt"
};
static final private int OPT_SCAN_BASE = 0;
static final private int OPT_SCAN_GMT = 1;
static final int EPOCH_YEAR = 1970;
/**
*----------------------------------------------------------------------
*
* cmdProc --
*
* This procedure is invoked as part of the Command interface to
* process the "clock" Tcl command. See the user documentation
* for details on what it does.
*
* Results:
* None.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
public void
cmdProc(
Interp interp, // Current interpreter.
TclObject argv[]) // Argument list.
throws
TclException // A standard Tcl exception.
{
int clockVal; // Time value as seconds of epoch.
String dateString; // Time value as string.
int argIx; // Counter over arguments.
String format = null; // User specified format string.
boolean useGmt = false; // User specified flag to use gmt.
TclObject baseObj = null; // User specified raw value of baseClock.
Date baseClock; // User specified time value.
Date date; // Parsed date value.
if (argv.length < 2) {
throw new TclNumArgsException(interp, 1, argv, "option ?arg ...?");
}
int cmd = TclIndex.get(interp, argv[1], validCmds, "option", 0);
switch (cmd) {
case CMD_CLICKS: {
if (argv.length != 2) {
throw new TclNumArgsException(interp, 2, argv, null);
}
long millis = new java.util.Date().getTime();
int clicks = (int)(millis%Integer.MAX_VALUE);
interp.setResult(clicks);
break;
}
case CMD_FORMAT: {
if ((argv.length < 3) || (argv.length > 7)) {
throw new TclNumArgsException(interp, 2, argv,
"clockval ?-format string? ?-gmt boolean?");
}
clockVal = TclInteger.get(interp, argv[2]);
for (argIx = 3; argIx+1 < argv.length; argIx += 2) {
int formatOpt = TclIndex.get(interp, argv[argIx],
formatOpts, "switch", 0);
switch (formatOpt) {
case OPT_FORMAT_FORMAT: {
format = argv[argIx+1].toString();
break;
}
case OPT_FORMAT_GMT: {
useGmt = TclBoolean.get(interp, argv[argIx+1]);
break;
}
}
}
if (argIx < argv.length) {
throw new TclNumArgsException(interp, 2, argv,
"clockval ?-format string? ?-gmt boolean?");
}
FormatClock(interp, clockVal, useGmt, format);
break;
}
case CMD_SCAN: {
if ((argv.length < 3) || (argv.length > 7)) {
throw new TclNumArgsException(interp, 2, argv,
"dateString ?-base clockValue? ?-gmt boolean?");
}
dateString = argv[2].toString();
for (argIx = 3; argIx+1 < argv.length; argIx += 2) {
int scanOpt = TclIndex.get(interp, argv[argIx],
scanOpts, "switch", 0);
switch (scanOpt) {
case OPT_SCAN_BASE: {
baseObj = argv[argIx+1];
break;
}
case OPT_SCAN_GMT: {
useGmt = TclBoolean.get(interp, argv[argIx+1]);
break;
}
}
}
if (argIx < argv.length) {
throw new TclNumArgsException(interp, 2, argv,
"clockval ?-format string? ?-gmt boolean?");
}
if (baseObj != null) {
baseClock = new Date(TclInteger.get(interp, baseObj)*1000);
} else {
baseClock = new Date();
}
date = GetDate(dateString, baseClock, useGmt);
if (date == null) {
throw new TclException(interp,
"unable to convert date-time string \"" +
dateString + "\"");
}
int seconds = (int)(date.getTime()/1000);
interp.setResult(seconds);
break;
}
case CMD_SECONDS: {
if (argv.length != 2) {
throw new TclNumArgsException(interp, 2, argv, null);
}
long millis = new java.util.Date().getTime();
int seconds = (int)(millis/1000);
interp.setResult(seconds);
break;
}
}
}
/**
*-----------------------------------------------------------------------------
*
* FormatClock --
*
* Formats a time value based on seconds into a human readable
* string.
*
* Results:
* None.
*
* Side effects:
* The interpreter will contain the formatted string as result.
*
*-----------------------------------------------------------------------------
*/
private void
FormatClock(
Interp interp, // Current interpreter.
int clockVal, // Time in seconds.
boolean useGMT, // Boolean
String format) // Format string
throws
TclException // A standard Tcl exception.
{
Date date = new Date((long)clockVal*1000);
Calendar calendar = Calendar.getInstance();
SimpleDateFormat fmt, locFmt;
FieldPosition fp = new FieldPosition(0);
if (format == null) {
format = new String ("%a %b %d %H:%M:%S %Z %Y");
}
calendar.setTime(date);
if (useGMT) {
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
}
fmt = new SimpleDateFormat("mm.dd.yy", Locale.US);
fmt.setCalendar(calendar);
StringBuffer result = new StringBuffer();
for (int ix = 0; ix < format.length(); ix++) {
if (format.charAt(ix) == '%' && ix+1 < format.length()) {
switch (format.charAt(++ix)) {
case '%': // Insert a %.
result.append('%');
break;
case 'a': // Abbreviated weekday name (Mon, Tue, etc.).
fmt.applyPattern("EEE");
fmt.format(date, result, fp);
break;
case 'A': // Full weekday name (Monday, Tuesday, etc.).
fmt.applyPattern("EEEE");
fmt.format(date, result, fp);
break;
case 'b': case 'h': // Abbreviated month name (Jan,Feb,etc.).
fmt.applyPattern("MMM");
fmt.format(date, result, fp);
break;
case 'B': // Full month name.
fmt.applyPattern("MMMM");
fmt.format(date, result, fp);
break;
case 'c': // Locale specific date and time.
locFmt = (SimpleDateFormat)DateFormat.getDateTimeInstance(
DateFormat.SHORT, DateFormat.SHORT);
locFmt.setCalendar(calendar);
locFmt.format(date, result, fp);
break;
case 'C': // Century (00 - 99).
int century = calendar.get(Calendar.YEAR)/100;
result.append((century < 10 ? "0" : "") + century);
break;
case 'd': // Day of month (01 - 31).
fmt.applyPattern("dd");
fmt.format(date, result, fp);
break;
case 'D': // Date as %m/%d/%y.
fmt.applyPattern("MM/dd/yy");
fmt.format(date, result, fp);
break;
case 'e': // Day of month (1 - 31), no leading zeros.
fmt.applyPattern("d");
String day = fmt.format(date);
result.append((day.length() < 2 ? " " : "") + day);
break;
case 'H': // Hour in 24-hour format (00 - 23).
fmt.applyPattern("HH");
fmt.format(date, result, fp);
break;
case 'I': // Hour in 12-hour format (01 - 12).
fmt.applyPattern("hh");
fmt.format(date, result, fp);
break;
case 'j': // Day of year (001 - 366).
fmt.applyPattern("DDD");
fmt.format(date, result, fp);
break;
case 'k': // Hour in 24-hour format (0 - 23), no leading zeros.
fmt.applyPattern("H");
String h24 = fmt.format(date);
result.append((h24.length() < 2 ? " " : "") + h24);
break;
case 'l': // Hour in 12-hour format (1 - 12), no leading zeros.
fmt.applyPattern("h");
String h12 = fmt.format(date);
result.append((h12.length() < 2 ? " " : "") + h12);
break;
case 'm': // Month number (01 - 12).
fmt.applyPattern("MM");
fmt.format(date, result, fp);
break;
case 'M': // Minute (00 - 59).
fmt.applyPattern("mm");
fmt.format(date, result, fp);
break;
case 'n': // Insert a newline.
result.append('\n');
break;
case 'p': // AM/PM indicator.
fmt.applyPattern("aa");
fmt.format(date, result, fp);
break;
case 'r': // Time as %I:%M:%S %p.
fmt.applyPattern("KK:mm:ss aaaa");
fmt.format(date, result, fp);
break;
case 'R': // Time as %H:%M.
fmt.applyPattern("hh:mm");
fmt.format(date, result, fp);
break;
case 's': // seconds since epoch.
long millis = calendar.getTime().getTime();
if (useGMT) {
Calendar localCalendar = Calendar.getInstance();
localCalendar.setTime(calendar.getTime());
millis -= localCalendar.get(Calendar.ZONE_OFFSET)
+ localCalendar.get(Calendar.DST_OFFSET);
}
result.append((int)(millis/1000));
break;
case 'S': // Seconds (00 - 59).
fmt.applyPattern("ss");
fmt.format(date, result, fp);
break;
case 't': // Insert a tab.
result.append('\t');
break;
case 'T': // Time as %H:%M:%S.
fmt.applyPattern("hh:mm:ss");
fmt.format(date, result, fp);
break;
case 'u': // Weekday number (1 - 7) Sunday = 7.
int dayOfWeek17 = calendar.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek17 == calendar.SUNDAY) {
result.append(7);
} else {
result.append(dayOfWeek17 - Calendar.SUNDAY);
}
break;
case 'U': // Week of year (01-52), Sunday is first day.
int weekS = GetWeek(calendar, Calendar.SUNDAY, false);
result.append((weekS < 10 ? "0" : "") + weekS);
break;
case 'V': // ISO 8601 Week Of Year (01 - 53).
int isoWeek = GetWeek(calendar, Calendar.MONDAY, true);
result.append((isoWeek < 10 ? "0" : "") + isoWeek);
break;
case 'w': // Weekday number (0 - 6) Sunday = 0.
int dayOfWeek06 = calendar.get(Calendar.DAY_OF_WEEK);
result.append(dayOfWeek06-calendar.SUNDAY);
break;
case 'W': // Week of year (01-52), Monday is first day.
int weekM = GetWeek(calendar, Calendar.MONDAY, false);
result.append((weekM < 10 ? "0" : "") + weekM);
break;
case 'x': // Locale specific date format.
locFmt = (SimpleDateFormat)DateFormat.getDateInstance(
DateFormat.SHORT);
locFmt.setCalendar(calendar);
locFmt.format(date, result, fp);
break;
case 'X': // Locale specific time format.
locFmt = (SimpleDateFormat)DateFormat.getTimeInstance(
DateFormat.SHORT);
locFmt.setCalendar(calendar);
locFmt.format(date, result, fp);
break;
case 'y': // Year without century (00 - 99).
fmt.applyPattern("yy");
fmt.format(date, result, fp);
break;
case 'Y': // Year with century (e.g. 1990)
fmt.applyPattern("yyyy");
fmt.format(date, result, fp);
break;
case 'Z': // Time zone name.
fmt.applyPattern("zzz");
fmt.format(date, result, fp);
break;
default:
result.append(format.charAt(ix));
break;
}
} else {
result.append(format.charAt(ix));
}
}
interp.setResult(result.toString());
}
/**
*-----------------------------------------------------------------------------
*
* GetWeek --
*
* Returns the week_of_year of the given date.
* The weekday considered as start of the week is given as argument.
* Specify iso as true to get the week_of_year accourding to ISO.
*
* Results:
* Day of the week .
*
* Side effects:
* The interpreter will contain the formatted string as result.
*
*-----------------------------------------------------------------------------
*/
private int
GetWeek(
Calendar calendar, // Calendar containing Date.
int firstDayOfWeek, // this day starts a week (MONDAY/SUNDAY).
boolean iso // evaluate according to ISO?
)
{
if (iso) {
firstDayOfWeek = Calendar.MONDAY;
}
/*
* After changing the firstDayOfWeek, we have to set the time value anew,
* so that the fields of the calendar are recalculated.
*/
calendar.setFirstDayOfWeek(firstDayOfWeek);
calendar.setMinimalDaysInFirstWeek(iso ? 4 : 7);
calendar.setTime(calendar.getTime());
int week = calendar.get(Calendar.WEEK_OF_YEAR);
if (!iso) {
/*
* The week for the first days of the year may be 52 or 53.
* But here we have to return 0, if we don't compute ISO week.
* So any bigger than 50th week in January will become 00.
*/
if (calendar.get(Calendar.MONTH) == Calendar.JANUARY && week > 50) {
week = 0;
}
}
return week;
}
/**
*-----------------------------------------------------------------------------
*
* GetDate --
*
* Scan a human readable date string and construct a Date.
*
* Results:
* The scanned date (or null, if an error occured).
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private Date
GetDate(
String dateString, // Date string to scan
Date baseDate, // Date to use as base
boolean useGMT) // Boolean
{
Calendar calendar = Calendar.getInstance();
Calendar now = Calendar.getInstance();
now.setTime(baseDate);
calendar.set(now.get(Calendar.YEAR), now.get(Calendar.MONTH),
now.get(Calendar.DAY_OF_MONTH), 0, 0 ,0);
if (useGMT) {
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
}
ClockToken[] dt = GetTokens(dateString, false);
ParsePosition parsePos = new ParsePosition(0);
ClockRelTimespan diff = new ClockRelTimespan();
int hasTime = 0;
int hasZone = 0;
int hasDate = 0;
int hasDay = 0;
int hasRel = 0;
while (parsePos.getIndex() < dt.length) {
if (ParseTime(dt, parsePos, calendar)) {
hasTime++;
} else if (ParseZone(dt, parsePos, calendar)) {
hasZone++;
} else if (ParseDate(dt, parsePos, calendar)) {
hasDate++;
} else if (ParseDay(dt, parsePos, calendar)) {
hasDay++;
} else if (ParseRel(dt, parsePos, diff)) {
hasRel++;
} else if (ParseNumber(dt, parsePos, calendar,
hasDate > 0 && hasTime > 0 && hasRel == 0)) {
if (hasDate == 0 || hasTime == 0 || hasRel > 0) {
hasTime++;
}
} else {
return null;
}
}
if (hasTime > 1 || hasZone > 1 || hasDate > 1 || hasDay > 1) {
return null;
}
/*
* The following line handles years that are specified using
* only two digits. The line of code below implements a policy
* defined by the X/Open workgroup on the millinium rollover.
* Note: some of those dates may not actually be valid on some
* platforms. The POSIX standard startes that the dates 70-99
* shall refer to 1970-1999 and 00-38 shall refer to 2000-2038.
* This later definition should work on all platforms.
*/
int thisYear = calendar.get(Calendar.YEAR);
if (thisYear < 100) {
if (thisYear >= 69) {
calendar.set(Calendar.YEAR, thisYear+1900);
} else {
calendar.set(Calendar.YEAR, thisYear+2000);
}
}
if (hasRel > 0) {
if (hasTime == 0 && hasDate == 0 && hasDay == 0) {
calendar.setTime(baseDate);
}
calendar.add(Calendar.SECOND, diff.getSeconds());
calendar.add(Calendar.MONTH, diff.getMonths());
}
return calendar.getTime();
}
/**
*-----------------------------------------------------------------------------
*
* ParseTime --
*
* Parse a time string and sets the Calendar.
* A time string is valid, if it confirms to the following yacc rule:
* time : tUNUMBER tMERIDIAN
* | tUNUMBER ':' tUNUMBER o_merid
* | tUNUMBER ':' tUNUMBER tSNUMBER
* | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid
* | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER
* ;
*
* Results:
* True, if a time was read (parsePos was incremented and calendar
* was set according to the read time); false otherwise.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private boolean
ParseTime (
ClockToken[] dt, // Input as scanned array of tokens
ParsePosition parsePos, // Current position in input
Calendar calendar // calendar object to set
)
{
int pos = parsePos.getIndex();
if (pos+5 < dt.length &&
dt[pos].isUNumber() &&
dt[pos+1].is(':') &&
dt[pos+2].isUNumber() &&
dt[pos+3].is(':') &&
dt[pos+4].isUNumber() &&
dt[pos+5].isSNumber()) {
calendar.set(Calendar.HOUR, dt[pos].getInt());
calendar.set(Calendar.MINUTE, dt[pos+2].getInt());
calendar.set(Calendar.SECOND, dt[pos+4].getInt());
parsePos.setIndex(pos+6);
return true;
}
if (pos+4 < dt.length &&
dt[pos].isUNumber() &&
dt[pos+1].is(':') &&
dt[pos+2].isUNumber() &&
dt[pos+3].is(':') &&
dt[pos+4].isUNumber()) {
parsePos.setIndex(pos+5);
ParseMeridianAndSetHour(dt, parsePos, calendar, dt[pos].getInt());
calendar.set(Calendar.MINUTE, dt[pos+2].getInt());
calendar.set(Calendar.SECOND, dt[pos+4].getInt());
return true;
}
if (pos+3 < dt.length &&
dt[pos].isUNumber() &&
dt[pos+1].is(':') &&
dt[pos+2].isUNumber() &&
dt[pos+3].isSNumber()) {
calendar.set(Calendar.HOUR, dt[pos].getInt());
calendar.set(Calendar.MINUTE, dt[pos+2].getInt());
parsePos.setIndex(pos+4);
return true;
}
if (pos+2 < dt.length &&
dt[pos].isUNumber() &&
dt[pos+1].is(':') &&
dt[pos+2].isUNumber()) {
parsePos.setIndex(pos+3);
ParseMeridianAndSetHour(dt, parsePos, calendar, dt[pos].getInt());
calendar.set(Calendar.MINUTE, dt[pos+2].getInt());
return true;
}
if (pos+1 < dt.length &&
dt[pos].isUNumber() &&
dt[pos+1].is(ClockToken.MERIDIAN)) {
parsePos.setIndex(pos+1);
ParseMeridianAndSetHour(dt, parsePos, calendar, dt[pos].getInt());
return true;
}
return false;
}
/**
*-----------------------------------------------------------------------------
*
* ParseZone --
*
* Parse a timezone string and sets the Calendar.
* A timezone string is valid, if it confirms to the following yacc rule:
* zone : tZONE tDST
* | tZONE
* | tDAYZONE
* ;
*
* Results:
* True, if a timezone was read (parsePos was incremented and calendar
* was set according to the read timezone); false otherwise.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private boolean
ParseZone (
ClockToken[] dt, // Input as scanned array of tokens
ParsePosition parsePos, // Current position in input
Calendar calendar // calendar object to set
)
{
int pos = parsePos.getIndex();
if (pos+1 < dt.length &&
dt[pos].is(ClockToken.ZONE) &&
dt[pos+1].is(ClockToken.DST)) {
calendar.setTimeZone(dt[pos].getZone());
parsePos.setIndex(pos+2);
return true;
}
if (pos < dt.length &&
dt[pos].is(ClockToken.ZONE)) {
calendar.setTimeZone(dt[pos].getZone());
parsePos.setIndex(pos+1);
return true;
}
if (pos < dt.length &&
dt[pos].is(ClockToken.DAYZONE)) {
calendar.setTimeZone(dt[pos].getZone());
parsePos.setIndex(pos+1);
return true;
}
return false;
}
/**
*-----------------------------------------------------------------------------
*
* ParseDay --
*
* Parse a day string and sets the Calendar.
* A day string is valid, if it confirms to the following yacc rule:
* day : tDAY
* | tDAY ','
* | tUNUMBER tDAY
* ;
*
* Results:
* True, if a day was read (parsePos was incremented and calendar
* was set according to the read day); false otherwise.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private boolean
ParseDay (
ClockToken[] dt, // Input as scanned array of tokens
ParsePosition parsePos, // Current position in input
Calendar calendar // calendar object to set
)
{
int pos = parsePos.getIndex();
if (pos+1 < dt.length &&
dt[pos].is(ClockToken.DAY) &&
dt[pos+1].is(',')) {
calendar.set(Calendar.DAY_OF_MONTH, dt[pos].getInt());
parsePos.setIndex(pos+2);
return true;
}
if (pos+1 < dt.length &&
dt[pos].isUNumber() &&
dt[pos+1].is(ClockToken.DAY)) {
calendar.set(Calendar.DAY_OF_MONTH, dt[pos+1].getInt());
parsePos.setIndex(pos+2);
return true;
}
if (pos < dt.length &&
dt[pos].is(ClockToken.DAY)) {
calendar.set(Calendar.DAY_OF_MONTH, dt[pos].getInt());
parsePos.setIndex(pos+1);
return true;
}
return false;
}
/**
*-----------------------------------------------------------------------------
*
* ParseDate --
*
* Parse a date string and sets the Calendar.
* A date string is valid, if it confirms to the following yacc rule:
* date : tUNUMBER '/' tUNUMBER
* | tUNUMBER '/' tUNUMBER '/' tUNUMBER
* | tMONTH tUNUMBER
* | tMONTH tUNUMBER ',' tUNUMBER
* | tUNUMBER tMONTH
* | tEPOCH
* | tUNUMBER tMONTH tUNUMBER
* ;
*
* Results:
* True, if a date was read (parsePos was incremented and calendar
* was set according to the read day); false otherwise.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private boolean
ParseDate (
ClockToken[] dt, // Input as scanned array of tokens
ParsePosition parsePos, // Current position in input
Calendar calendar // calendar object to set
)
{
int pos = parsePos.getIndex();
if (pos+4 < dt.length &&
dt[pos].isUNumber() &&
dt[pos+1].is('/') &&
dt[pos+2].isUNumber() &&
dt[pos+3].is('/') &&
dt[pos+4].isUNumber()) {
calendar.set(Calendar.DAY_OF_MONTH, dt[pos+2].getInt());
calendar.set(Calendar.MONTH, dt[pos].getInt()-1);
calendar.set(Calendar.YEAR, dt[pos+4].getInt());
parsePos.setIndex(pos+5);
return true;
}
if (pos+3 < dt.length &&
dt[pos].is(ClockToken.MONTH) &&
dt[pos+1].isUNumber() &&
dt[pos+2].is(',') &&
dt[pos+3].isUNumber()) {
calendar.set(Calendar.DAY_OF_MONTH, dt[pos+1].getInt());
calendar.set(Calendar.MONTH, dt[pos].getInt());
calendar.set(Calendar.YEAR, dt[pos+3].getInt());
parsePos.setIndex(pos+4);
return true;
}
if (pos+2 < dt.length &&
dt[pos].isUNumber() &&
dt[pos+1].is('/') &&
dt[pos+2].isUNumber()) {
calendar.set(Calendar.DAY_OF_MONTH, dt[pos+2].getInt());
calendar.set(Calendar.MONTH, dt[pos].getInt()-1);
parsePos.setIndex(pos+3);
return true;
}
if (pos+2 < dt.length &&
dt[pos].isUNumber() &&
dt[pos+1].is(ClockToken.MONTH) &&
dt[pos+2].isUNumber()) {
calendar.set(Calendar.DAY_OF_MONTH, dt[pos].getInt());
calendar.set(Calendar.MONTH, dt[pos+1].getInt());
calendar.set(Calendar.YEAR, dt[pos+2].getInt());
parsePos.setIndex(pos+3);
return true;
}
if (pos+1 < dt.length &&
dt[pos].is(ClockToken.MONTH) &&
dt[pos+1].isUNumber()) {
calendar.set(Calendar.DAY_OF_MONTH, dt[pos+1].getInt());
calendar.set(Calendar.MONTH, dt[pos].getInt());
parsePos.setIndex(pos+2);
return true;
}
if (pos+1 < dt.length &&
dt[pos].isUNumber() &&
dt[pos+1].is(ClockToken.MONTH)) {
calendar.set(Calendar.DAY_OF_MONTH, dt[pos].getInt());
calendar.set(Calendar.MONTH, dt[pos+1].getInt());
parsePos.setIndex(pos+2);
return true;
}
if (pos < dt.length &&
dt[pos].is(ClockToken.EPOCH)) {
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.MONTH, 0);
calendar.set(Calendar.YEAR, EPOCH_YEAR);
parsePos.setIndex(pos+1);
return true;
}
return false;
}
/**
*-----------------------------------------------------------------------------
*
* ParseNumber --
*
* Parse a number and sets the Calendar.
* If argument mayBeYear is true, this number is conidered as year,
* otherwise it is date and time in the form HHMM.
*
* Results:
* True, if a number was read (parsePos was incremented and calendar
* was set according to the read day); false otherwise.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private boolean
ParseNumber (
ClockToken[] dt, // Input as scanned array of tokens
ParsePosition parsePos, // Current position in input
Calendar calendar, // calendar object to set
boolean mayBeYear // number is considered to be year?
)
{
int pos = parsePos.getIndex();
if (pos < dt.length &&
dt[pos].isUNumber()) {
parsePos.setIndex(pos+1);
if (mayBeYear) {
calendar.set(Calendar.YEAR, dt[pos].getInt());
} else {
calendar.set(Calendar.HOUR_OF_DAY, dt[pos].getInt()/100);
calendar.set(Calendar.MINUTE, dt[pos].getInt()%100);
calendar.set(Calendar.SECOND, 0);
}
return true;
}
return false;
}
/**
*-----------------------------------------------------------------------------
*
* ParseRel --
*
* Parse a relative time specification and sets the time difference.
* A relative time specification is valid, if it confirms to the
* following yacc rule:
* rel : relunit tAGO
* | relunit
* ;
*
* Results:
* True, if a relative time specification was read (parsePos was
* incremented and the time difference was set according to the read
* relative time specification); false otherwise.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private boolean
ParseRel (
ClockToken[] dt, // Input as scanned array of tokens
ParsePosition parsePos, // Current position in input
ClockRelTimespan diff // time difference to evaluate
)
{
if (ParseRelUnit(dt, parsePos, diff)) {
int pos = parsePos.getIndex();
if (pos < dt.length &&
dt[pos].is(ClockToken.AGO)) {
diff.negate();
parsePos.setIndex(pos+1);
}
return true;
}
return false;
}
/**
*-----------------------------------------------------------------------------
*
* ParseRelUnit --
*
* Parse a relative time unit and sets the time difference.
* A relative time unit is valid, if it confirms to the
* following yacc rule:
* relunit : tUNUMBER tMINUTE_UNIT
* | tSNUMBER tMINUTE_UNIT
* | tMINUTE_UNIT
* | tSNUMBER tSEC_UNIT
* | tUNUMBER tSEC_UNIT
* | tSEC_UNIT
* | tSNUMBER tMONTH_UNIT
* | tUNUMBER tMONTH_UNIT
* | tMONTH_UNIT
* ;
*
* Results:
* True, if a relative time unit was read (parsePos was incremented and
* the time difference was set according to the read relative time unit);
* false otherwise.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private boolean
ParseRelUnit (
ClockToken[] dt, // Input as scanned array of tokens
ParsePosition parsePos, // Current position in input
ClockRelTimespan diff // time difference to evaluate
)
{
int pos = parsePos.getIndex();
if (pos+1 < dt.length &&
(dt[pos].isUNumber() || dt[pos].isSNumber()) &&
dt[pos+1].is(ClockToken.MINUTE_UNIT)) {
diff.addSeconds(dt[pos].getInt()*dt[pos+1].getInt()*60);
parsePos.setIndex(pos+2);
return true;
} else if (pos+1 < dt.length &&
(dt[pos].isUNumber() || dt[pos].isSNumber()) &&
dt[pos+1].is(ClockToken.SEC_UNIT)) {
diff.addSeconds(dt[pos].getInt());
parsePos.setIndex(pos+2);
return true;
} else if (pos+1 < dt.length &&
(dt[pos].isUNumber() || dt[pos].isSNumber()) &&
dt[pos+1].is(ClockToken.MONTH_UNIT)) {
diff.addMonths(dt[pos].getInt()*dt[pos+1].getInt());
parsePos.setIndex(pos+2);
return true;
} else if (pos < dt.length &&
dt[pos].is(ClockToken.MINUTE_UNIT)) {
diff.addSeconds(dt[pos].getInt()*60);
parsePos.setIndex(pos+1);
return true;
} else if (pos < dt.length &&
dt[pos].is(ClockToken.SEC_UNIT)) {
diff.addSeconds(1);
parsePos.setIndex(pos+1);
return true;
} else if (pos < dt.length &&
dt[pos].is(ClockToken.MONTH_UNIT)) {
diff.addMonths(dt[pos].getInt());
parsePos.setIndex(pos+1);
return true;
}
return false;
}
/**
*-----------------------------------------------------------------------------
*
* ParseMeridianAndSetHour --
*
* Parse a meridian and sets the hour field of the calendar.
* A meridian is valid, if it confirms to the following yacc rule:
* o_merid : // NULL
* | tMERIDIAN
* ;
*
* Results:
* None; parsePos was incremented and the claendar was set according
* to the read meridian.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private void
ParseMeridianAndSetHour(
ClockToken[] dt, // Input as scanned array of tokens
ParsePosition parsePos, // Current position in input
Calendar calendar, // calendar object to set
int hour // hour value (1-12 or 0-23) to set.
)
{
int pos = parsePos.getIndex();
int hourField;
if (pos < dt.length &&
dt[pos].is(ClockToken.MERIDIAN)) {
calendar.set(Calendar.AM_PM, dt[pos].getInt());
parsePos.setIndex(pos+1);
hourField = Calendar.HOUR;
} else {
hourField = Calendar.HOUR_OF_DAY;
}
if (hourField == Calendar.HOUR && hour == 12) {
hour = 0;
}
calendar.set(hourField, hour);
}
/**
*-----------------------------------------------------------------------------
*
* GetTokens --
*
* Lexical analysis of the input string.
*
* Results:
* An array of ClockToken, representing the input string.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private ClockToken[]
GetTokens (
String in, // String to parse
boolean debug // Send the generated token list to stderr?
)
{
ParsePosition parsePos = new ParsePosition(0);
ClockToken dt;
Vector tokenVector = new Vector(in.length());
while ((dt = GetNextToken(in, parsePos)) != null) {
tokenVector.addElement(dt);
}
ClockToken[] tokenArray = new ClockToken[tokenVector.size()];
tokenVector.copyInto(tokenArray);
if (debug) {
for (int ix = 0; ix < tokenArray.length; ix++) {
if (ix != 0) {
System.err.print(",");
}
System.err.print(tokenArray[ix].toString());
}
System.err.println("");
}
return tokenArray;
}
/**
*-----------------------------------------------------------------------------
*
* GetNextToken --
*
* Lexical analysis of the next token of input string.
*
* Results:
* A ClockToken representing the next token of the input string,
* (parsePos was incremented accordingly), if one was found.
* null otherwise (e.g. at end of input).
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private ClockToken
GetNextToken (
String in, // String to parse
ParsePosition parsePos // Current position in input
)
{
int pos = parsePos.getIndex();
int sign;
while (true) {
while (pos < in.length() && Character.isSpaceChar(in.charAt(pos))) {
pos++;
}
if (pos >= in.length()) {
break;
}
char c = in.charAt(pos);
if (Character.isDigit(c) || c == '-' || c == '+') {
if (c == '-' || c == '+') {
sign = c == '-' ? -1 : 1;
if (!Character.isDigit(in.charAt(++pos))) {
/*
* skip the '-' sign
*/
continue;
}
} else {
sign = 0;
}
int number = 0;
while (pos < in.length()
&& Character.isDigit(c = in.charAt(pos))) {
number = 10 * number + c - '0';
pos++;
}
if (sign < 0) {
number = -number;
}
parsePos.setIndex(pos);
return new ClockToken(number, sign != 0);
}
if (Character.isLetter(c)) {
int beginPos = pos;
while (++pos < in.length()) {
c = in.charAt(pos);
if (!Character.isLetter(c) && c != '.') {
break;
}
}
parsePos.setIndex(pos);
return LookupWord(in.substring(beginPos, pos));
}
parsePos.setIndex(pos+1);
return new ClockToken(in.charAt(pos));
}
parsePos.setIndex(pos+1);
return null;
}
/**
*-----------------------------------------------------------------------------
*
* LookupWord --
*
* Construct a ClockToken for the given word.
*
* Results:
* A ClockToken representing the given word.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
private ClockToken LookupWord(
String word // word to lookup
)
{
int ix;
String names[];
String zones[][];
if (word.equalsIgnoreCase("am") || word.equalsIgnoreCase("a.m.")) {
return new ClockToken(ClockToken.MERIDIAN, Calendar.AM);
}
if (word.equalsIgnoreCase("pm") || word.equalsIgnoreCase("p.m.")) {
return new ClockToken(ClockToken.MERIDIAN, Calendar.PM);
}
/*
* See if we have an abbreviation for a day or month.
*/
boolean abbrev;
if (word.length() == 3) {
abbrev = true;
} else if (word.length() == 4 && word.charAt(3) == '.') {
abbrev = true;
word = word.substring(0, 3);
} else {
abbrev = false;
}
DateFormatSymbols symbols = new DateFormatSymbols(Locale.US);
if (abbrev) {
names = symbols.getShortMonths();
} else {
names = symbols.getMonths();
}
for (ix = 0; ix < names.length; ix++) {
if (word.equalsIgnoreCase(names[ix])) {
return new ClockToken(ClockToken.MONTH, ix);
}
}
if (abbrev) {
names = symbols.getShortWeekdays();
} else {
names = symbols.getWeekdays();
}
for (ix = 0; ix < names.length; ix++) {
if (word.equalsIgnoreCase(names[ix])) {
return new ClockToken(ClockToken.DAY, ix);
}
}
/*
* Drop out any periods and try the timezone table.
*/
StringBuffer withoutDotsBuf = new StringBuffer(word.length());
for (ix = 0; ix < word.length(); ix++) {
if (word.charAt(ix) != '.') {
withoutDotsBuf.append(word.charAt(ix));
}
}
String withoutDots = new String(withoutDotsBuf);
zones = symbols.getZoneStrings();
for (ix = 0; ix < zones.length; ix++) {
if (withoutDots.equalsIgnoreCase(zones[ix][2]) ||
withoutDots.equalsIgnoreCase(zones[ix][4])) {
TimeZone zone = TimeZone.getTimeZone(zones[ix][0]);
return new ClockToken(ClockToken.ZONE, zone);
}
}
if (withoutDots.equalsIgnoreCase("dst")) {
return new ClockToken(ClockToken.DST, null);
}
/*
* Strip off any plural and try the units.
*/
String singular;
if (word.endsWith("s")) {
singular = word.substring(0, word.length()-1);
} else {
singular = word;
}
if (singular.equalsIgnoreCase("year")) {
return new ClockToken(ClockToken.MONTH_UNIT, 12);
} else if (singular.equalsIgnoreCase("month")) {
return new ClockToken(ClockToken.MONTH_UNIT, 1);
} else if (singular.equalsIgnoreCase("fortnight")) {
return new ClockToken(ClockToken.MINUTE_UNIT, 14*24*60);
} else if (singular.equalsIgnoreCase("week")) {
return new ClockToken(ClockToken.MINUTE_UNIT, 7*24*60);
} else if (singular.equalsIgnoreCase("day")) {
return new ClockToken(ClockToken.MINUTE_UNIT, 24*60);
} else if (singular.equalsIgnoreCase("hour")) {
return new ClockToken(ClockToken.MINUTE_UNIT, 60);
} else if (singular.equalsIgnoreCase("minute")) {
return new ClockToken(ClockToken.MINUTE_UNIT, 1);
} else if (singular.equalsIgnoreCase("min")) {
return new ClockToken(ClockToken.MINUTE_UNIT, 1);
} else if (singular.equalsIgnoreCase("second")) {
return new ClockToken(ClockToken.SEC_UNIT, 1);
} else if (singular.equalsIgnoreCase("sec")) {
return new ClockToken(ClockToken.SEC_UNIT, 1);
}
if (singular.equalsIgnoreCase("tomorrow")) {
return new ClockToken(ClockToken.MINUTE_UNIT, 1*24*60);
} else if (singular.equalsIgnoreCase("yesterday")) {
return new ClockToken(ClockToken.MINUTE_UNIT, -1*24*60);
} else if (singular.equalsIgnoreCase("today")) {
return new ClockToken(ClockToken.MINUTE_UNIT, 0);
} else if (singular.equalsIgnoreCase("now")) {
return new ClockToken(ClockToken.MINUTE_UNIT, 0);
} else if (singular.equalsIgnoreCase("last")) {
return new ClockToken(-1, false);
} else if (singular.equalsIgnoreCase("this")) {
return new ClockToken(ClockToken.MINUTE_UNIT, 0);
} else if (singular.equalsIgnoreCase("next")) {
return new ClockToken(2, false);
} else if (singular.equalsIgnoreCase("ago")) {
return new ClockToken(ClockToken.AGO, 1);
} else if (singular.equalsIgnoreCase("epoch")) {
return new ClockToken(ClockToken.EPOCH, 0);
}
/*
* Ignore military timezones.
*/
return new ClockToken(word);
}
} // end ClockCmd
/**
*-----------------------------------------------------------------------------
*
* CLASS ClockToken --
*
* An object of this class represents a lexical unit of the human
* readable date string. It can be one of the following variants:
*
* - signed number,
* = occurence can be asked by isSNumber(),
* = value can be retrieved by means of getInt();
* - unsigned number,
* = occurence can be asked by isUNumber(),
* = value can be retrieved by means of getInt();
* - a single character (delimiters like ':' or '/'),
* = occurence can be asked by is(), e.g. is('/');
* - a word (like "January" or "DST")
* = occurence can be asked by is(), e.g. is(ClockToken.AGO);
* = value can be retrieved by means of getInt() or getZone().
*
*-----------------------------------------------------------------------------
*/
class ClockToken {
final static int SNUMBER = 1;
final static int UNUMBER = 2;
final static int WORD = 3;
final static int CHAR = 4;
final static int MONTH = 5;
final static int DAY = 6;
final static int MONTH_UNIT = 7;
final static int MINUTE_UNIT = 8;
final static int SEC_UNIT = 9;
final static int AGO = 10;
final static int EPOCH = 11;
final static int ZONE = 12;
final static int DAYZONE = 13;
final static int DST = 14;
final static int MERIDIAN = 15;
ClockToken(int number, boolean signed) {
this.kind = signed ? SNUMBER : UNUMBER;
this.number = number;
}
ClockToken(int kind, int number) {
this.kind = kind;
this.number = number;
}
ClockToken(int kind, TimeZone zone) {
this.kind = kind;
this.zone = zone;
}
ClockToken(String word) {
this.kind = WORD;
this.word = word;
}
ClockToken(char c) {
this.kind = CHAR;
this.c = c;
}
public boolean isSNumber() {
return kind == SNUMBER;
}
public boolean isUNumber() {
return kind == UNUMBER;
}
public boolean is(char c) {
return this.kind == CHAR && this.c == c;
}
public boolean is(int kind) {
return this.kind == kind;
}
int getInt() {
return number;
}
TimeZone getZone() {
return zone;
}
public String toString() {
if (isSNumber()) {
return "S"+Integer.toString(getInt());
} else if (isUNumber()) {
return "U"+Integer.toString(getInt());
} else if (kind == WORD) {
return word;
} else if (kind == CHAR) {
return new Character(c).toString();
} else if (kind == ZONE || kind == DAYZONE) {
return zone.getID();
} else {
return "("+kind+","+getInt()+")";
}
}
private int kind;
private int number;
private String word;
private char c;
private TimeZone zone;
} // end ClockToken
/**
*-----------------------------------------------------------------------------
*
* CLASS ClockRelTimespan --
*
* An object of this class can be used to track the time difference during
* the analysis of a relative time specification.
*
* It has two read only properties 'seconds' and 'months', which are set
* to 0 during initialization and which can be modified by means of the
* addSeconds(), addMonths() and negate() methods.
*
*-----------------------------------------------------------------------------
*/
class ClockRelTimespan {
ClockRelTimespan() {
seconds = 0;
months = 0;
}
void addSeconds(int s) {
seconds += s;
}
void addMonths(int m) {
months += m;
}
void negate() {
seconds = -seconds;
months = -months;
}
int getSeconds() {
return seconds;
}
int getMonths() {
return months;
}
private int seconds;
private int months;
}
*** all.org Wed Nov 11 01:52:53 1998
--- all Mon Dec 28 13:35:42 1998
***************
*** 16,22 ****
# These are currently the tests that Jacl can pass comfortably.
# (ToDo) Add others!
! set fileList {append assocd case concat error eval expr
fileName for format get
if incr info join lindex linsert list llength lrange
lreplace lsort parse parseOld pkg proc regexp rename scan set split
--- 16,22 ----
# These are currently the tests that Jacl can pass comfortably.
# (ToDo) Add others!
! set fileList {append assocd case clock concat error eval expr
fileName for format get
if incr info join lindex linsert list llength lrange
lreplace lsort parse parseOld pkg proc regexp rename scan set split
# Commands covered: clock
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# SCCS: @(#) clock.test 1.17 97/11/24 15:05:38
if {[string compare test [info procs test]] == 1} then {source defs}
test clock-1.1 {clock tests} {
list [catch {clock} msg] $msg
} {1 {wrong # args: should be "clock option ?arg ...?"}}
test clock-1.2 {clock tests} {
list [catch {clock foo} msg] $msg
} {1 {bad option "foo": must be clicks, format, scan, or seconds}}
# clock clicks
test clock-2.1 {clock clicks tests} {
expr [clock clicks]+1
concat {}
} {}
test clock-2.2 {clock clicks tests} {
list [catch {clock clicks foo} msg] $msg
} {1 {wrong # args: should be "clock clicks"}}
test clock-2.3 {clock clicks tests} {
set start [clock clicks]
after 10
set end [clock clicks]
expr "$end > $start"
} {1}
# clock format
test clock-3.1 {clock format tests} {unixOnly} {
set clockval 657687766
clock format $clockval -format {%a %b %d %I:%M:%S %p %Y} -gmt true
} {Sun Nov 04 03:02:46 AM 1990}
test clock-3.2 {clock format tests} {
list [catch {clock format} msg] $msg
} {1 {wrong # args: should be "clock format clockval ?-format string? ?-gmt
boolean?"}}
test clock-3.3 {clock format tests} {
list [catch {clock format foo} msg] $msg
} {1 {expected integer but got "foo"}}
test clock-3.4 {clock format tests} {unixOrPc} {
set clockval 657687766
clock format $clockval -format "%a %b %d %I:%M:%S %p %Y" -gmt true
} "Sun Nov 04 03:02:46 AM 1990"
test clock-3.5 {clock format tests} {
list [catch {clock format a b c d e g} msg] $msg
} {1 {wrong # args: should be "clock format clockval ?-format string? ?-gmt
boolean?"}}
test clock-3.6 {clock format tests} {unixOrPc nonPortable} {
set clockval -1
clock format $clockval -format "%a %b %d %I:%M:%S %p %Y" -gmt true
} "Wed Dec 31 11:59:59 PM 1969"
test clock-3.7 {clock format tests} {
list [catch {clock format 123 -bad arg} msg] $msg
} {1 {bad switch "-bad": must be -format, or -gmt}}
test clock-3.8 {clock format tests} {
clock format 123 -format "x"
} x
test clock-3.9 {clock format tests} {
clock format 123 -format ""
} ""
# clock scan
test clock-4.1 {clock scan tests} {
list [catch {clock scan} msg] $msg
} {1 {wrong # args: should be "clock scan dateString ?-base clockValue? ?-gmt
boolean?"}}
test clock-4.2 {clock scan tests} {
list [catch {clock scan "bad-string"} msg] $msg
} {1 {unable to convert date-time string "bad-string"}}
test clock-4.3 {clock scan tests} {
clock format [clock scan "14 Feb 92" -gmt true] \
-format {%m/%d/%y %I:%M:%S %p} -gmt true
} {02/14/92 12:00:00 AM}
test clock-4.4 {clock scan tests} {
clock format [clock scan "Feb 14, 1992 12:20 PM" -gmt true] \
-format {%m/%d/%y %I:%M:%S %p} -gmt true
} {02/14/92 12:20:00 PM}
test clock-4.5 {clock scan tests} {
clock format \
[clock scan "Feb 14, 1992 12:20 PM" -base 319363200 -gmt true] \
-format {%m/%d/%y %I:%M:%S %p} -gmt true
} {02/14/92 12:20:00 PM}
test clock-4.6 {clock scan tests} {
set time [clock scan "Oct 23,1992 15:00"]
clock format $time -format {%b %d,%Y %H:%M}
} {Oct 23,1992 15:00}
test clock-4.7 {clock scan tests} {
set time [clock scan "Oct 23,1992 15:00 GMT"]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Oct 23,1992 15:00 GMT}
test clock-4.8 {clock scan tests} {
set time [clock scan "Oct 23,1992 15:00" -gmt true]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Oct 23,1992 15:00 GMT}
test clock-4.9 {clock scan tests} {
list [catch {clock scan "Jan 12" -bad arg} msg] $msg
} {1 {bad switch "-bad": must be -base, or -gmt}}
# The following two two tests test the two year date policy
test clock-4.10 {clock scan tests} {
set time [clock scan "1/1/71" -gmt true]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,1971 00:00 GMT}
test clock-4.11 {clock scan tests} {
set time [clock scan "1/1/37" -gmt true]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,2037 00:00 GMT}
# clock seconds
test clock-5.1 {clock seconds tests} {
expr [clock seconds]+1
concat {}
} {}
test clock-5.2 {clock seconds tests} {
list [catch {clock seconds foo} msg] $msg
} {1 {wrong # args: should be "clock seconds"}}
test clock-5.3 {clock seconds tests} {
set start [clock seconds]
after 2000
set end [clock seconds]
expr "$end > $start"
} {1}
# The following dates check certain roll over dates
set day [expr 24 * 60 * 60]
test clock-6.1 {clock roll over dates} {
set time [clock scan "12/31/1998" -gmt true]
clock format [expr $time + $day] -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,1999 00:00 GMT}
test clock-6.2 {clock roll over dates} {
set time [clock scan "12/31/1999" -gmt true]
clock format [expr $time + $day] -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,2000 00:00 GMT}
test clock-6.3 {clock roll over dates} {
set time [clock scan "2/28/2000" -gmt true]
clock format [expr $time + $day] -format {%b %d,%Y %H:%M GMT} -gmt true
} {Feb 29,2000 00:00 GMT}
test clock-6.4 {clock roll over dates} {
set time [clock scan "2/29/2000" -gmt true]
clock format [expr $time + $day] -format {%b %d,%Y %H:%M GMT} -gmt true
} {Mar 01,2000 00:00 GMT}
test clock-6.5 {clock roll over dates} {
set time [clock scan "January 1, 2000" -gmt true]
clock format $time -format %A -gmt true
} {Saturday}
test clock-6.6 {clock roll over dates} {
set time [clock scan "January 1, 2000" -gmt true]
clock format $time -format %j -gmt true
} {001}
test clock-6.7 {clock roll over dates} {
set time [clock scan "February 29, 2000" -gmt true]
clock format $time -format %A -gmt true
} {Tuesday}
test clock-6.8 {clock roll over dates} {
set time [clock scan "February 29, 2000" -gmt true]
clock format $time -format %j -gmt true
} {060}
test clock-6.9 {clock roll over dates} {
set time [clock scan "March 1, 2000" -gmt true]
clock format $time -format %A -gmt true
} {Wednesday}
test clock-6.10 {clock roll over dates} {
set time [clock scan "March 1, 2000" -gmt true]
clock format $time -format %j -gmt true
} {061}
test clock-6.11 {clock roll over dates} {
set time [clock scan "March 1, 2001" -gmt true]
clock format $time -format %j -gmt true
} {060}
Well, Tcl Blend and Jacl are not really commercial products so they do not
have a "release schedule". I am currently working on a number of features
and bug fixes that will be going into the beta release. Once the beta
release is done no "new features" will be going in and only bug fixes
(and perhaps unimplemented commands) will be worked on. The only real
answer I can give you is that the 1.1 final will be released
"when it is done".
Mo DeJong
dejong@...
gimme multimedia group
On Tue, 22 Dec 1998, Philip Chu wrote:
> I just joined this list, so forgive me if this has been answered recently:
> What is the release schedule for TclBlend? In particular, when will
> TclBlend 1.1 final be released? I would like to use it in a commercial
> product.
>
> --
> Phil Chu
> philipchu@...http://www.technicat.com/
>
> ----------------------------------------------------------------
> The TclJava mailing list is sponsored by WebNet Technologies.
> To subscribe: send mail to TclJava-request@...
> with the word SUBSCRIBE as the subject.
> To unsubscribe: send mail to TclJava-request@...
> with the word UNSUBSCRIBE as the subject.
> To send to the list, send email to 'TclJava@...'.
> A list archive is at: http://www.findmail.com/listsaver/tcldallas/
>
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
I just joined this list, so forgive me if this has been answered recently:
What is the release schedule for TclBlend? In particular, when will
TclBlend 1.1 final be released? I would like to use it in a commercial
product.
--
Phil Chu
philipchu@...http://www.technicat.com/
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Jacl works in applets, with limitations.
Check out:
http://ptolemy.eecs.berkeley.edu/~cxh/java/jaclapplet/index.html
The biggest limitation is that commands like 'java::new' does not
work. If you are not interfacing directly to java, then Jacl might
provide enough functionality for you.
-Christopher
--------
Jacl Request
Name: Howard Jess
email: howard@...
Synopsis: Applet support
DesiredBehavior:
Mostly interested in web-based applications: we have a largish system that
uses TCL scripts for CGI; we'd like to leverage our TCL knowledge in buildin
g browser-based applications. So far, JACL doesn't support applets, but JPy
thon does. We'd rather stick with TCL, if JACL support were possible.
--------
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Hello,
I'm working with TclBlend 1.1a1 and JDK1.2 on WinNT for two weeks now
and most of the time I'm really happy: Good work, Chris+Mo!
But meanwhile I found some -mostly small- bugs (buggies?),
which I will report here on this mailinglist (one after the other).
Usage of javax.swing.JOptionPane freezes the whole application!
May be, there is something wrong in thread control?
It must be a problem of TclJava, since the corresponding program in
pure Java is working fine, but it fails with Jacl and TclBlend.
Here are the two programs, first the tcl one, then the Java stuff:
--------------------------------------------------------------------------------
package require java
proc keyPressed {} {
java::call javax.swing.JOptionPane showMessageDialog \
[java::null] "This is a very important message" "Wow!" \
[java::field javax.swing.JOptionPane INFORMATION_MESSAGE]
}
set this [java::new javax.swing.JFrame "Dialog-Test"]
java::bind $this keyPressed keyPressed
$this setSize 400 200
[$this getContentPane] add [java::new javax.swing.JLabel \
"Press any key, then wait and see..."]
$this show
# The funny lines below will go into the event loop,
# if we are running under a tclsh, wish or jaclsh...
if {[info globals tk_version] != ""} {
wm withdraw .
catch {console hide}
} else {
vwait forever
}
--------------------------------------------------------------------------------
import javax.swing.*;
import java.awt.event.*;
public class Dialog extends KeyAdapter implements KeyListener {
public void keyPressed (KeyEvent e) {
JOptionPane.showMessageDialog (null, "This is a very important message",
"Wow!", JOptionPane.INFORMATION_MESSAGE);
}
public Dialog () {
JFrame f = new JFrame ("Dialog-Test");
f.setSize (400, 200);
f.addKeyListener (this);
f.getContentPane ().add (new JLabel ("Press any key, then wait and see..."));
f.show ();
}
public static void main(String args[]) {
Dialog f = new Dialog ();
}
}
--------------------------------------------------------------------------------
Thanks for listening, Krischan
--
Christian Krone, SQL Datenbanksysteme GmbH
Mail mailto:krischan@...
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
>FOR IMMEDIATE RELEASE
>December 1, 1998
>
>FURTHER INFORMATION CONTACT
>Ellen Maremont Silver
>(707)829-0515 ext. 322 silver@...
>http://www.oreilly.com/
>
>JAVA/PERL TOOL AVAILABLE AS OPEN SOURCE SOFTWARE
>Programmers Can Use Strengths of Two Popular Languages in the Same
>Environment
>
>Sebastopol, CA--Java/Perl Lingo (JPL), software which enables
>programmers to use the use the strengths of both Java and Perl in the
>same environment, is now freely available as open source software.
>Until now, the tool has been available exclusively in O'Reilly &
>Associates' Perl Resource Kit-UNIX Edition, a commercial product. JPL
>was developed by Larry Wall, creator of Perl and Senior Software
>Developer at O'Reilly & Associates.
>
>JPL, available since November, 1997, is a unique project whose goal is
>to seamlessly unite the two popular languages in a way which lets them
>complement each other's strengths. Java excels at helping computers
>across a network or the Internet communicate and share data; Perl is
>used especially for system administration and interactive Web sites.
>JPL enables programmers to implement Java methods with Perl, and for
>Perl code to access Java via the Java Native Interface (JNI). It
>includes a translator and build system that make it easy to create JPL
>applications.
>
>The JPL tool and its source code are available as part of the latest
>development release of Perl (version 5.005_54) and can be obtained at
>http://www.perl.com/. Subscription information for the JPL mailing list
>is available at http://www.perl.org/maillist.html/.
>
>"O'Reilly has been a strong supporter of open source software, so
>releasing JPL as open source matches our company values," said Gina
>Blaber, Director of O'Reilly's Software Products. "JPL will benefit
>from the attention of the broader development community. Further, our
>Perl books and software are an important part of the O'Reilly business,
>so we want to thank and support the open source community by making the
>JPL source available."
>
>O'Reilly first released the Perl Resource Kit-UNIX in November, 1997,
>and followed it in August with the Perl Resource Kit-Win32 Edition.
>
># # #
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/
Hey John!
> Hey Mo!
>
> > > Now I need to go
> >
> > Did you set that tcl_platform(javaCastNeeded) variable yourself? I have
> > never seen that before.
>
> I set it myself, because I needed a flag to test for
> whether I needed the cast...
>
>
> > This depends on what types the Java objects are returned as
> > in the methods.
> >
> > > 1. I have to do extra work to cast most of the objects
> > > I get back from Java methods.
>
> I said "most." I understand how it works, my point
> is that *most* of the time in *real* code I seem to
> be calling methods that are overridden, which means
> that I have to downcast the result. I already explained
> why this is bogus.
To be honest, I do not see how it would be easy to explain the
1.0 behavior to anyone that has worked with any OO system. I
did not invent this OO stuff so I am not going to defend it
but at the very least the interface between tcl and jacl should
respect the OO "rules of the road".
> > True, the docs need some work before the beta is released.
> >
> > > 3. It's going to be hard to explain and teach to
> > > Tcl programmers.
>
> I didn't say hard to document, I said hard to explain.
> They're not the same thing. Writing documentation
> isn't going to fix the problem.
This really is a feature that "can not be removed". It is not
just a matter of adding a command of something. This behavior
is at the lowest level of the interaction between tcl and java.
If it were possible to add a "no typing" feature we might do it,
but it is not so there is no reason to argue about it.
> > That is not possible. This is not a "feature" that was
> > added on to anything. This is now the "behavior" and
> > the only way to not use it is by using the 1.0 version.
> > There were so many changes needed to get this to work
> > that removing the "feature" is no longer an option.
> >
> > > Anyway, I'm reverting to 1.0 so I can get some work
> > > done. I think the 1.1 team should seriously consider
> > > removing this feature.
>
> "That is not possible"? Come off it, Mo, it's code,
> not Mt Rushmore... What I'm telling you is that this
> "feature" is just not working. At the least, consider
> an option to allow it to be turned off. Please?
I know, I know, Tcl is not typed and Java is. My point is
that when you use the two together you have to respect the
rules for both languages as much as possible. All things
being equal, I would vote for the thing that was easy to
code. In this situation the "easy to code" argument
falls flat on its face because in 1.0 you were able to do
things to Java objects from Tcl code that would not be
allowed in Java code. I have also attempted to ignore
the role of object types in method invocations in this
thread. This handy new feature in 1.1 would be very
difficult to implement properly if the reflected objects
were not typed (like in 1.0).
> > Ok, the main point I want to make about this "new feature"
> > is that it is not really a feature as much as it is a bug
> > fix. The 1.0 version did not keep track of the type of
> > Java objects. This means that in some instances (like the
> > situation you describe where Java objects were typed as
> > java.lang.Object) it would be "easier" to use because
> > the upcast from Object to whatever could be avoided, but
> > there are other situations where this "behavior" would
> > lead to voilations of the Java language specification.
> > I am not going to try to rehash this with an example
> > or anything but I can point you to the HTML version of my
> > paper from the Tcl conference (of course if you have the
> > proceedings you could just look at that). Section 5 has
> > a number of examples of why the behavior in 1.0 was bad
> > and why the new 1.1 behavior is good.
> >
> > http://www.cs.umn.edu/~dejong/tcl/paper.html
>
> This example doesn't say WHY the 1.1 behaviour is
> good. It just says it is "consistent with object-oriented
> principles", much as above you talk about "violating
> the Java language specification." But that's irrelevant
> here -- we are coding in Tcl, which is neither typed
> nor object-oriented. Give me ONE decent example that
> says WHY it is better.
Example at bottom of email.
> > I know that is "seems" like a little more work to use
> > the java::cast command but it really is better in the
> > long run. Another nice feature that 1.1 gives you
> > is the ability to use Java interface classes which
> > were not accessable in 1.0. Yet another nice feature that
> > is not described in my paper or the docs is the fact
> > that Java array objects are typed and the elements of
> > the arrays are typed in 1.1.
>
> Can you give us an example of using interface classes?
>
> > I hope that helps
>
> No, not really.
>
> JohnR
>
> > Mo DeJong
> > dejong@...
> >
>
>
Ok, here is attempt #2 at why the new system is better. The class
could be saved as simple.java and the commands at the bottom can
be run inside jacl or tclblend.
public class simple implements simple.inter {
public static interface inter {
public void allowed();
}
public void allowed() {
System.out.println("allowed");
}
public void not_allowed() {
System.out.println("NOT allowed");
System.exit(-1);
}
public static Object getAsObject() {
return new simple();
}
public static inter getAsInterface() {
return new simple();
}
}
/*
Example of regular object use.
%set o [java::call simple getAsObject]
%java::info class $o
1.0 returns "simple"
1.1 returns "java.lang.Object"
%$o allowed
This would print "allowed" in 1.0
This would fail in 1.1 because type is "Object" not "simple" (this is the
correct behavior)
Example of interface use (new in 1.1).
%set i [java::call simple getAsInterface]
%java::info class $i
1.0 would think the object type is "simple"
1.1 would see the object as an interface called "inter"
(ignore the fact that inter is an inner class, that is just so
that you only have to save this as a single simple.java file).
%$i allowed
This would work in 1.0 and 1.1
%$i not_allowed
1.0 this INCORRECT invocation would be allowed because 1.0 did not
understand Java interfaces.
1.1 this method would be rejected because the method "not_allowed"
is not defined for the interface "inter".
*/
I hope that helps
mo dejong
dejong at cs.umn.edu
----------------------------------------------------------------
The TclJava mailing list is sponsored by WebNet Technologies.
To subscribe: send mail to TclJava-request@...
with the word SUBSCRIBE as the subject.
To unsubscribe: send mail to TclJava-request@...
with the word UNSUBSCRIBE as the subject.
To send to the list, send email to 'TclJava@...'.
A list archive is at: http://www.findmail.com/listsaver/tcldallas/