Initial revision

From-SVN: r26263
This commit is contained in:
Tom Tromey 1999-04-07 14:42:40 +00:00
parent 140fa895c6
commit ee9dd3721b
370 changed files with 173494 additions and 0 deletions

482
libjava/COPYING.LIB Normal file
View file

@ -0,0 +1,482 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

5035
libjava/ChangeLog Normal file

File diff suppressed because it is too large Load diff

11
libjava/LIBGCJ_LICENSE Normal file
View file

@ -0,0 +1,11 @@
March 2, 1999
The libgcj library is licensed under the terms of the GNU Library
General Public License.
You should have received a copy of the GNU Library General Public
License along with libjava; see the file COPYING.LIB. If not, write
to the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.

660
libjava/Makefile.am Normal file
View file

@ -0,0 +1,660 @@
## Process this file with automake to produce Makefile.in.
AUTOMAKE_OPTIONS = foreign no-installinfo
if TESTSUBDIR
SUBDIRS = testsuite
endif
## ################################################################
##
## What gets installed, and where.
##
toolexecdir = $(exec_prefix)/$(target_alias)
toolexeclibdir = $(toolexecdir)/lib$(MULTISUBDIR)
toolexeclib_LIBRARIES = libgcj.a
data_DATA = libgcj.zip
## For now, only on native systems.
if NATIVE
bin_PROGRAMS = jv-convert
endif
## ################################################################
##
## Compilers and compilation flags.
##
## CANADIAN is a misnomer. Really we check to see if we must pick up
## the tools from the path.
if CANADIAN
if NULL_TARGET
## In this case, gcj is found outside the build tree. However, zip is
## found in the build tree.
GCJ = gcj
ZIP = $(MULTIBUILDTOP)../$(COMPPATH)/zip/zip$(EXEEXT)
else
GCJ = $(target_alias)-gcj
ZIP = zip
endif
GCJH = gcjh
else # CANADIAN
## JAVAC is set to `$(GCJ) -C'. However, JAVAC is run from the srcdir
## (due to problems running it in builddir). In this case the obvious
## definition of GCJ won't work; instead we resort to this ugly
## definition that gives us absolute paths.
expanded = `cd $(MULTIBUILDTOP)../$(COMPPATH)/gcc && pwd`
GCJ = $(expanded)/gcj$(EXEEXT) -B$(expanded)/
GCJH = $(MULTIBUILDTOP)../$(COMPPATH)/gcc/gcjh$(EXEEXT)
ZIP = $(MULTIBUILDTOP)../$(COMPPATH)/zip/zip$(EXEEXT)
endif # CANADIAN
JAVAC = $(GCJ) -C
EH_COMMON_INCLUDE = @EH_COMMON_INCLUDE@
WARNINGS = -W -Wall
AM_CXXFLAGS = -fno-rtti -fvtable-thunks @LIBGCJ_CXXFLAGS@ $(WARNINGS)
if USING_GCC
AM_CFLAGS = @LIBGCJ_CFLAGS@ $(WARNINGS)
else
AM_CFLAGS = @LIBGCJ_CFLAGS@
endif
JCFLAGS = -g
JC1FLAGS = -g @LIBGCJ_JAVAFLAGS@
INCLUDES = -Iinclude -I$(top_srcdir)/include $(GCINCS) $(THREADINCS) $(EH_COMMON_INCLUDE)
## ################################################################
##
## How to build libgcj.a and libgcj.zip
##
## Objects from C++ sources in subdirs.
nat_files = $(nat_source_files:.cc=.o)
## Objects from C sources in subdirs.
c_files = $(c_source_files:.c=.o)
## Objects from Java sources in subdirs.
javao_files = $(java_source_files:.java=.o)
libgcj_a_SOURCES = prims.cc jni.cc exception.cc
EXTRA_libgcj_a_SOURCES = boehm.cc nogc.cc posix-threads.cc no-threads.cc \
$(c_source_files) $(java_source_files)
libgcj_a_DEPENDENCIES = libgcj.zip $(javao_files) $(nat_files) \
$(c_files) $(GCOBJS) $(THREADOBJS)
libgcj_a_LIBADD = $(javao_files) $(nat_files) $(c_files) $(GCOBJS) \
$(THREADOBJS)
## Make the .class files depend on the .zip file. This seems
## backwards, but is right. This doesn't catch all the .class files,
## but that is ok, because the ones it fails to pick up are defined in
## a .java file with some other class which is caught. Note that we
## only want to create headers for those files which do not have
## hand-maintained headers.
$(java_source_files:.java=.class): libgcj.zip
## We have the zip file depend on the java sources and not the class
## files, because we don't know the names of all the class files.
## FIXME: this method fails in a peculiar case: if libgcj.zip is
## up-to-date, and foo.class is removed, and bar.java is touched, then
## `make libgcj.zip' will not rebuilt foo.class. That's because
## libgcj.zip is not out-of-date with respect to foo.java.
libgcj.zip: $(java_source_files)
## This little nastiness is here so that the backquoted stuff in the
## GCJ definition can be correctly expanded, if required.
javac="$(JAVAC)"; cd $(srcdir); \
$$javac $(JCFLAGS) -classpath $(here):`/bin/pwd` -d $(here) \
$(subst $(srcdir)/,,$?)
-@rm -f libgcj.zip
## Note that we explicitly want to include directory information.
$(ZIP) -r libgcj java -n .class -i '*.class' -i '*/'
MOSTLYCLEANFILES = $(javao_files) $(nat_files) $(nat_headers) $(c_files)
CLEANFILES = libgcj.zip $(class_files)
SUFFIXES = .class .java .h
.class.o:
CLASSPATH=$(here) $(CC) -fassume-compiled $(JC1FLAGS) -c -o $@ $<
.java.o:
CLASSPATH=$(here) $(GCJ) -fassume-compiled $(JC1FLAGS) -c -o $@ $<
## This is GNU make specific. For the .o files in subdirs, use a
## special rule. The standard automake rule can't be overridden (this
## is a bug in automake), and it also won't put the .o files into
## subdirs. FIXME.
$(nat_files): %.o: %.cc
$(CXXCOMPILE) -c -o $@ $<
$(nat_files) $(GCOBJS) $(THREADOBJS) $(libgcj_a_OBJECTS): \
include/config.h $(nat_headers)
## FIXME: GNU make.
$(c_files): %.o: %.c
$(COMPILE) -c -o $@ $<
$(c_files): java/lang/fdlibm.h java/lang/ieeefp.h java/lang/mprec.h
## FIXME: GNU make.
$(javao_files): %.o: %.java
CLASSPATH=$(here) $(GCJ) -fassume-compiled $(JC1FLAGS) -c -o $@ $<
## ################################################################
##
## How to build header files.
##
.class.h:
## FIXME: GNU make specific.
$(GCJH) -classpath $(top_builddir) $(basename $<)
## Header files used when compiling some of the nat* files.
nat_headers = $(ordinary_java_source_files:.java=.h)
$(nat_headers): libgcj.zip
## Our internal main program needs to be able to create a FirstThread.
FTFRIEND = void JvRunMain (jclass klass, int argc, const char **argv)
java/lang/FirstThread.h: java/lang/FirstThread.class libgcj.zip
$(GCJH) -classpath $(top_builddir) -friend '$(FTFRIEND);' \
$(basename $<)
## ThreadGroup has a special constructor that is used when creating
## the first ThreadGroup. We need to expose this to the main program.
TGFRIEND = void JvRunMain (jclass klass, int argc, const char **argv)
java/lang/ThreadGroup.h: java/lang/ThreadGroup.class libgcj.zip
$(GCJH) -classpath $(top_builddir) -friend '$(TGFRIEND);' \
$(basename $<)
java/lang/String.h: java/lang/String.class libgcj.zip
$(GCJH) -classpath $(top_builddir) \
-friend 'jchar* _Jv_GetStringChars (jstring str);' \
-friend 'jstring* _Jv_StringFindSlot (jchar*, jint, jint);' \
-friend 'jstring* _Jv_StringGetSlot (jstring);' \
-friend 'jstring _Jv_NewStringUtf8Const (_Jv_Utf8Const* str);' \
-friend 'jstring _Jv_NewStringLatin1 (const char*, jsize);' \
-friend 'jstring _Jv_AllocString (jsize);' \
$(basename $<)
java/lang/reflect/Field.h: java/lang/reflect/Field.class libgcj.zip
$(GCJH) -classpath $(top_builddir) \
-friend 'jfieldID _Jv_FromReflectedField (java::lang::reflect::Field *);' \
-friend 'jobject _Jv_JNI_ToReflectedField (_Jv_JNIEnv*, jclass, jfieldID);' \
-friend 'java::lang::Class;' \
$(basename $<)
java/lang/reflect/Method.h: java/lang/reflect/Method.class libgcj.zip
$(GCJH) -classpath $(top_builddir) \
-friend 'jmethodID _Jv_FromReflectedMethod (java::lang::reflect::Method *);' \
-friend 'java::lang::Class;' \
$(basename $<)
## ################################################################
##
## Additional `check' targets for maintainer convenience.
##
## This is used for maintainer-check. FIXME: should set from
## configure using AC_CHECK_TOOL.
NM = nm
## Try to make sure our library doesn't stomp the namespace.
maintainer-check: libgcj.a
$(NM) libgcj.a | grep ' T ' \
## Anything with `4java' is assumed to be from .java source.
| grep -v '4java' \
## Anything with Jv is ok.
| grep -v 'Jv' \
## `terminate' and `unexpected' are part of the runtime.
| grep -v 'terminate__Fv' | grep -v 'unexpected__Fv'
## This rule can be used to see if the headers are more or less
## correct.
header-check: libgcj.zip $(nat_headers)
rm -f htest.cc; \
for h in $(nat_headers); do \
echo "#include \"$$h\"" >> htest.cc; \
done; \
$(CXXCOMPILE) -fsyntax-only htest.cc
## ################################################################
##
## The `jv-convert' program and code to rebuild the converter header
## files.
##
## it only makes sense to try to rebuild the JIS .h files on native
## systems.
if NATIVE
if MAINTAINER_MODE
noinst_PROGRAMS = gen-from-JIS
endif
endif
CONVERT_DIR = gnu/gcj/convert
jv_convert_SOURCES =
EXTRA_jv_convert_SOURCES = $(convert_source_files)
jv_convert_LDFLAGS = --main=gnu.gcj.convert.Convert
jv_convert_LINK = $(GCJ) $(JC1FLAGS) $(LDFLAGS) -o jv-convert
jv_convert_LDADD = $(convert_source_files:.java=.o) -L. $(GCLIBS) $(THREADLIBS)
jv_convert_DEPENDENCIES = $(convert_source_files:.java=.o) \
$(GCDEPS) $(THREADDEPS) libgcj.a
# The Unicode consortium does not permit re-distributing the file JIS0208.TXT.
# You can get it from ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/.
$(srcdir)/$(CONVERT_DIR)/JIS0208.h: # JIS0208.TXT
echo '/* This file is autoamtically generated from Unicode tables */' > tmp-0208; \
sed -n -e 's|\(0x....\).*0x\(..\)\(..\).*\(0x....\).*#\(.*\).$$|MAP(0x\2, 0x\3, \4) /*\5 */|p' \
<JIS0208.TXT >> tmp-0208; \
mv tmp-0208 $(srcdir)/$(CONVERT_DIR)/JIS0208.h
# The Unicode consortium does not permit re-distributing the file JIS0212.TXT.
# You can get it from ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/.
$(srcdir)/$(CONVERT_DIR)/JIS0212.h: # JIS0212.TXT
echo '/* This file is autoamtically generated from Unicode tables */' > tmp-0212; \
sed -n -e 's|0x\(..\)\(..\).*\(0x....\).*#\(.*\).$$|MAP(0x\1, 0x\2, \3) /*\4 */|p' \
<JIS0212.TXT >> tmp-0212; \
mv tmp-0212 $(srcdir)/$(CONVERT_DIR)/JIS0212.h
gen_from_JIS_SOURCES =
EXTRA_gen_from_JIS_SOURCES = $(srcdir)/$(CONVERT_DIR)/gen-from-JIS.c \
$(srcdir)/$(CONVERT_DIR)/JIS0208.h \
$(srcdir)/$(CONVERT_DIR)/JIS0212.h
gen_from_JIS_LDADD = $(CONVERT_DIR)/gen-from-JIS.o
gen_from_JIS_DEPENDENCIES = $(CONVERT_DIR)/gen-from-JIS.o
$(CONVERT_DIR)/gen-from-JIS.o: $(srcdir)/$(CONVERT_DIR)/gen-from-JIS.c \
$(srcdir)/$(CONVERT_DIR)/JIS0208.h \
$(srcdir)/$(CONVERT_DIR)/JIS0212.h
$(COMPILE) -c -o $(CONVERT_DIR)/gen-from-JIS.o \
$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.c
if NATIVE
if MAINTAINER_MODE
$(srcdir)/$(CONVERT_DIR)/JIS0208_to_Unicode.cc: ./gen-from-JIS$(EXEEXT)
./gen-from-JIS JIS0208>$(srcdir)/$(CONVERT_DIR)/JIS0208_to_Unicode.cc
$(srcdir)/$(CONVERT_DIR)/JIS0212_to_Unicode.cc: ./gen-from-JIS$(EXEEXT)
./gen-from-JIS JIS0212>$(srcdir)/$(CONVERT_DIR)/JIS0212_to_Unicode.cc
endif # MAINTAINER_MODE
endif # NATIVE
## ################################################################
##
## This section lists all the source files we care about.
##
convert_source_files = \
gnu/gcj/convert/BytesToUnicode.java \
gnu/gcj/convert/Convert.java \
gnu/gcj/convert/Input_8859_1.java \
gnu/gcj/convert/Input_EUCJIS.java \
gnu/gcj/convert/Input_UTF8.java \
gnu/gcj/convert/Output_8859_1.java \
gnu/gcj/convert/Output_JavaSrc.java \
gnu/gcj/convert/Output_UTF8.java \
gnu/gcj/convert/UnicodeToBytes.java
## List of all .java files for which the .h file is maintained by
## hand.
special_java_source_files = java/lang/Class.java java/lang/Object.java
## List of all .java files to be compiled. Please keep this list
## alphabetical. Please put files from gnu/gcj/convert into
## convert_source_files. If the .java file has a hand-maintained
## header, please list it in special_java_source_files.
ordinary_java_source_files = $(convert_source_files) \
gnu/gcj/text/BaseBreakIterator.java \
gnu/gcj/text/CharacterBreakIterator.java \
gnu/gcj/text/LineBreakIterator.java \
gnu/gcj/text/LocaleData_en.java \
gnu/gcj/text/LocaleData_en_US.java \
gnu/gcj/text/SentenceBreakIterator.java \
gnu/gcj/text/WordBreakIterator.java \
gnu/gcj/protocol/http/Connection.java \
gnu/gcj/protocol/http/Handler.java \
java/io/BufferedInputStream.java \
java/io/BufferedOutputStream.java \
java/io/BufferedReader.java \
java/io/BufferedWriter.java \
java/io/ByteArrayInputStream.java \
java/io/ByteArrayOutputStream.java \
java/io/CharArrayReader.java \
java/io/CharArrayWriter.java \
java/io/CharConversionException.java \
java/io/DataInput.java \
java/io/DataInputStream.java \
java/io/DataOutput.java \
java/io/DataOutputStream.java \
java/io/EOFException.java \
java/io/File.java \
java/io/FileDescriptor.java \
java/io/FileInputStream.java \
java/io/FileNotFoundException.java \
java/io/FileOutputStream.java \
java/io/FileReader.java \
java/io/FileWriter.java \
java/io/FilenameFilter.java \
java/io/FilterInputStream.java \
java/io/FilterOutputStream.java \
java/io/FilterReader.java \
java/io/FilterWriter.java \
java/io/IOException.java \
java/io/InputStream.java \
java/io/InputStreamReader.java \
java/io/InterruptedIOException.java \
java/io/LineNumberInputStream.java \
java/io/LineNumberReader.java \
java/io/OutputStream.java \
java/io/OutputStreamWriter.java \
java/io/PipedInputStream.java \
java/io/PipedOutputStream.java \
java/io/PipedReader.java \
java/io/PipedWriter.java \
java/io/PrintStream.java \
java/io/PrintWriter.java \
java/io/PushbackInputStream.java \
java/io/PushbackReader.java \
java/io/RandomAccessFile.java \
java/io/Reader.java \
java/io/SequenceInputStream.java \
java/io/Serializable.java \
java/io/StreamTokenizer.java \
java/io/StringBufferInputStream.java \
java/io/StringReader.java \
java/io/StringWriter.java \
java/io/SyncFailedException.java \
java/io/UTFDataFormatException.java \
java/io/UnsupportedEncodingException.java \
java/io/Writer.java \
java/lang/AbstractMethodError.java \
java/lang/ArithmeticException.java \
java/lang/ArrayIndexOutOfBoundsException.java \
java/lang/ArrayStoreException.java \
java/lang/Boolean.java \
java/lang/Byte.java \
java/lang/Character.java \
java/lang/ClassCastException.java \
java/lang/ClassCircularityError.java \
java/lang/ClassFormatError.java \
java/lang/ClassLoader.java \
java/lang/ClassNotFoundException.java \
java/lang/CloneNotSupportedException.java \
java/lang/Cloneable.java \
java/lang/Comparable.java \
java/lang/Compiler.java \
java/lang/Double.java \
java/lang/Error.java \
java/lang/Exception.java \
java/lang/ExceptionInInitializerError.java \
java/lang/FirstThread.java \
java/lang/Float.java \
java/lang/IllegalAccessError.java \
java/lang/IllegalAccessException.java \
java/lang/IllegalArgumentException.java \
java/lang/IllegalMonitorStateException.java \
java/lang/IllegalStateException.java \
java/lang/IllegalThreadStateException.java \
java/lang/IncompatibleClassChangeError.java \
java/lang/IndexOutOfBoundsException.java \
java/lang/InstantiationError.java \
java/lang/InstantiationException.java \
java/lang/Integer.java \
java/lang/InternalError.java \
java/lang/InterruptedException.java \
java/lang/LinkageError.java \
java/lang/Long.java \
java/lang/Math.java \
java/lang/NegativeArraySizeException.java \
java/lang/NoClassDefFoundError.java \
java/lang/NoSuchFieldError.java \
java/lang/NoSuchFieldException.java \
java/lang/NoSuchMethodError.java \
java/lang/NoSuchMethodException.java \
java/lang/NullPointerException.java \
java/lang/Number.java \
java/lang/NumberFormatException.java \
java/lang/OutOfMemoryError.java \
java/lang/Process.java \
java/lang/Runnable.java \
java/lang/Runtime.java \
java/lang/RuntimeException.java \
java/lang/SecurityException.java \
java/lang/SecurityManager.java \
java/lang/Short.java \
java/lang/StackOverflowError.java \
java/lang/String.java \
java/lang/StringBuffer.java \
java/lang/StringIndexOutOfBoundsException.java \
java/lang/System.java \
java/lang/Thread.java \
java/lang/ThreadDeath.java \
java/lang/ThreadGroup.java \
java/lang/Throwable.java \
java/lang/UnknownError.java \
java/lang/UnsatisfiedLinkError.java \
java/lang/UnsupportedOperationException.java \
java/lang/VerifyError.java \
java/lang/VirtualMachineError.java \
java/lang/Void.java \
java/lang/reflect/AccessibleObject.java \
java/lang/reflect/Array.java \
java/lang/reflect/Constructor.java \
java/lang/reflect/Field.java \
java/lang/reflect/InvocationTargetException.java \
java/lang/reflect/Member.java \
java/lang/reflect/Method.java \
java/lang/reflect/Modifier.java \
java/net/BindException.java \
java/net/ConnectException.java \
java/net/ContentHandler.java \
java/net/ContentHandlerFactory.java \
java/net/FileNameMap.java \
java/net/HttpURLConnection.java \
java/net/InetAddress.java \
java/net/MalformedURLException.java \
java/net/NoRouteToHostException.java \
java/net/PlainSocketImpl.java \
java/net/ProtocolException.java \
java/net/ServerSocket.java \
java/net/Socket.java \
java/net/SocketException.java \
java/net/SocketImpl.java \
java/net/SocketImplFactory.java \
java/net/URL.java \
java/net/URLConnection.java \
java/net/URLStreamHandler.java \
java/net/URLStreamHandlerFactory.java \
java/net/UnknownHostException.java \
java/net/UnknownServiceException.java \
java/text/BreakIterator.java \
java/text/CharacterIterator.java \
java/text/ChoiceFormat.java \
java/text/DateFormat.java \
java/text/DateFormatSymbols.java \
java/text/DecimalFormat.java \
java/text/DecimalFormatSymbols.java \
java/text/FieldPosition.java \
java/text/Format.java \
java/text/MessageFormat.java \
java/text/NumberFormat.java \
java/text/ParseException.java \
java/text/ParsePosition.java \
java/text/SimpleDateFormat.java \
java/text/StringCharacterIterator.java \
java/util/BitSet.java \
java/util/Calendar.java \
java/util/ConcurrentModificationException.java \
java/util/Date.java \
java/util/Dictionary.java \
java/util/EmptyStackException.java \
java/util/Enumeration.java \
java/util/EventListener.java \
java/util/EventObject.java \
java/util/GregorianCalendar.java \
java/util/Hashtable.java \
java/util/ListResourceBundle.java \
java/util/Locale.java \
java/util/MissingResourceException.java \
java/util/NoSuchElementException.java \
java/util/Observable.java \
java/util/Observer.java \
java/util/Properties.java \
java/util/Random.java \
java/util/ResourceBundle.java \
java/util/SimpleTimeZone.java \
java/util/Stack.java \
java/util/StringTokenizer.java \
java/util/TimeZone.java \
java/util/TooManyListenersException.java \
java/util/Vector.java \
java/util/zip/Adler32.java \
java/util/zip/CRC32.java \
java/util/zip/Checksum.java \
java/util/zip/Deflater.java \
java/util/zip/DeflaterOutputStream.java \
java/util/zip/ZipConstants.java \
java/util/zip/ZipEntry.java \
java/util/zip/ZipException.java \
java/util/zip/ZipFile.java \
java/util/zip/ZipOutputStream.java
java_source_files = $(ordinary_java_source_files) $(special_java_source_files)
## Math library: C, not C++
c_source_files = \
java/lang/dtoa.c java/lang/k_rem_pio2.c java/lang/s_tan.c \
java/lang/e_acos.c java/lang/k_sin.c java/lang/strtod.c \
java/lang/e_asin.c java/lang/k_tan.c java/lang/w_acos.c \
java/lang/e_atan2.c java/lang/mprec.c java/lang/w_asin.c \
java/lang/e_exp.c java/lang/s_atan.c java/lang/w_atan2.c \
java/lang/e_fmod.c java/lang/s_ceil.c java/lang/w_exp.c \
java/lang/e_log.c java/lang/s_copysign.c java/lang/w_fmod.c \
java/lang/e_pow.c java/lang/s_cos.c java/lang/w_log.c \
java/lang/e_rem_pio2.c java/lang/s_fabs.c java/lang/w_pow.c \
java/lang/e_remainder.c java/lang/s_floor.c java/lang/w_remainder.c \
java/lang/e_scalb.c java/lang/s_rint.c java/lang/w_sqrt.c \
java/lang/e_sqrt.c java/lang/s_scalbn.c java/lang/sf_rint.c \
java/lang/k_cos.c java/lang/s_sin.c
## This lists all the C++ source files in subdirectories.
nat_source_files = java/lang/natObject.cc java/lang/natClass.cc \
java/lang/natString.cc java/lang/natDouble.cc java/lang/natRuntime.cc \
java/lang/natSystem.cc java/lang/natThread.cc java/io/natFile.cc \
java/io/natFileDescriptor.cc java/util/natDate.cc \
java/util/natGregorianCalendar.cc java/lang/natFirstThread.cc \
java/lang/natCharacter.cc java/lang/natMath.cc java/lang/natFloat.cc \
java/lang/reflect/natField.cc java/net/natInetAddress.cc \
java/net/natPlainSocketImpl.cc java/lang/reflect/natMethod.cc \
java/lang/reflect/natArray.cc gnu/gcj/convert/natInput_EUCJIS.cc \
gnu/gcj/convert/JIS0208_to_Unicode.cc \
gnu/gcj/convert/JIS0212_to_Unicode.cc
## ################################################################
##
## This section is for make and multilib madness.
##
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and
# friends when we are called from the top level Makefile.
AM_MAKEFLAGS = \
"AR_FLAGS=$(AR_FLAGS)" \
"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
"CFLAGS=$(CFLAGS)" \
"CXXFLAGS=$(CXXFLAGS)" \
"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
"INSTALL=$(INSTALL)" \
"INSTALL_DATA=$(INSTALL_DATA)" \
"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
"LDFLAGS=$(LDFLAGS)" \
"LIBCFLAGS=$(LIBCFLAGS)" \
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
"MAKE=$(MAKE)" \
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
"PICFLAG=$(PICFLAG)" \
"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
"SHELL=$(SHELL)" \
"exec_prefix=$(exec_prefix)" \
"infodir=$(infodir)" \
"libdir=$(libdir)" \
"prefix=$(prefix)" \
"AR=$(AR)" \
"AS=$(AS)" \
"CC=$(CC)" \
"CXX=$(CXX)" \
"LD=$(LD)" \
"LIBCFLAGS=$(LIBCFLAGS)" \
"NM=$(NM)" \
"PICFLAG=$(PICFLAG)" \
"RANLIB=$(RANLIB)" \
"DESTDIR=$(DESTDIR)"
CONFIG_STATUS_DEPENDENCIES = $(libgcj_basedir)/configure.host
MAKEOVERRIDES=
# Multilib support variables.
MULTISRCTOP =
MULTIBUILDTOP =
MULTIDIRS =
MULTISUBDIR =
MULTIDO = true
MULTICLEAN = true
# Multilib support.
.PHONY: all-multi mostlyclean-multi clean-multi distclean-multi \
maintainer-clean-multi
all-recursive: all-multi
install-recursive: install-multi
mostlyclean-recursive: mostlyclean-multi
clean-recursive: clean-multi
distclean-recursive: distclean-multi
maintainer-clean-recursive: maintainer-clean-multi
all-multi:
$(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do
install-multi:
$(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do
mostlyclean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean
clean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean
distclean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean
maintainer-clean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean
## ################################################################
## See above.
cygnus_hack =

1309
libjava/Makefile.in Normal file

File diff suppressed because it is too large Load diff

89
libjava/acconfig.h Normal file
View file

@ -0,0 +1,89 @@
/* Name of this package. */
#undef PACKAGE
/* Version number of this package. */
#undef VERSION
/* Define this if you want runtime debugging enabled. */
#undef DEBUG
/* Define if using POSIX threads that have the mutexattr functions. */
#undef HAVE_PTHREAD_MUTEXATTR_INIT
/* Define this if you prefer size over speed for java.lang.Character. */
#undef COMPACT_CHARACTER
/* Define if you have memcpy. */
#undef HAVE_MEMCPY
/* Define if you have memmove. */
#undef HAVE_MEMMOVE
/* Define if you have strerror. */
#undef HAVE_STRERROR
/* Define if you have fsync. */
#undef HAVE_FSYNC
/* Define if you have sleep. */
#undef HAVE_SLEEP
/* Define if you have __int32_t and __uint32_t. */
#undef HAVE_INT32_DEFINED
/* Define if you're running eCos. */
#undef ECOS
/* */
#undef HAVE_LOCALTIME
/* */
#undef HAVE_MKTIME
/* Define if using POSIX threads on Linux. */
#undef LINUX_THREADS
/* Define if you have the `ctime_r' function. */
#undef HAVE_CTIME_R
/* Define if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R
/* Define if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R
/* Define if inet6 structures are defined in netinet/in.h. */
#undef HAVE_INET6
/* Define it socklen_t typedef is in sys/socket.h. */
#undef HAVE_SOCKLEN_T
/* Define if Boehm GC in use. */
#undef HAVE_BOEHM_GC
/* Define if gethostname is declared in <unistd.h>. */
#undef HAVE_GETHOSTNAME_DECL
/* Define if gethostbyname_r returns `int'. */
#undef GETHOSTBYNAME_R_RETURNS_INT
/* Define if gethostbyaddr_r returns `int'. */
#undef GETHOSTBYADDR_R_RETURNS_INT
/* Define if struct tm has tm_gmtoff field. */
#undef STRUCT_TM_HAS_GMTOFF
/* Define if global `timezone' exists. */
#undef HAVE_TIMEZONE
/* Define if you have the appropriate function. */
#undef HAVE_ACCESS
#undef HAVE_STAT
#undef HAVE_MKDIR
#undef HAVE_RENAME
#undef HAVE_RMDIR
#undef HAVE_UNLINK
#undef HAVE_REALPATH
#undef HAVE_READDIR_R
#undef HAVE_GETHOSTBYNAME_R
#undef HAVE_GETHOSTBYADDR_R

156
libjava/acinclude.m4 Normal file
View file

@ -0,0 +1,156 @@
# FIXME: We temporarily define our own version of AC_PROG_CC. This is
# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
# are probably using a cross compiler, which will not be able to fully
# link an executable. This should really be fixed in autoconf
# itself.
AC_DEFUN(LIBGCJ_CONFIGURE,
[
dnl Default to --enable-multilib
AC_ARG_ENABLE(multilib,
[ --enable-multilib build many library versions (default)],
[case "${enableval}" in
yes) multilib=yes ;;
no) multilib=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for multilib option) ;;
esac], [multilib=yes])dnl
dnl We may get other options which we dont document:
dnl --with-target-subdir, --with-multisrctop, --with-multisubdir
if test "[$]{srcdir}" = "."; then
if test "[$]{with_target_subdir}" != "."; then
libgcj_basedir="[$]{srcdir}/[$]{with_multisrctop}../$1"
else
libgcj_basedir="[$]{srcdir}/[$]{with_multisrctop}$1"
fi
else
libgcj_basedir="[$]{srcdir}/$1"
fi
AC_SUBST(libgcj_basedir)
AC_CANONICAL_HOST
dnl Still use "libjava" here to placate dejagnu.
AM_INIT_AUTOMAKE(libjava, 0.0.7)
# FIXME: We temporarily define our own version of AC_PROG_CC. This is
# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
# are probably using a cross compiler, which will not be able to fully
# link an executable. This should really be fixed in autoconf
# itself.
AC_DEFUN(LIB_AC_PROG_CC,
[AC_BEFORE([$0], [AC_PROG_CPP])dnl
AC_CHECK_PROG(CC, gcc, gcc)
if test -z "$CC"; then
AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc)
test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH])
fi
AC_PROG_CC_GNU
if test $ac_cv_prog_gcc = yes; then
GCC=yes
dnl Check whether -g works, even if CFLAGS is set, in case the package
dnl plays around with CFLAGS (such as to build both debugging and
dnl normal versions of a library), tasteless as that idea is.
ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
AC_PROG_CC_G
if test "$ac_test_CFLAGS" = set; then
CFLAGS="$ac_save_CFLAGS"
elif test $ac_cv_prog_cc_g = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-O2"
fi
else
GCC=
test "${CFLAGS+set}" = set || CFLAGS="-g"
fi
])
LIB_AC_PROG_CC
# Likewise for AC_PROG_CXX.
AC_DEFUN(LIB_AC_PROG_CXX,
[AC_BEFORE([$0], [AC_PROG_CXXCPP])dnl
AC_CHECK_PROGS(CXX, $CCC c++ g++ gcc CC cxx cc++, gcc)
test -z "$CXX" && AC_MSG_ERROR([no acceptable c++ found in \$PATH])
AC_PROG_CXX_GNU
if test $ac_cv_prog_gxx = yes; then
GXX=yes
dnl Check whether -g works, even if CXXFLAGS is set, in case the package
dnl plays around with CXXFLAGS (such as to build both debugging and
dnl normal versions of a library), tasteless as that idea is.
ac_test_CXXFLAGS="${CXXFLAGS+set}"
ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS=
AC_PROG_CXX_G
if test "$ac_test_CXXFLAGS" = set; then
CXXFLAGS="$ac_save_CXXFLAGS"
elif test $ac_cv_prog_cxx_g = yes; then
CXXFLAGS="-g -O2"
else
CXXFLAGS="-O2"
fi
else
GXX=
test "${CXXFLAGS+set}" = set || CXXFLAGS="-g"
fi
])
LIB_AC_PROG_CXX
# AC_CHECK_TOOL does AC_REQUIRE (AC_CANONICAL_BUILD). If we dont
# run it explicitly here, it will be run implicitly before
# LIBGCJ_CONFIGURE, which doesn't work because that means that it will
# be run before AC_CANONICAL_HOST.
AC_CANONICAL_BUILD
AC_CHECK_TOOL(AS, as)
AC_CHECK_TOOL(AR, ar)
AC_CHECK_TOOL(RANLIB, ranlib, :)
AC_PROG_INSTALL
AM_MAINTAINER_MODE
# We need AC_EXEEXT to keep automake happy in cygnus mode. However,
# at least currently, we never actually build a program, so we never
# need to use $(EXEEXT). Moreover, the test for EXEEXT normally
# fails, because we are probably configuring with a cross compiler
# which cant create executables. So we include AC_EXEEXT to keep
# automake happy, but we dont execute it, since we dont care about
# the result.
if false; then
AC_EXEEXT
fi
# configure.host sets the following important variables
# libgcj_cflags - host specific C compiler flags
# libgcj_cxxflags - host specific C++ compiler flags
# libgcj_javaflags - host specific Java compiler flags
libgcj_cflags=
libgcj_cxxflags=
libgcj_javaflags=
. [$]{libgcj_basedir}/configure.host
case [$]{libgcj_basedir} in
/* | [A-Za-z]:[/\\]*) libgcj_flagbasedir=[$]{libgcj_basedir} ;;
*) libgcj_flagbasedir='[$](top_builddir)/'[$]{libgcj_basedir} ;;
esac
LIBGCJ_CFLAGS="[$]{libgcj_cflags}"
LIBGCJ_CXXFLAGS="[$]{libgcj_cxxflags}"
LIBGCJ_JAVAFLAGS="[$]{libgcj_javaflags}"
AC_SUBST(LIBGCJ_CFLAGS)
AC_SUBST(LIBGCJ_CXXFLAGS)
AC_SUBST(LIBGCJ_JAVAFLAGS)
])dnl

317
libjava/aclocal.m4 vendored Normal file
View file

@ -0,0 +1,317 @@
dnl aclocal.m4 generated automatically by aclocal 1.4
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
# FIXME: We temporarily define our own version of AC_PROG_CC. This is
# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
# are probably using a cross compiler, which will not be able to fully
# link an executable. This should really be fixed in autoconf
# itself.
AC_DEFUN(LIBGCJ_CONFIGURE,
[
dnl Default to --enable-multilib
AC_ARG_ENABLE(multilib,
[ --enable-multilib build many library versions (default)],
[case "${enableval}" in
yes) multilib=yes ;;
no) multilib=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for multilib option) ;;
esac], [multilib=yes])dnl
dnl We may get other options which we dont document:
dnl --with-target-subdir, --with-multisrctop, --with-multisubdir
if test "[$]{srcdir}" = "."; then
if test "[$]{with_target_subdir}" != "."; then
libgcj_basedir="[$]{srcdir}/[$]{with_multisrctop}../$1"
else
libgcj_basedir="[$]{srcdir}/[$]{with_multisrctop}$1"
fi
else
libgcj_basedir="[$]{srcdir}/$1"
fi
AC_SUBST(libgcj_basedir)
AC_CANONICAL_HOST
dnl Still use "libjava" here to placate dejagnu.
AM_INIT_AUTOMAKE(libjava, 0.0.7)
# FIXME: We temporarily define our own version of AC_PROG_CC. This is
# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
# are probably using a cross compiler, which will not be able to fully
# link an executable. This should really be fixed in autoconf
# itself.
AC_DEFUN(LIB_AC_PROG_CC,
[AC_BEFORE([$0], [AC_PROG_CPP])dnl
AC_CHECK_PROG(CC, gcc, gcc)
if test -z "$CC"; then
AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc)
test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH])
fi
AC_PROG_CC_GNU
if test $ac_cv_prog_gcc = yes; then
GCC=yes
dnl Check whether -g works, even if CFLAGS is set, in case the package
dnl plays around with CFLAGS (such as to build both debugging and
dnl normal versions of a library), tasteless as that idea is.
ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
AC_PROG_CC_G
if test "$ac_test_CFLAGS" = set; then
CFLAGS="$ac_save_CFLAGS"
elif test $ac_cv_prog_cc_g = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-O2"
fi
else
GCC=
test "${CFLAGS+set}" = set || CFLAGS="-g"
fi
])
LIB_AC_PROG_CC
# Likewise for AC_PROG_CXX.
AC_DEFUN(LIB_AC_PROG_CXX,
[AC_BEFORE([$0], [AC_PROG_CXXCPP])dnl
AC_CHECK_PROGS(CXX, $CCC c++ g++ gcc CC cxx cc++, gcc)
test -z "$CXX" && AC_MSG_ERROR([no acceptable c++ found in \$PATH])
AC_PROG_CXX_GNU
if test $ac_cv_prog_gxx = yes; then
GXX=yes
dnl Check whether -g works, even if CXXFLAGS is set, in case the package
dnl plays around with CXXFLAGS (such as to build both debugging and
dnl normal versions of a library), tasteless as that idea is.
ac_test_CXXFLAGS="${CXXFLAGS+set}"
ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS=
AC_PROG_CXX_G
if test "$ac_test_CXXFLAGS" = set; then
CXXFLAGS="$ac_save_CXXFLAGS"
elif test $ac_cv_prog_cxx_g = yes; then
CXXFLAGS="-g -O2"
else
CXXFLAGS="-O2"
fi
else
GXX=
test "${CXXFLAGS+set}" = set || CXXFLAGS="-g"
fi
])
LIB_AC_PROG_CXX
# AC_CHECK_TOOL does AC_REQUIRE (AC_CANONICAL_BUILD). If we dont
# run it explicitly here, it will be run implicitly before
# LIBGCJ_CONFIGURE, which doesn't work because that means that it will
# be run before AC_CANONICAL_HOST.
AC_CANONICAL_BUILD
AC_CHECK_TOOL(AS, as)
AC_CHECK_TOOL(AR, ar)
AC_CHECK_TOOL(RANLIB, ranlib, :)
AC_PROG_INSTALL
AM_MAINTAINER_MODE
# We need AC_EXEEXT to keep automake happy in cygnus mode. However,
# at least currently, we never actually build a program, so we never
# need to use $(EXEEXT). Moreover, the test for EXEEXT normally
# fails, because we are probably configuring with a cross compiler
# which cant create executables. So we include AC_EXEEXT to keep
# automake happy, but we dont execute it, since we dont care about
# the result.
if false; then
AC_EXEEXT
fi
# configure.host sets the following important variables
# libgcj_cflags - host specific C compiler flags
# libgcj_cxxflags - host specific C++ compiler flags
# libgcj_javaflags - host specific Java compiler flags
libgcj_cflags=
libgcj_cxxflags=
libgcj_javaflags=
. [$]{libgcj_basedir}/configure.host
case [$]{libgcj_basedir} in
/* | [A-Za-z]:[/\\]*) libgcj_flagbasedir=[$]{libgcj_basedir} ;;
*) libgcj_flagbasedir='[$](top_builddir)/'[$]{libgcj_basedir} ;;
esac
LIBGCJ_CFLAGS="[$]{libgcj_cflags}"
LIBGCJ_CXXFLAGS="[$]{libgcj_cxxflags}"
LIBGCJ_JAVAFLAGS="[$]{libgcj_javaflags}"
AC_SUBST(LIBGCJ_CFLAGS)
AC_SUBST(LIBGCJ_CXXFLAGS)
AC_SUBST(LIBGCJ_JAVAFLAGS)
])dnl
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.
# serial 1
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN(AM_INIT_AUTOMAKE,
[AC_REQUIRE([AC_PROG_INSTALL])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_SUBST(VERSION)
dnl test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
#
# Check to make sure that the build environment is sane.
#
AC_DEFUN(AM_SANITY_CHECK,
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "[$]*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "[$]*" != "X $srcdir/configure conftestfile" \
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "[$]2" = conftestfile
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
rm -f conftest*
AC_MSG_RESULT(yes)])
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
AC_DEFUN(AM_MISSING_PROG,
[AC_MSG_CHECKING(for working $2)
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if ($2 --version) < /dev/null > /dev/null 2>&1; then
$1=$2
AC_MSG_RESULT(found)
else
$1="$3/missing $2"
AC_MSG_RESULT(missing)
fi
AC_SUBST($1)])
# Add --enable-maintainer-mode option to configure.
# From Jim Meyering
# serial 1
AC_DEFUN(AM_MAINTAINER_MODE,
[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
dnl maintainer-mode is disabled by default
AC_ARG_ENABLE(maintainer-mode,
[ --enable-maintainer-mode enable make rules and dependencies not useful
(and sometimes confusing) to the casual installer],
USE_MAINTAINER_MODE=$enableval,
USE_MAINTAINER_MODE=no)
AC_MSG_RESULT($USE_MAINTAINER_MODE)
AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes)
MAINT=$MAINTAINER_MODE_TRUE
AC_SUBST(MAINT)dnl
]
)
# Define a conditional.
AC_DEFUN(AM_CONDITIONAL,
[AC_SUBST($1_TRUE)
AC_SUBST($1_FALSE)
if $2; then
$1_TRUE=
$1_FALSE='#'
else
$1_TRUE='#'
$1_FALSE=
fi])
# Like AC_CONFIG_HEADER, but automatically create stamp file.
AC_DEFUN(AM_CONFIG_HEADER,
[AC_PREREQ([2.12])
AC_CONFIG_HEADER([$1])
dnl When config.status generates a header, we must update the stamp-h file.
dnl This file resides in the same directory as the config header
dnl that is generated. We must strip everything past the first ":",
dnl and everything past the last "/".
AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
<<am_indx=1
for am_file in <<$1>>; do
case " <<$>>CONFIG_HEADERS " in
*" <<$>>am_file "*<<)>>
echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
;;
esac
am_indx=`expr "<<$>>am_indx" + 1`
done<<>>dnl>>)
changequote([,]))])

367
libjava/boehm.cc Normal file
View file

@ -0,0 +1,367 @@
// boehm.cc - interface between libjava and Boehm GC.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#include <stdio.h>
#include <cni.h>
#include <java/lang/Class.h>
#include <jvm.h>
#include <java-field.h>
// We need to include gc_priv.h. However, it tries to include
// config.h if it hasn't already been included. So we force the
// inclusion of the Boehm config.h.
extern "C"
{
#include <boehm-config.h>
#include <gc_priv.h>
#include <gc_mark.h>
// These aren't declared in any Boehm GC header.
void GC_finalize_all (void);
ptr_t GC_debug_generic_malloc (size_t size, int k, GC_EXTRA_PARAMS);
};
// FIXME: this should probably be defined in some GC header.
#ifdef GC_DEBUG
# define GC_GENERIC_MALLOC(Size, Type) \
GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
#else
# define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
#endif
// We must check for plausibility ourselves.
#define MAYBE_MARK(Obj, Top, Limit, Source, Exit) \
if ((ptr_t) (Obj) >= GC_least_plausible_heap_addr \
&& (ptr_t) (Obj) <= GC_greatest_plausible_heap_addr) \
PUSH_CONTENTS (Obj, Top, Limit, Source, Exit)
#define ObjectClass _CL_Q34java4lang6Object
extern java::lang::Class ObjectClass;
#define ClassClass _CL_Q34java4lang5Class
extern java::lang::Class ClassClass;
// Nonzero if this module has been initialized.
static int initialized = 0;
// `kind' index used when allocating Java objects.
static int obj_kind_x;
// `kind' index used when allocating Java arrays.
static int array_kind_x;
// Freelist used for Java objects.
static ptr_t *obj_free_list;
// Freelist used for Java arrays.
static ptr_t *array_free_list;
// This is called by the GC during the mark phase. It marks a Java
// object. We use `void *' arguments and return, and not what the
// Boehm GC wants, to avoid pollution in our headers.
void *
_Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
{
mse *mark_stack_ptr = (mse *) msp;
mse *mark_stack_limit = (mse *) msl;
jobject obj = (jobject) addr;
_Jv_VTable *dt = *(_Jv_VTable **) addr;
// We check this in case a GC occurs before the vtbl is set. FIXME:
// should use allocation lock while initializing object.
if (! dt)
return mark_stack_ptr;
jclass klass = dt->clas;
// Every object has a sync_info pointer.
word w = (word) obj->sync_info;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o1label);
// Mark the object's class.
w = (word) klass;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o2label);
if (klass == &ClassClass)
{
jclass c = (jclass) addr;
w = (word) c->next;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c2label);
w = (word) c->name;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c3label);
w = (word) c->superclass;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c4label);
for (int i = 0; i < c->constants.size; ++i)
{
w = (word) c->constants.data[i];
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5label);
}
// If the class is an array, then the methods field holds a
// pointer to the element class. If the class is primitive,
// then the methods field holds a pointer to the array class.
w = (word) c->methods;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c6label);
if (! c->isArray() && ! c->isPrimitive())
{
// Scan each method in the cases where `methods' really
// points to a methods structure.
for (int i = 0; i < c->method_count; ++i)
{
w = (word) c->methods[i].name;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
cm1label);
w = (word) c->methods[i].signature;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
cm2label);
// FIXME: `ncode' entry?
}
}
// Mark all the fields.
w = (word) c->fields;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8label);
for (int i = 0; i < c->field_count; ++i)
{
#ifndef COMPACT_FIELDS
w = (word) c->fields[i].name;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8alabel);
#endif
w = (word) c->fields[i].type;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8blabel);
}
w = (word) c->vtable;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c9label);
w = (word) c->interfaces;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cAlabel);
for (int i = 0; i < c->interface_count; ++i)
{
w = (word) c->interfaces[i];
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cClabel);
}
w = (word) c->loader;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cBlabel);
}
else
{
// NOTE: each class only holds information about the class
// itself. So we must do the marking for the entire inheritance
// tree in order to mark all fields. FIXME: what about
// interfaces? We skip Object here, because Object only has a
// sync_info, and we handled that earlier.
// Note: occasionally `klass' can be null. For instance, this
// can happen if a GC occurs between the point where an object
// is allocated and where the vtbl slot is set.
while (klass && klass != &ObjectClass)
{
jfieldID field = JvGetFirstInstanceField (klass);
jint max = JvNumInstanceFields (klass);
for (int i = 0; i < max; ++i)
{
if (JvFieldIsRef (field))
{
jobject val = JvGetObjectField (obj, field);
w = (word) val;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit,
obj, elabel);
}
field = field->getNextInstanceField ();
}
klass = klass->getSuperclass();
}
}
return mark_stack_ptr;
}
// This is called by the GC during the mark phase. It marks a Java
// array (of objects). We use `void *' arguments and return, and not
// what the Boehm GC wants, to avoid pollution in our headers.
void *
_Jv_MarkArray (void *addr, void *msp, void *msl, void * /*env*/)
{
mse *mark_stack_ptr = (mse *) msp;
mse *mark_stack_limit = (mse *) msl;
jobjectArray array = (jobjectArray) addr;
_Jv_VTable *dt = *(_Jv_VTable **) addr;
// We check this in case a GC occurs before the vtbl is set. FIXME:
// should use allocation lock while initializing object.
if (! dt)
return mark_stack_ptr;
jclass klass = dt->clas;
// Every object has a sync_info pointer.
word w = (word) array->sync_info;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, array, e1label);
// Mark the object's class.
w = (word) klass;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o2label);
for (int i = 0; i < JvGetArrayLength (array); ++i)
{
jobject obj = elements (array)[i];
w = (word) obj;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, array, e2label);
}
return mark_stack_ptr;
}
// Allocate space for a new Java object. FIXME: this might be the
// wrong interface; we might prefer to pass in the object type as
// well. It isn't important for this collector, but it might be for
// other collectors.
void *
_Jv_AllocObj (jsize size)
{
return GC_GENERIC_MALLOC (size, obj_kind_x);
}
// Allocate space for a new Java array. FIXME: again, this might be
// the wrong interface.
void *
_Jv_AllocArray (jsize size)
{
return GC_GENERIC_MALLOC (size, array_kind_x);
}
// Allocate some space that is known to be pointer-free.
void *
_Jv_AllocBytes (jsize size)
{
return GC_GENERIC_MALLOC (size, PTRFREE);
}
static void
call_finalizer (GC_PTR obj, GC_PTR client_data)
{
_Jv_FinalizerFunc *fn = (_Jv_FinalizerFunc *) client_data;
jobject jobj = (jobject) obj;
(*fn) (jobj);
}
void
_Jv_RegisterFinalizer (void *object, _Jv_FinalizerFunc *meth)
{
GC_REGISTER_FINALIZER_NO_ORDER (object, call_finalizer, meth,
NULL, NULL);
}
void
_Jv_RunFinalizers (void)
{
GC_invoke_finalizers ();
}
void
_Jv_RunAllFinalizers (void)
{
GC_finalize_all ();
}
void
_Jv_RunGC (void)
{
GC_gcollect ();
}
long
_Jv_GCTotalMemory (void)
{
return GC_get_heap_size ();
}
/* Sum size of each hblk. */
static void
sum_blocks (struct hblk *h, word arg)
{
long *sump = (long *) arg;
/* This evil computation is from boehm-gc/checksums.c. */
hdr *hhdr = HDR (h);
int bytes = WORDS_TO_BYTES (hhdr->hb_sz);
bytes += HDR_BYTES + HBLKSIZE - 1;
bytes &= ~ (HBLKSIZE - 1);
*sump += bytes;
}
/* This turns out to be expensive to implement. For now, we don't
care. We could make it less expensive, perhaps, but that would
require some changes to the collector. */
long
_Jv_GCFreeMemory (void)
{
long sum = 0;
GC_apply_to_all_blocks (sum_blocks, &sum);
return sum;
}
void
_Jv_InitGC (void)
{
int proc;
DCL_LOCK_STATE;
DISABLE_SIGNALS ();
LOCK ();
if (initialized)
{
UNLOCK ();
ENABLE_SIGNALS ();
return;
}
initialized = 1;
// Set up state for marking and allocation of Java objects.
obj_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
* sizeof (ptr_t),
PTRFREE);
memset (obj_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
proc = GC_n_mark_procs++;
GC_mark_procs[proc] = (mark_proc) _Jv_MarkObj;
obj_kind_x = GC_n_kinds++;
GC_obj_kinds[obj_kind_x].ok_freelist = obj_free_list;
GC_obj_kinds[obj_kind_x].ok_reclaim_list = 0;
GC_obj_kinds[obj_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
GC_obj_kinds[obj_kind_x].ok_relocate_descr = FALSE;
GC_obj_kinds[obj_kind_x].ok_init = TRUE;
// Set up state for marking and allocation of arrays of Java
// objects.
array_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
* sizeof (ptr_t),
PTRFREE);
memset (array_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
proc = GC_n_mark_procs++;
GC_mark_procs[proc] = (mark_proc) _Jv_MarkArray;
array_kind_x = GC_n_kinds++;
GC_obj_kinds[array_kind_x].ok_freelist = array_free_list;
GC_obj_kinds[array_kind_x].ok_reclaim_list = 0;
GC_obj_kinds[array_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
GC_obj_kinds[array_kind_x].ok_relocate_descr = FALSE;
GC_obj_kinds[array_kind_x].ok_init = TRUE;
UNLOCK ();
ENABLE_SIGNALS ();
}

965
libjava/chartables.pl Normal file
View file

@ -0,0 +1,965 @@
# chartables.pl - A perl program to generate tables for use by the
# Character class.
# Copyright (C) 1998, 1999 Cygnus Solutions
#
# This file is part of libjava.
#
# This software is copyrighted work licensed under the terms of the
# Libjava License. Please consult the file "LIBJAVA_LICENSE" for
# details.
# This program requires a `unidata.txt' file of the form distributed
# on the Unicode 2.0 CD ROM. Or, get it more conveniently here:
# ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData-Latest.txt
# Version `2.1.8' of this file was last used to update the Character class.
# Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
# "The Java Language Specification", ISBN 0-201-63451-1
# plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
# Usage: perl chartables.pl [-n] UnicodeData-VERSION.txt
# If this exits with nonzero status, then you must investigate the
# cause of the problem.
# Diagnostics and other information to stderr.
# This creates the new include/java-chartables.h and
# include/java-chardecomp.h files directly.
# With -n, the files are not created, but all processing
# still occurs.
# Fields in the table.
$CODE = 0;
$NAME = 1;
$CATEGORY = 2;
$DECOMPOSITION = 5;
$DECIMAL = 6;
$DIGIT = 7;
$NUMERIC = 8;
$UPPERCASE = 12;
$LOWERCASE = 13;
$TITLECASE = 14;
# A special case.
$TAMIL_DIGIT_ONE = 0x0be7;
$TAMIL_DIGIT_NINE = 0x0bef;
# These are endpoints of legitimate gaps in the tables.
$CJK_IDEOGRAPH_END = 0x9fa5;
$HANGUL_END = 0xd7a3;
$HIGH_SURROGATE_END = 0xdb7f;
$PRIVATE_HIGH_SURROGATE_END = 0xdbff;
$LOW_SURROGATE_END = 0xdfff;
$PRIVATE_END = 0xf8ff;
%title_to_upper = ();
%title_to_lower = ();
%numerics = ();
%name = ();
@digit_start = ();
@digit_end = ();
@space_start = ();
@space_end = ();
# @letter_start = ();
# @letter_end = ();
@all_start = ();
@all_end = ();
@all_cats = ();
@upper_start = ();
@upper_end = ();
@upper_map = ();
%upper_anom = ();
@lower_start = ();
@lower_end = ();
@lower_map = ();
%lower_anom = ();
@attributes = ();
# There are a few characters which actually need two attributes.
# These are special-cased.
$ROMAN_START = 0x2160;
$ROMAN_END = 0x217f;
%second_attributes = ();
$prevcode = -1;
$status = 0;
%category_map =
(
'Mn' => 'NON_SPACING_MARK',
'Mc' => 'COMBINING_SPACING_MARK',
'Me' => 'ENCLOSING_MARK',
'Nd' => 'DECIMAL_DIGIT_NUMBER',
'Nl' => 'LETTER_NUMBER',
'No' => 'OTHER_NUMBER',
'Zs' => 'SPACE_SEPARATOR',
'Zl' => 'LINE_SEPARATOR',
'Zp' => 'PARAGRAPH_SEPARATOR',
'Cc' => 'CONTROL',
'Cf' => 'FORMAT',
'Cs' => 'SURROGATE',
'Co' => 'PRIVATE_USE',
'Cn' => 'UNASSIGNED',
'Lu' => 'UPPERCASE_LETTER',
'Ll' => 'LOWERCASE_LETTER',
'Lt' => 'TITLECASE_LETTER',
'Lm' => 'MODIFIER_LETTER',
'Lo' => 'OTHER_LETTER',
'Pc' => 'CONNECTOR_PUNCTUATION',
'Pd' => 'DASH_PUNCTUATION',
'Ps' => 'START_PUNCTUATION',
'Pe' => 'END_PUNCTUATION',
'Pi' => 'START_PUNCTUATION',
'Pf' => 'END_PUNCTUATION',
'Po' => 'OTHER_PUNCTUATION',
'Sm' => 'MATH_SYMBOL',
'Sc' => 'CURRENCY_SYMBOL',
'Sk' => 'MODIFIER_SYMBOL',
'So' => 'OTHER_SYMBOL'
);
# These maps characters to their decompositions.
%canonical_decomposition = ();
%full_decomposition = ();
# Handle `-n' and open output files.
local ($f1, $f2) = ('include/java-chartables.h',
'include/java-chardecomp.h');
if ($ARGV[0] eq '-n')
{
shift @ARGV;
$f1 = '/dev/null';
$f2 = '/dev/null';
}
open (CHARTABLE, "> $f1");
open (DECOMP, "> $f2");
# Process the Unicode file.
while (<>)
{
chop;
# Specify a limit for split so that we pick up trailing fields.
# We make the limit larger than we need, to catch the case where
# there are extra fields.
@fields = split (';', $_, 30);
# Convert code to number.
$ncode = hex ($fields[$CODE]);
if ($#fields != 14)
{
print STDERR ("Entry for \\u", $fields[$CODE],
" has wrong number of fields: ", $#fields, "\n");
}
$name{$fields[$CODE]} = $fields[$NAME];
# If we've found a gap in the table, fill it in.
if ($ncode != $prevcode + 1)
{
&process_gap (*fields, $prevcode, $ncode);
}
&process_char (*fields, $ncode);
$prevcode = $ncode;
}
if ($prevcode != 0xffff)
{
# Setting of `fields' parameter doesn't matter here.
&process_gap (*fields, $prevcode, 0x10000);
}
print CHARTABLE "// java-chartables.h - Character tables for java.lang.Character -*- c++ -*-\n\n";
print CHARTABLE "#ifndef __JAVA_CHARTABLES_H__\n";
print CHARTABLE "#define __JAVA_CHARTABLES_H__\n\n";
print CHARTABLE "// These tables are automatically generated by the chartables.pl\n";
print CHARTABLE "// script. DO NOT EDIT the tables. Instead, fix the script\n";
print CHARTABLE "// and run it again.\n\n";
print CHARTABLE "// This file should only be included by natCharacter.cc\n\n";
$bytes = 0;
# Titlecase mapping tables.
if ($#title_to_lower != $#title_to_upper)
{
# If this fails we need to reimplement toTitleCase.
print STDERR "titlecase mappings have different sizes\n";
$status = 1;
}
# Also ensure that the tables are entirely parallel.
foreach $key (sort keys %title_to_lower)
{
if (! defined $title_to_upper{$key})
{
print STDERR "titlecase mappings have different entries\n";
$status = 1;
}
}
&print_single_map ("title_to_lower_table", %title_to_lower);
&print_single_map ("title_to_upper_table", %title_to_upper);
print CHARTABLE "#ifdef COMPACT_CHARACTER\n\n";
printf CHARTABLE "#define TAMIL_DIGIT_ONE 0x%04x\n\n", $TAMIL_DIGIT_ONE;
# All numeric values.
&print_numerics;
# Digits only.
&print_block ("digit_table", *digit_start, *digit_end);
# Space characters.
&print_block ("space_table", *space_start, *space_end);
# Letters. We used to generate a separate letter table. But this
# doesn't really seem worthwhile. Simply using `all_table' saves us
# about 800 bytes, and only adds 3 table probes to isLetter.
# &print_block ("letter_table", *letter_start, *letter_end);
# Case tables.
&print_case_table ("upper", *upper_start, *upper_end, *upper_map, *upper_anom);
&print_case_table ("lower", *lower_start, *lower_end, *lower_map, *lower_anom);
# Everything else.
&print_all_block (*all_start, *all_end, *all_cats);
print CHARTABLE "#else /* COMPACT_CHARACTER */\n\n";
printf CHARTABLE "#define ROMAN_START 0x%04x\n", $ROMAN_START;
printf CHARTABLE "#define ROMAN_END 0x%04x\n\n", $ROMAN_END;
&print_fast_tables (*all_start, *all_end, *all_cats,
*attributes, *second_attributes);
print CHARTABLE "#endif /* COMPACT_CHARACTER */\n\n";
print CHARTABLE "#endif /* __JAVA_CHARTABLES_H__ */\n";
printf STDERR "Approximately %d bytes of data generated (compact case)\n",
$bytes;
# Now generate decomposition tables.
printf DECOMP "// java-chardecomp.h - Decomposition character tables -*- c++ -*-\n\n";
printf DECOMP "#ifndef __JAVA_CHARDECOMP_H__\n";
printf DECOMP "#define __JAVA_CHARDECOMP_H__\n\n";
print DECOMP "// These tables are automatically generated by the chartables.pl\n";
print DECOMP "// script. DO NOT EDIT the tables. Instead, fix the script\n";
print DECOMP "// and run it again.\n\n";
print DECOMP "// This file should only be included by natCollator.cc\n\n";
print DECOMP "struct decomp_entry\n{\n";
print DECOMP " jchar key;\n";
print DECOMP " const char *value;\n";
print DECOMP "};\n\n";
&write_decompositions;
printf DECOMP "#endif /* __JAVA_CHARDECOMP_H__ */\n";
close (CHARTABLE);
close (DECOMP);
exit $status;
# Process a gap in the space.
sub process_gap
{
local (*fields, $prevcode, $ncode) = @_;
local (@gap_fields, $i);
if ($ncode == $CJK_IDEOGRAPH_END
|| $ncode == $HANGUL_END
|| $ncode == $HIGH_SURROGATE_END
|| $ncode == $PRIVATE_HIGH_SURROGATE_END
|| $ncode == $LOW_SURROGATE_END
|| $ncode == $PRIVATE_END)
{
# The characters in the gap we just found are known to
# have the same properties as the character at the end of
# the gap.
@gap_fields = @fields;
}
else
{
# This prints too much to be enabled.
# print STDERR "Gap found at \\u", $fields[$CODE], "\n";
@gap_fields = ('', '', 'Cn', '', '', '', '', '', '', '', '',
'', '', '', '');
}
for ($i = $prevcode + 1; $i < $ncode; ++$i)
{
$gap_fields[$CODE] = sprintf ("%04x", $i);
$gap_fields[$NAME] = "CHARACTER " . $gap_fields[$CODE];
&process_char (*gap_fields, $i);
}
}
# Process a single character.
sub process_char
{
local (*fields, $ncode) = @_;
if ($fields[$DECOMPOSITION] ne '')
{
&add_decomposition ($ncode, $fields[$DECOMPOSITION]);
}
# If this is a titlecase character, mark it.
if ($fields[$CATEGORY] eq 'Lt')
{
$title_to_upper{$fields[$CODE]} = $fields[$UPPERCASE];
$title_to_lower{$fields[$CODE]} = $fields[$LOWERCASE];
}
else
{
# For upper and lower case mappings, we try to build compact
# tables that map range onto range. We specifically want to
# avoid titlecase characters. Java specifies a range check to
# make sure the character is not between 0x2000 and 0x2fff.
# We avoid that here because we need to generate table entries
# -- toLower and toUpper still work in that range.
if ($fields[$UPPERCASE] eq ''
&& ($fields[$LOWERCASE] ne ''
|| $fields[$NAME] =~ /CAPITAL (LETTER|LIGATURE)/))
{
if ($fields[$LOWERCASE] ne '')
{
&update_case_block (*upper_start, *upper_end, *upper_map,
$fields[$CODE], $fields[$LOWERCASE]);
&set_attribute ($ncode, hex ($fields[$LOWERCASE]));
}
else
{
$upper_anom{$fields[$CODE]} = 1;
}
}
elsif ($fields[$LOWERCASE] ne '')
{
print STDERR ("Java missed upper case char \\u",
$fields[$CODE], "\n");
}
elsif ($fields[$CATEGORY] eq 'Lu')
{
# This case is for letters which are marked as upper case
# but for which there is no lower case equivalent. For
# instance, LATIN LETTER YR.
}
if ($fields[$LOWERCASE] eq ''
&& ($fields[$UPPERCASE] ne ''
|| $fields[$NAME] =~ /SMALL (LETTER|LIGATURE)/))
{
if ($fields[$UPPERCASE] ne '')
{
&update_case_block (*lower_start, *lower_end, *lower_map,
$fields[$CODE], $fields[$UPPERCASE]);
&set_attribute ($ncode, hex ($fields[$UPPERCASE]));
}
else
{
$lower_anom{$fields[$CODE]} = 1;
}
}
elsif ($fields[$UPPERCASE] ne '')
{
print STDERR ("Java missed lower case char \\u",
$fields[$CODE], "\n");
}
elsif ($fields[$CATEGORY] eq 'Ll')
{
# This case is for letters which are marked as lower case
# but for which there is no upper case equivalent. For
# instance, FEMININE ORDINAL INDICATOR.
}
}
# If we have a non-decimal numeric value, add it to the list.
if ($fields[$CATEGORY] eq 'Nd'
&& ($ncode < 0x2000 || $ncode > 0x2fff)
&& $fields[$NAME] =~ /DIGIT/)
{
# This is a digit character that is handled elsewhere.
}
elsif ($fields[$DIGIT] ne '' || $fields[$NUMERIC] ne '')
{
# Do a simple check.
if ($fields[$DECIMAL] ne '')
{
# This catches bugs in an earlier implementation of
# chartables.pl. Now it is here for historical interest
# only.
# print STDERR ("Character \u", $fields[$CODE],
# " would have been missed as digit\n");
}
local ($val) = $fields[$DIGIT];
$val = $fields[$NUMERIC] if $val eq '';
local ($ok) = 1;
# If we have a value which is not a positive integer, then we
# set the value to -2 to make life easier for
# Character.getNumericValue.
if ($val !~ m/^[0-9]+$/)
{
if ($fields[$CATEGORY] ne 'Nl'
&& $fields[$CATEGORY] ne 'No')
{
# This shows a few errors in the Unicode table. These
# characters have a missing Numeric field, and the `N'
# for the mirrored field shows up there instead. I
# reported these characters to errata@unicode.org on
# Thu Sep 10 1998. They said it will be fixed in the
# 2.1.6 release of the tables.
print STDERR ("Character \u", $fields[$CODE],
" has value but is not numeric; val = '",
$val, "'\n");
# We skip these.
$ok = 0;
}
$val = "-2";
}
if ($ok)
{
$numerics{$fields[$CODE]} = $val;
&set_attribute ($ncode, $val);
}
}
# We build a table that lists ranges of ordinary decimal values.
# At each step we make sure that the digits are in the correct
# order, with no holes, as this is assumed by Character. If this
# fails, reimplementation is required. This implementation
# dovetails nicely with the Java Spec, which has strange rules for
# what constitutes a decimal value. In particular the Unicode
# name must contain the word `DIGIT'. The spec doesn't directly
# say that digits must have type `Nd' (or that their value must an
# integer), but that can be inferred from the list of digits in
# the book(s). Currently the only Unicode characters whose name
# includes `DIGIT' which would not fit are the Tibetan "half"
# digits.
if ($fields[$CATEGORY] eq 'Nd')
{
if (($ncode < 0x2000 || $ncode > 0x2fff)
&& $fields[$NAME] =~ /DIGIT/)
{
&update_digit_block (*digit_start, *digit_end, $fields[$CODE],
$fields[$DECIMAL]);
&set_attribute ($ncode, $fields[$DECIMAL]);
}
else
{
# If this fails then Character.getType will fail. We
# assume that things in `digit_table' are the only
# category `Nd' characters.
print STDERR ("Character \u", $fields[$CODE],
" is class Nd but not in digit table\n");
$status = 1;
}
}
# Keep track of space characters.
if ($fields[$CATEGORY] =~ /Z[slp]/)
{
&update_block (*space_start, *space_end, $fields[$CODE]);
}
# Keep track of letters.
# if ($fields[$CATEGORY] =~ /L[ultmo]/)
# {
# &update_letter_block (*letter_start, *letter_end, $fields[$CODE],
# $fields[$CATEGORY]);
# }
# Keep track of all characters. You might think we wouldn't have
# to do this for uppercase letters, or other characters we already
# "classify". The problem is that this classification is
# different. E.g., \u216f is uppercase by Java rules, but is a
# LETTER_NUMBER here.
&update_all_block (*all_start, *all_end, *all_cats,
$fields[$CODE], $fields[$CATEGORY]);
}
# Called to add a new decomposition.
sub add_decomposition
{
local ($ncode, $value) = @_;
local ($is_full) = 0;
local ($first) = 1;
local (@decomp) = ();
foreach (split (' ', $value))
{
if ($first && /^\<.*\>$/)
{
$is_full = 1;
}
else
{
push (@decomp, hex ($_));
}
$first = 0;
}
# We pack the value into a string because this means we can stick
# with Perl 4 features.
local ($s) = pack "I*", @decomp;
if ($is_full)
{
$full_decomposition{$ncode} = $s;
}
else
{
$canonical_decomposition{$ncode} = $s;
}
}
# Write a single decomposition table.
sub write_single_decomposition
{
local ($name, $is_canon, %table) = @_;
printf DECOMP "static const decomp_entry ${name}_decomposition[] =\n{\n";
local ($key, @expansion, $char);
local ($first_line) = 1;
for ($key = 0; $key <= 65535; ++$key)
{
next if ! defined $table{$key};
printf DECOMP ",\n"
unless $first_line;
$first_line = 0;
printf DECOMP " { 0x%04x, \"", $key;
# We represent the expansion as a series of bytes, terminated
# with a double nul. This is ugly, but relatively
# space-efficient. Most expansions are short, but there are a
# few that are very long (e.g. \uFDFA). This means that if we
# chose a fixed-space representation we would waste a lot of
# space.
@expansion = unpack "I*", $table{$key};
foreach $char (@expansion)
{
printf DECOMP "\\x%02x\\x%02x", ($char / 256), ($char % 256);
}
printf DECOMP "\" }";
}
printf DECOMP "\n};\n\n";
}
sub write_decompositions
{
&write_single_decomposition ('canonical', 1, %canonical_decomposition);
&write_single_decomposition ('full', 0, %full_decomposition);
}
# We represent a block of characters with a pair of lists. This
# function updates the pair to account for the new character. Returns
# 1 if we added to the old block, 0 otherwise.
sub update_block
{
local (*start, *end, $char) = @_;
local ($nchar) = hex ($char);
local ($count) = $#end;
if ($count >= 0 && $end[$count] == $nchar - 1)
{
++$end[$count];
return 1;
}
else
{
++$count;
$start[$count] = $nchar;
$end[$count] = $nchar;
}
return 0;
}
# Return true if we will be appending this character to the end of the
# existing block.
sub block_append_p
{
local (*end, $char) = @_;
return $#end >= 0 && $end[$#end] == $char - 1;
}
# This updates the digit block. This table is much like an ordinary
# block, but it has an extra constraint.
sub update_digit_block
{
local (*start, *end, $char, $value) = @_;
&update_block ($start, $end, $char);
local ($nchar) = hex ($char);
# We want to make sure that the new digit's value is correct for
# its place in the block. However, we special-case Tamil digits,
# since Tamil does not have a digit `0'.
local ($count) = $#start;
if (($nchar < $TAMIL_DIGIT_ONE || $nchar > $TAMIL_DIGIT_NINE)
&& $nchar - $start[$count] != $value)
{
# If this fails then Character.digit_value will be wrong.
print STDERR "Character \\u", $char, " violates digit constraint\n";
$status = 1;
}
}
# Update letter table. We could be smart about avoiding upper or
# lower case letters, but it is much simpler to just track them all.
sub update_letter_block
{
local (*start, *end, $char, $category) = @_;
&update_block (*start, *end, $char);
}
# Update `all' table. This table holds all the characters we don't
# already categorize for other reasons. FIXME: if a given type has
# very few characters, we should just inline the code. E.g., there is
# only one paragraph separator.
sub update_all_block
{
local (*start, *end, *cats, $char, $category) = @_;
local ($nchar) = hex ($char);
local ($count) = $#end;
if ($count >= 0
&& $end[$count] == $nchar - 1
&& $cats[$count] eq $category)
{
++$end[$count];
}
else
{
++$count;
$start[$count] = $nchar;
$end[$count] = $nchar;
$cats[$count] = $category;
}
}
# Update a case table. We handle case tables specially because we
# want to map (e.g.) a block of uppercase characters directly onto the
# corresponding block of lowercase characters. Therefore we generate
# a new entry when the block would no longer map directly.
sub update_case_block
{
local (*start, *end, *map, $char, $mapchar) = @_;
local ($nchar) = hex ($char);
local ($nmap) = hex ($mapchar);
local ($count) = $#end;
if ($count >= 0
&& $end[$count] == $nchar - 1
&& $nchar - $start[$count] == $nmap - $map[$count])
{
++$end[$count];
}
else
{
++$count;
$start[$count] = $nchar;
$end[$count] = $nchar;
$map[$count] = $nmap;
}
}
# Set the attribute value for the character. Each character can have
# only one attribute.
sub set_attribute
{
local ($ncode, $attr) = @_;
if ($attributes{$ncode} ne '' && $attributes{$ncode} ne $attr)
{
if ($ncode >= $ROMAN_START && $ncode <= $ROMAN_END)
{
$second_attributes{$ncode} = $attr;
}
else
{
printf STDERR "character \\u%04x already has attribute\n", $ncode;
}
}
# Attributes can be interpreted as unsigned in some situations,
# so we check against 65535. This could cause errors -- we need
# to check the interpretation here.
elsif ($attr < -32768 || $attr > 65535)
{
printf STDERR "attribute out of range for character \\u%04x\n", $ncode;
}
else
{
$attributes{$ncode} = $attr;
}
}
# Print a block table.
sub print_block
{
local ($title, *start, *end) = @_;
print CHARTABLE "static const jchar ", $title, "[][2] =\n";
print CHARTABLE " {\n";
local ($i) = 0;
while ($i <= $#start)
{
print CHARTABLE " { ";
&print_char ($start[$i]);
print CHARTABLE ", ";
&print_char ($end[$i]);
print CHARTABLE " }";
print CHARTABLE "," if ($i != $#start);
print CHARTABLE "\n";
++$i;
$bytes += 4; # Two bytes per char.
}
print CHARTABLE " };\n\n";
}
# Print the numerics table.
sub print_numerics
{
local ($i, $key, $count, @keys);
$i = 0;
@keys = sort keys %numerics;
$count = @keys;
print CHARTABLE "static const jchar numeric_table[] =\n";
print CHARTABLE " { ";
foreach $key (@keys)
{
&print_char (hex ($key));
++$i;
print CHARTABLE ", " if $i < $count;
# Print 5 per line.
print CHARTABLE "\n " if ($i % 5 == 0);
$bytes += 2; # One character.
}
print CHARTABLE " };\n\n";
print CHARTABLE "static const jshort numeric_value[] =\n";
print CHARTABLE " { ";
$i = 0;
foreach $key (@keys)
{
print CHARTABLE $numerics{$key};
if ($numerics{$key} > 32767 || $numerics{$key} < -32768)
{
# This means our generated type info is incorrect. We
# could just detect and work around this here, but I'm
# lazy.
print STDERR "numeric value won't fit in a short\n";
$status = 1;
}
++$i;
print CHARTABLE ", " if $i < $count;
# Print 10 per line.
print CHARTABLE "\n " if ($i % 10 == 0);
$bytes += 2; # One short.
}
print CHARTABLE " };\n\n";
}
# Print a table that maps one single letter onto another. It assumes
# the map is index by char code.
sub print_single_map
{
local ($title, %map) = @_;
local (@keys) = sort keys %map;
$num = @keys;
print CHARTABLE "static const jchar ", $title, "[][2] =\n";
print CHARTABLE " {\n";
$i = 0;
for $key (@keys)
{
print CHARTABLE " { ";
&print_char (hex ($key));
print CHARTABLE ", ";
&print_char (hex ($map{$key}));
print CHARTABLE " }";
++$i;
if ($i < $num)
{
print CHARTABLE ",";
}
else
{
print CHARTABLE " ";
}
print CHARTABLE " // ", $name{$key}, "\n";
$bytes += 4; # Two bytes per char.
}
print CHARTABLE " };\n\n";
}
# Print the `all' block.
sub print_all_block
{
local (*start, *end, *cats) = @_;
&print_block ("all_table", *start, *end);
local ($i) = 0;
local ($sum) = 0;
while ($i <= $#start)
{
$sum += $end[$i] - $start[$i] + 1;
++$i;
}
# We do this computation just to make sure it isn't cheaper to
# simply list all the characters individually.
printf STDERR ("all_table encodes %d characters in %d entries\n",
$sum, $#start + 1);
print CHARTABLE "static const jbyte category_table[] =\n";
print CHARTABLE " { ";
$i = 0;
while ($i <= $#cats)
{
if ($i > 0 && $cats[$i] eq $cats[$i - 1])
{
# This isn't an error. We can have a duplicate because
# two ranges are not adjacent while the intervening
# characters are left out of the table for other reasons.
# We could exploit this to make the table a little smaller.
# printf STDERR "Duplicate all entry at \\u%04x\n", $start[$i];
}
print CHARTABLE 'java::lang::Character::', $category_map{$cats[$i]};
print CHARTABLE ", " if ($i < $#cats);
++$i;
print CHARTABLE "\n ";
++$bytes;
}
print CHARTABLE " };\n\n";
}
# Print case table.
sub print_case_table
{
local ($title, *start, *end, *map, *anomalous) = @_;
&print_block ($title . '_case_table', *start, *end);
print CHARTABLE "static const jchar ", $title, "_case_map_table[] =\n";
print CHARTABLE " { ";
local ($i) = 0;
while ($i <= $#map)
{
&print_char ($map[$i]);
print CHARTABLE ", " if $i < $#map;
++$i;
print CHARTABLE "\n " if $i % 5 == 0;
$bytes += 2;
}
print CHARTABLE " };\n";
local ($key, @keys);
@keys = sort keys %anomalous;
if ($title eq 'upper')
{
if ($#keys >= 0)
{
# If these are found we need to change Character.isUpperCase.
print STDERR "Found anomalous upper case characters\n";
$status = 1;
}
}
else
{
print CHARTABLE "\n";
print CHARTABLE "static const jchar ", $title, "_anomalous_table[] =\n";
print CHARTABLE " { ";
$i = 0;
foreach $key (@keys)
{
&print_char (hex ($key));
print CHARTABLE ", " if $i < $#keys;
++$i;
print CHARTABLE "\n " if $i % 5 == 0;
$bytes += 2;
}
print CHARTABLE " };\n";
}
print CHARTABLE "\n";
}
# Print the type table and attributes table for the fast version.
sub print_fast_tables
{
local (*start, *end, *cats, *atts, *second_atts) = @_;
print CHARTABLE "static const jbyte type_table[] =\n{ ";
local ($i, $j);
for ($i = 0; $i <= $#cats; ++$i)
{
for ($j = $start[$i]; $j <= $end[$i]; ++$j)
{
print CHARTABLE 'java::lang::Character::', $category_map{$cats[$i]};
print CHARTABLE "," if ($i < $#cats || $j < $end[$i]);
print CHARTABLE "\n ";
}
}
print CHARTABLE "\n };\n\n";
print CHARTABLE "static const jshort attribute_table[] =\n{ ";
for ($i = 0; $i <= 0xffff; ++$i)
{
$atts{$i} = 0 if ! defined $atts{$i};
print CHARTABLE $atts{$i};
print CHARTABLE ", " if $i < 0xffff;
print CHARTABLE "\n " if $i % 5 == 1;
}
print CHARTABLE "\n };\n\n";
print CHARTABLE "static const jshort secondary_attribute_table[] =\n{ ";
for ($i = $ROMAN_START; $i <= $ROMAN_END; ++$i)
{
print CHARTABLE $second_atts{$i};
print CHARTABLE ", " if $i < $ROMAN_END;
print CHARTABLE "\n " if $i % 5 == 1;
}
print CHARTABLE "\n };\n\n";
}
# Print a character constant.
sub print_char
{
local ($ncode) = @_;
printf CHARTABLE "0x%04x", $ncode;
}

104
libjava/classes.pl Normal file
View file

@ -0,0 +1,104 @@
# classes.pl - A perl program to generate most of the contents of
# javaprims.h automatically.
# Copyright (C) 1998, 1999 Cygnus Solutions
#
# This file is part of libjava.
#
# This software is copyrighted work licensed under the terms of the
# Libjava License. Please consult the file "LIBJAVA_LICENSE" for
# details.
# Usage: cd <top-srcdir> ; perl classes.pl.
# Can also be run from the `include' directory; this lets us
# more easily insert the output into javaprims.h (which is where it goes).
use DirHandle;
if (-d 'java')
{
# Ok here.
}
elsif (-d '../java')
{
chdir ('..');
}
else
{
die "couldn't find java directory\n";
}
&scan ('java', 2);
exit 0;
sub scan
{
local ($dir, $indent) = @_;
local (@subdirs) = ();
local (@classes) = ();
local ($d) = new DirHandle $dir;
local (*JFILE);
local ($name);
if (defined $d)
{
while (defined ($name = $d->read))
{
next if $name eq 'CVS';
next if $name eq '.';
next if $name eq '..';
if ($dir eq 'java'
&& $name ne 'lang'
&& $name ne 'util'
&& $name ne 'io')
{
# We only generate decls for java.lang, java.io, and
# java.util.
next;
}
if (-d ($dir . '/' . $name))
{
push (@subdirs, $name);
next;
}
next unless $name =~ /\.java$/;
open (FILE, "< $dir/$name");
while (<FILE>)
{
# NOTE: we don't skip `/*' comments.
s,//.*$,,;
# For now assume that class names start with upper
# case letter.
next unless /(class|interface) ([A-Z][A-Za-z0-9]+)/;
push (@classes, $2);
}
close (FILE);
}
undef $d;
}
local ($spaces) = ' ' x $indent;
local ($classname);
($classname = $dir) =~ s/^.*\///;
print $spaces, "namespace ", $classname, "\n";
print $spaces, "{\n";
foreach (sort @classes)
{
print $spaces, " class ", $_, ";\n";
}
print "\n" if scalar @classes > 0 && scalar @subdirs > 0;
local ($first) = 1;
foreach (sort @subdirs)
{
print "\n" unless $first;
$first = 0;
&scan ("$dir/$_", $indent + 2);
}
print $spaces, "};\n";
}

3783
libjava/configure vendored Executable file

File diff suppressed because it is too large Load diff

61
libjava/configure.host Normal file
View file

@ -0,0 +1,61 @@
# configure.host
# This shell script handles all host based configuration for libgcj.
# It sets various shell variables based on the the host and the
# configuration options. You can modify this shell script without
# needing to rerun autoconf.
# This shell script should be invoked as
# . configure.host
# If it encounters an error, it will exit with a message.
# It uses the following shell variables:
# host The configuration host
# host_cpu The configuration host CPU
# target_optspace --enable-target-optspace ("yes", "no", "")
# It sets the following shell variables:
# libgcj_cflags Special CFLAGS to use when building
# libgcj_cxxflags Special CXXFLAGS to use when building
# libgcj_javaflags Special JAVAFLAGS to use when building
libgcj_flags=
libgcj_cflags=
libgcj_cxxflags=
libgcj_javaflags=
case "${target_optspace}:${host}" in
yes:*)
libgcj_flags="${libgcj_flags} -Os"
;;
:m32r-* | :d10v-* | :d30v-*)
libgcj_flags="${libgcj_flags} -Os"
;;
no:* | :*)
# Nothing.
;;
esac
AM_RUNTESTFLAGS=
# Set any host dependent compiler flags.
# THIS TABLE IS SORTED. KEEP IT THAT WAY.
echo "$target"
case "${host}" in
mips-tx39-*|mipstx39-unknown-*)
libgcj_flags="${libgcj_flags} -G 0"
LDFLAGS="$LDFLAGS -Tjmr3904dram.ld"
AM_RUNTESTFLAGS="--target_board=jmr3904-sim"
;;
i686-*|i586-*)
libgcj_flags="${libgcj_flags} -ffloat-store"
;;
*)
;;
esac
libgcj_cflags="${libgcj_cflags} ${libgcj_flags}"
libgcj_cxxflags="${libgcj_cxxflags} ${libgcj_flags}"
libgcj_javaflags="${libgcj_javaflags} ${libgcj_flags}"

387
libjava/configure.in Normal file
View file

@ -0,0 +1,387 @@
dnl Process this with autoconf to create configure
AC_INIT(java/lang/System.java)
dnl Can't be done in LIBGCJ_CONFIGURE because that confuses automake.
AC_CONFIG_AUX_DIR(..)
AC_CANONICAL_SYSTEM
dnl We use these options to decide which functions to include.
AC_ARG_WITH(target-subdir,
[ --with-target-subdir=SUBDIR Configuring in a subdirectory])
AC_ARG_WITH(cross-host,
[ --with-cross-host=HOST Configuring with a cross compiler])
LIBGCJ_CONFIGURE(.)
AM_CONFIG_HEADER(include/config.h)
if test -z "$with_target_subdir" || test "$with_target_subdir" = "."; then
COMPPATH=.
else
COMPPATH=..
fi
AC_SUBST(COMPPATH)
dnl The -no-testsuite modules omit the test subdir.
AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
dnl See whether the user prefers size or speed for Character.
dnl The default is size.
AC_ARG_ENABLE(fast-character,
[ --enable-fast-character Prefer speed over size for Character],
# Nothing
, AC_DEFINE(COMPACT_CHARACTER))
dnl See if the user has requested runtime debugging.
AC_ARG_ENABLE(libgcj-debug,
[ --enable-libgcj-debug Enable runtime debugging code],
if test "$enable_libgcj_debug" = yes; then
AC_DEFINE(DEBUG)
fi)
dnl If the target is an eCos system, use the appropriate eCos
dnl I/O routines.
dnl FIXME: this should not be a local option but a global target
dnl system; at present there is no eCos target.
TARGET_ECOS="no"
AC_ARG_WITH(ecos,
[ --with-ecos Enable runtime eCos target support.],
TARGET_ECOS="$with_ecos"
)
case "$TARGET_ECOS" in
no)
FILE_DESCRIPTOR=natFileDescriptorPosix.cc
;;
*)
FILE_DESCRIPTOR=natFileDescriptorEcos.cc
AC_DEFINE(ECOS)
;;
esac
AC_EGREP_HEADER(__uint32_t, sys/types.h, AC_DEFINE(HAVE_INT32_DEFINED))
AC_EGREP_HEADER(__uint32_t, sys/config.h, AC_DEFINE(HAVE_INT32_DEFINED))
dnl These may not be defined in a non-ANS conformant embedded system.
dnl FIXME: Should these case a runtime exception in that case?
AC_EGREP_HEADER(mktime, time.h, AC_DEFINE(HAVE_MKTIME))
AC_EGREP_HEADER(localtime, time.h, AC_DEFINE(HAVE_LOCALTIME))
dnl Create the subdirectory for natFileDescriptor.cc, or the attempt
dnl to create the link will fail.
test -d java || mkdir java
test -d java/io || mkdir java/io
AC_LINK_FILES(java/io/$FILE_DESCRIPTOR, java/io/natFileDescriptor.cc)
dnl Allow the GC to be disabled. Can be useful when debugging.
AC_MSG_CHECKING([for garbage collector to use])
AC_ARG_ENABLE(java-gc,
changequote(<<,>>)dnl
<< --enable-java-gc=TYPE choose garbage collector [boehm]>>,
changequote([,])
GC=$enableval,
GC=boehm)
GCLIBS=
GCINCS=
GCDEPS=
GCOBJS=
case "$GC" in
boehm)
AC_MSG_RESULT(boehm)
GCLIBS='-L$(top_builddir)/../boehm-gc -lgcjgc'
GCDEPS='$(top_builddir)/../boehm-gc/libgcjgc.a'
GCINCS='-I$(top_srcdir)/../boehm-gc -I$(top_builddir)/../boehm-gc'
dnl We also want to pick up some cpp flags required when including
dnl boehm-config.h. Yuck.
GCINCS="$GCINCS `cat ../boehm-gc/boehm-cflags`"
GCOBJS=boehm.o
GCHDR=boehm-gc.h
dnl The POSIX thread support needs to know this.
AC_DEFINE(HAVE_BOEHM_GC)
;;
no)
AC_MSG_RESULT(none)
GCOBJS=nogc.o
GCHDR=no-gc.h
;;
*)
AC_MSG_ERROR(unrecognized collector \"$GC\")
;;
esac
AC_SUBST(GCLIBS)
AC_SUBST(GCINCS)
AC_SUBST(GCDEPS)
AC_SUBST(GCOBJS)
AC_LINK_FILES(include/$GCHDR, include/java-gc.h)
dnl Note that this code is kept in sync with similar code in gcc/configure.in.
dnl In particular both packages must make the same decision about which
dnl thread package to use.
AC_MSG_CHECKING([for threads package to use])
AC_ARG_ENABLE(threads, [ --enable-threads=TYPE choose threading package],
THREADS=$enableval,
dnl FIXME: figure out native threads to use here.
THREADS=no)
if test "$THREADS" = yes; then
case "$host" in
*-*-vxworks*)
THREADS=vxworks
;;
*-*-linux*)
# FIXME: this isn't correct in all cases.
THREADS=posix
;;
*-*-win*)
THREADS=win32
;;
*-*-irix*)
THREADS=irix
;;
*-*-solaris*)
# FIXME: for now, choose POSIX, because we implement that.
# Later, choose solaris threads.
THREADS=posix
;;
*)
# For now.
THREADS=none
;;
esac
fi
case "$THREADS" in
no | none | single)
THREADS=none
;;
posix | pthreads)
THREADS=posix
case "$host" in
*-*-linux*)
AC_DEFINE(LINUX_THREADS)
;;
esac
;;
qt)
;;
decosf1 | irix | mach | os2 | solaris | win32 | dce | vxworks)
AC_MSG_ERROR(thread package $THREADS not yet supported)
;;
*)
AC_MSG_ERROR($THREADS is an unknown thread package)
;;
esac
AC_MSG_RESULT($THREADS)
THREADLIBS=
THREADINCS=
THREADDEPS=
THREADOBJS=
THREADH=
case "$THREADS" in
posix)
THREADLIBS=-lpthread
THREADOBJS=posix-threads.o
THREADH=posix-threads.h
# MIT pthreads doesn't seem to have the mutexattr functions.
# But for now we don't check for it. We just assume you aren't
# using MIT pthreads.
AC_DEFINE(HAVE_PTHREAD_MUTEXATTR_INIT)
;;
qt)
THREADLIBS='-L$(top_builddir)/../qthreads -lgcjcoop'
THREADOBJS=quick-threads.o
THREADINCS='-I$(top_srcdir)/../qthreads'
THREADH=quick-threads.h
THREADDEPS='$(top_builddir)/../qthreads/libgcjcoop.a'
;;
none)
THREADOBJS=no-threads.o
THREADH=no-threads.h
;;
esac
AC_LINK_FILES(include/$THREADH, include/java-threads.h)
AC_SUBST(THREADLIBS)
AC_SUBST(THREADINCS)
AC_SUBST(THREADDEPS)
AC_SUBST(THREADOBJS)
AM_CONDITIONAL(USING_GCC, test "$GCC" = yes)
CANADIAN=no
NULL_TARGET=no
# Find eh-common.h and support headers. If we're in the tree with
# gcc, then look there. Otherwise look in compat-include. If all else
# fails, just hope the user has set things up somehow.
if test -r $srcdir/../gcc/eh-common.h; then
EH_COMMON_INCLUDE='-I$(top_srcdir)/../gcc -I$(top_srcdir)/../include'
else
if test -d $srcdir/../compat-include; then
EH_COMMON_INCLUDE='-I$(top_srcdir)/../compat-include'
else
EH_COMMON_INCLUDE=
fi
fi
if test -n "${with_cross_host}"; then
# We are being configured with a cross compiler. AC_REPLACE_FUNCS
# may not work correctly, because the compiler may not be able to
# link executables.
# We assume newlib. This lets us hard-code the functions we know
# we'll have.
AC_DEFINE(HAVE_MEMMOVE)
AC_DEFINE(HAVE_MEMCPY)
AC_DEFINE(HAVE_STRERROR)
AC_DEFINE(HAVE_CTIME_R)
AC_DEFINE(HAVE_GMTIME_R)
AC_DEFINE(HAVE_LOCALTIME_R)
dnl This is only for POSIX threads.
AC_DEFINE(HAVE_PTHREAD_MUTEXATTR_INIT)
dnl We also assume we are using gcc, which provides alloca.
AC_DEFINE(HAVE_ALLOCA)
# If Canadian cross, then don't pick up tools from the build
# directory.
if test "$build" != "$with_cross_host"; then
CANADIAN=yes
EH_COMMON_INCLUDE=
fi
else
# Some POSIX thread systems don't have pthread_mutexattr_settype.
# E.g., Solaris.
AC_CHECK_FUNCS(strerror ioctl select open fsync sleep)
AC_CHECK_FUNCS(ctime_r ctime, break)
AC_CHECK_FUNCS(gmtime_r localtime_r readdir_r getpwuid_r)
AC_CHECK_FUNCS(access stat mkdir rename rmdir unlink realpath)
AC_CHECK_FUNCS(inet_aton inet_addr, break)
AC_CHECK_FUNCS(inet_pton uname)
AC_CHECK_FUNCS(gethostbyname_r, [
AC_DEFINE(HAVE_GETHOSTBYNAME_R)
# There are two different kinds of gethostbyname_r.
# We look for the one that returns `int'.
# Hopefully this check is robust enough.
AC_EGREP_HEADER(int.*gethostbyname_r, netdb.h, [
AC_DEFINE(GETHOSTBYNAME_R_RETURNS_INT)])])
AC_CHECK_FUNCS(gethostbyaddr_r, [
AC_DEFINE(HAVE_GETHOSTBYADDR_R)
# There are two different kinds of gethostbyaddr_r.
# We look for the one that returns `int'.
# Hopefully this check is robust enough.
AC_EGREP_HEADER(int.*gethostbyaddr_r, netdb.h, [
AC_DEFINE(GETHOSTBYADDR_R_RETURNS_INT)])])
AC_CHECK_FUNCS(gethostname, [
AC_DEFINE(HAVE_GETHOSTNAME)
AC_EGREP_HEADER(gethostname, unistd.h, [
AC_DEFINE(HAVE_GETHOSTNAME_DECL)])])
# Look for these functions in the thread library.
save_LIBS="$LIBS"
LIBS="$LIBS $THREADLIBS"
AC_CHECK_FUNCS(pthread_mutexattr_settype pthread_mutexattr_setkind_np sched_yield)
LIBS="$save_LIBS"
# We require a way to get the time.
time_found=no
AC_CHECK_FUNCS(gettimeofday time ftime, time_found=yes)
if test "$time_found" = no; then
AC_MSG_ERROR([no function found to get the time])
fi
# We require memmove.
memmove_found=no
AC_CHECK_FUNCS(memmove, memmove_found=yes)
if test "$memmove_found" = no; then
AC_MSG_ERROR([memmove is required])
fi
# We require memcpy.
memcpy_found=no
AC_CHECK_FUNCS(memcpy, memcpy_found=yes)
if test "$memcpy_found" = no; then
AC_MSG_ERROR([memcpy is required])
fi
test -d "$libgcj_basedir/../gcc/java" || {
CANADIAN=yes
NULL_TARGET=yes
}
fi
AM_CONDITIONAL(CANADIAN, test "$CANADIAN" = yes)
AM_CONDITIONAL(NULL_TARGET, test "$NULL_TARGET" = yes)
AM_CONDITIONAL(NATIVE, test "$CANADIAN" = no || test "$NULL_TARGET" = yes)
AC_SUBST(EH_COMMON_INCLUDE)
AC_SUBST(AM_RUNTESTFLAGS)
dnl We check for sys/filio.h because Solaris 2.5 defines FIONREAD there.
dnl On that system, sys/ioctl.h will not include sys/filio.h unless
dnl BSD_COMP is defined; just including sys/filio.h is simpler.
AC_CHECK_HEADERS(unistd.h sys/time.h sys/types.h fcntl.h sys/ioctl.h sys/filio.h sys/stat.h sys/select.h sys/socket.h netinet/in.h arpa/inet.h netdb.h pwd.h)
dnl We avoid AC_HEADER_DIRENT since we really only care about dirent.h
dnl for now. If you change this, you also must update natFile.cc.
AC_CHECK_HEADERS(dirent.h)
AC_MSG_CHECKING([whether struct sockaddr_in6 is in netinet/in.h])
AC_TRY_COMPILE([#include <netinet/in.h>], [struct sockaddr_in6 addr6;],
[AC_DEFINE(HAVE_INET6)
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)])
AC_MSG_CHECKING([for socklen_t in sys/socket.h])
AC_TRY_COMPILE([#include <sys/socket.h>], [socklen_t x = 5;],
[AC_DEFINE(HAVE_SOCKLEN_T)
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)])
AC_MSG_CHECKING([for tm_gmtoff in struct tm])
AC_TRY_COMPILE([#include <time.h>], [struct tm tim; tim.tm_gmtoff = 0;],
[AC_DEFINE(STRUCT_TM_HAS_GMTOFF)
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)
AC_MSG_CHECKING([for global timezone variable])
dnl FIXME: we don't want a link check here because that won't work
dnl when cross-compiling. So instead we make an assumption that
dnl the header file will mention timezone if it exists.
AC_TRY_COMPILE([#include <time.h>], [long z2 = timezone;],
[AC_DEFINE(HAVE_TIMEZONE)
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)])])
AC_FUNC_ALLOCA
AC_CHECK_PROGS(PERL, perl, false)
if test "${multilib}" = "yes"; then
multilib_arg="--enable-multilib"
else
multilib_arg=
fi
here=`pwd`
AC_SUBST(here)
AC_OUTPUT(Makefile testsuite/Makefile,
[if test -n "$CONFIG_FILES"; then
ac_file=Makefile . ${libgcj_basedir}/../config-ml.in
fi],
srcdir=${srcdir}
host=${host}
target=${target}
with_multisubdir=${with_multisubdir}
ac_configure_args="${multilib_arg} ${ac_configure_args}"
CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
libgcj_basedir=${libgcj_basedir}
CC="${CC}"
CXX="${CXX}"
)

972
libjava/doc/cni.sgml Normal file
View file

@ -0,0 +1,972 @@
<!DOCTYPE article PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<article>
<artheader>
<title>The Cygnus Native Interface for C++/Java Integration</title>
<subtitle>Writing native Java methods in natural C++</subtitle>
<authorgroup>
<corpauthor>Cygnus Solutions</corpauthor>
</authorgroup>
<date>February, 1999</date>
</artheader>
<abstract><para>
This documents CNI, the Cygnus Native Interface,
which is is a convenient way to write Java native methods using C++.
This is a more efficient, more convenient, but less portable
alternative to the standard JNI (Java Native Interface).</para>
</abstract>
<sect1><title>Basic Concepts</title>
<para>
In terms of languages features, Java is mostly a subset
of C++. Java has a few important extensions, plus a powerful standard
class library, but on the whole that does not change the basic similarity.
Java is a hybrid object-oriented language, with a few native types,
in addition to class types. It is class-based, where a class may have
static as well as per-object fields, and static as well as instance methods.
Non-static methods may be virtual, and may be overloaded. Overloading is
resolved at compile time by matching the actual argument types against
the parameter types. Virtual methods are implemented using indirect calls
through a dispatch table (virtual function table). Objects are
allocated on the heap, and initialized using a constructor method.
Classes are organized in a package hierarchy.
</para>
<para>
All of the listed attributes are also true of C++, though C++ has
extra features (for example in C++ objects may be allocated not just
on the heap, but also statically or in a local stack frame). Because
<acronym>gcj</acronym> uses the same compiler technology as
<acronym>g++</acronym> (the GNU C++ compiler), it is possible
to make the intersection of the two languages use the same
<acronym>ABI</acronym> (object representation and calling conventions).
The key idea in <acronym>CNI</acronym> is that Java objects are C++ objects,
and all Java classes are C++ classes (but not the other way around).
So the most important task in integrating Java and C++ is to
remove gratuitous incompatibilities.
</para>
<para>
You write CNI code as a regular C++ source file. (You do have to use
a Java/CNI-aware C++ compiler, specifically a recent version of G++.)</para>
<para>
You start with:
<programlisting>
#include &lt;cni.h&gt;
</programlisting></para>
<para>
You then include header files for the various Java classes you need
to use:
<programlisting>
#include &lt;java/lang/Character.h&gt;
#include &lt;java/util/Date.h&gt;
#include &lt;java/lang/IndexOutOfBoundsException.h&gt;
</programlisting></para>
<para>
In general, <acronym>CNI</acronym> functions and macros start with the
`<literal>Jv</literal>' prefix, for example the function
`<literal>JvNewObjectArray</literal>'. This convention is used to
avoid conflicts with other libraries.
Internal functions in <acronym>CNI</acronym> start with the prefix
`<literal>_Jv_</literal>'. You should not call these;
if you find a need to, let us know and we will try to come up with an
alternate solution. (This manual lists <literal>_Jv_AllocBytes</literal>
as an example; <acronym>CNI</acronym> should instead provide
a <literal>JvAllocBytes</literal> function.)</para>
<para>
These header files are automatically generated by <command>gcjh</command>.
</para>
</sect1>
<sect1><title>Packages</title>
<para>
The only global names in Java are class names, and packages.
A <firstterm>package</firstterm> can contain zero or more classes, and
also zero or more sub-packages.
Every class belongs to either an unnamed package or a package that
has a hierarchical and globally unique name.
</para>
<para>
A Java package is mapped to a C++ <firstterm>namespace</firstterm>.
The Java class <literal>java.lang.String</literal>
is in the package <literal>java.lang</literal>, which is a sub-package
of <literal>java</literal>. The C++ equivalent is the
class <literal>java::lang::String</literal>,
which is in the namespace <literal>java::lang</literal>,
which is in the namespace <literal>java</literal>.
</para>
<para>
Here is how you could express this:
<programlisting>
// Declare the class(es), possibly in a header file:
namespace java {
namespace lang {
class Object;
class String;
...
}
}
class java::lang::String : public java::lang::Object
{
...
};
</programlisting>
</para>
<para>
The <literal>gcjh</literal> tool automatically generates the
nessary namespace declarations.</para>
<sect2><title>Nested classes as a substitute for namespaces</title>
<para>
<!-- FIXME the next line reads poorly jsm -->
It is not that long since g++ got complete namespace support,
and it was very recent (end of February 1999) that <literal>libgcj</literal>
was changed to uses namespaces. Releases before then used
nested classes, which are the C++ equivalent of Java inner classes.
They provide similar (though less convenient) functionality.
The old syntax is:
<programlisting>
class java {
class lang {
class Object;
class String;
};
};
</programlisting>
The obvious difference is the use of <literal>class</literal> instead
of <literal>namespace</literal>. The more important difference is
that all the members of a nested class have to be declared inside
the parent class definition, while namespaces can be defined in
multiple places in the source. This is more convenient, since it
corresponds more closely to how Java packages are defined.
The main difference is in the declarations; the syntax for
using a nested class is the same as with namespaces:
<programlisting>
class java::lang::String : public java::lang::Object
{ ... }
</programlisting>
Note that the generated code (including name mangling)
using nested classes is the same as that using namespaces.</para>
</sect2>
<sect2><title>Leaving out package names</title>
<para>
<!-- FIXME next line reads poorly jsm -->
Having to always type the fully-qualified class name is verbose.
It also makes it more difficult to change the package containing a class.
The Java <literal>package</literal> declaration specifies that the
following class declarations are in the named package, without having
to explicitly name the full package qualifiers.
The <literal>package</literal> declaration can be followed by zero or
more <literal>import</literal> declarations, which allows either
a single class or all the classes in a package to be named by a simple
identifier. C++ provides something similar
with the <literal>using</literal> declaration and directive.
</para>
<para>
A Java simple-type-import declaration:
<programlisting>
import <replaceable>PackageName</replaceable>.<replaceable>TypeName</replaceable>;
</programlisting>
allows using <replaceable>TypeName</replaceable> as a shorthand for
<literal><replaceable>PackageName</replaceable>.<replaceable>TypeName</replaceable></literal>.
The C++ (more-or-less) equivalent is a <literal>using</literal>-declaration:
<programlisting>
using <replaceable>PackageName</replaceable>::<replaceable>TypeName</replaceable>;
</programlisting>
</para>
<para>
A Java import-on-demand declaration:
<programlisting>
import <replaceable>PackageName</replaceable>.*;
</programlisting>
allows using <replaceable>TypeName</replaceable> as a shorthand for
<literal><replaceable>PackageName</replaceable>.<replaceable>TypeName</replaceable></literal>
The C++ (more-or-less) equivalent is a <literal>using</literal>-directive:
<programlisting>
using namespace <replaceable>PackageName</replaceable>;
</programlisting>
</para>
</sect2>
</sect1>
<sect1><title>Primitive types</title>
<para>
Java provides 8 <quote>primitives</quote> types:
<literal>byte</literal>, <literal>short</literal>, <literal>int</literal>,
<literal>long</literal>, <literal>float</literal>, <literal>double</literal>,
<literal>char</literal>, and <literal>boolean</literal>.
These are the same as the following C++ <literal>typedef</literal>s
(which are defined by <literal>cni.h</literal>):
<literal>jbyte</literal>, <literal>jshort</literal>, <literal>jint</literal>,
<literal>jlong</literal>, <literal>jfloat</literal>,
<literal>jdouble</literal>,
<literal>jchar</literal>, and <literal>jboolean</literal>.
You should use the C++ typenames
(<ForeignPhrase><Abbrev>e.g.</Abbrev></ForeignPhrase> <literal>jint</literal>),
and not the Java types names
(<ForeignPhrase><Abbrev>e.g.</Abbrev></ForeignPhrase> <literal>int</literal>),
even if they are <quote>the same</quote>.
This is because there is no guarantee that the C++ type
<literal>int</literal> is a 32-bit type, but <literal>jint</literal>
<emphasis>is</emphasis> guaranteed to be a 32-bit type.
<informaltable frame="all" colsep="1" rowsep="0">
<tgroup cols="3">
<thead>
<row>
<entry>Java type</entry>
<entry>C/C++ typename</entry>
<entry>Description</entry>
</thead>
<tbody>
<row>
<entry>byte</entry>
<entry>jbyte</entry>
<entry>8-bit signed integer</entry>
</row>
<row>
<entry>short</entry>
<entry>jshort</entry>
<entry>16-bit signed integer</entry>
</row>
<row>
<entry>int</entry>
<entry>jint</entry>
<entry>32-bit signed integer</entry>
</row>
<row>
<entry>long</entry>
<entry>jlong</entry>
<entry>64-bit signed integer</entry>
</row>
<row>
<entry>float</entry>
<entry>jfloat</entry>
<entry>32-bit IEEE floating-point number</entry>
</row>
<row>
<entry>double</entry>
<entry>jdouble</entry>
<entry>64-bit IEEE floating-point number</entry>
</row>
<row>
<entry>char</entry>
<entry>jchar</entry>
<entry>16-bit Unicode character</entry>
</row>
<row>
<entry>boolean</entry>
<entry>jboolean</entry>
<entry>logical (Boolean) values</entry>
</row>
<row>
<entry>void</entry>
<entry>void</entry>
<entry>no value</entry>
</row>
</tbody></tgroup>
</informaltable>
</para>
<para>
<funcsynopsis>
<funcdef><function>JvPrimClass</function></funcdef>
<paramdef><parameter>primtype</parameter></paramdef>
</funcsynopsis>
This is a macro whose argument should be the name of a primitive
type, <ForeignPhrase><Abbrev>e.g.</Abbrev></ForeignPhrase>
<literal>byte</literal>.
The macro expands to a pointer to the <literal>Class</literal> object
corresponding to the primitive type.
<ForeignPhrase><Abbrev>E.g.</Abbrev></ForeignPhrase>,
<literal>JvPrimClass(void)</literal>
has the same value as the Java expression
<literal>Void.TYPE</literal> (or <literal>void.class</literal>).
</para>
</sect1>
<sect1><title>Objects and Classes</title>
<sect2><title>Classes</title>
<para>
All Java classes are derived from <literal>java.lang.Object</literal>.
C++ does not have a unique <quote>root</quote>class, but we use
a C++ <literal>java::lang::Object</literal> as the C++ version
of the <literal>java.lang.Object</literal> Java class. All
other Java classes are mapped into corresponding C++ classes
derived from <literal>java::lang::Object</literal>.</para>
<para>
Interface inheritance (the <quote><literal>implements</literal></quote>
keyword) is currently not reflected in the C++ mapping.</para>
</sect2>
<sect2><title>Object references</title>
<para>
We implement a Java object reference as a pointer to the start
of the referenced object. It maps to a C++ pointer.
(We cannot use C++ references for Java references, since
once a C++ reference has been initialized, you cannot change it to
point to another object.)
The <literal>null</literal> Java reference maps to the <literal>NULL</literal>
C++ pointer.
</para>
<para>
Note that in some Java implementations an object reference is implemented as
a pointer to a two-word <quote>handle</quote>. One word of the handle
points to the fields of the object, while the other points
to a method table. Gcj does not use this extra indirection.
</para>
</sect2>
<sect2><title>Object fields</title>
<para>
Each object contains an object header, followed by the instance
fields of the class, in order. The object header consists of
a single pointer to a dispatch or virtual function table.
(There may be extra fields <quote>in front of</quote> the object,
for example for
memory management, but this is invisible to the application, and
the reference to the object points to the dispatch table pointer.)
</para>
<para>
The fields are laid out in the same order, alignment, and size
as in C++. Specifically, 8-bite and 16-bit native types
(<literal>byte</literal>, <literal>short</literal>, <literal>char</literal>,
and <literal>boolean</literal>) are <emphasis>not</emphasis>
widened to 32 bits.
Note that the Java VM does extend 8-bit and 16-bit types to 32 bits
when on the VM stack or temporary registers.</para>
<para>
If you include the <literal>gcjh</literal>-generated header for a
class, you can access fields of Java classes in the <quote>natural</quote>
way. Given the following Java class:
<programlisting>
public class Int
{
public int i;
public Integer (int i) { this.i = i; }
public static zero = new Integer(0);
}
</programlisting>
you can write:
<programlisting>
#include &lt;cni.h&gt;
#include &lt;Int.h&gt;
Int*
mult (Int *p, jint k)
{
if (k == 0)
return Int::zero; // static member access.
return new Int(p->i * k);
}
</programlisting>
</para>
<para>
<acronym>CNI</acronym> does not strictly enforce the Java access
specifiers, because Java permissions cannot be directly mapped
into C++ permission. Private Java fields and methods are mapped
to private C++ fields and methods, but other fields and methods
are mapped to public fields and methods.
</para>
</sect2>
</sect1>
<sect1><title>Arrays</title>
<para>
While in many ways Java is similar to C and C++,
it is quite different in its treatment of arrays.
C arrays are based on the idea of pointer arithmetic,
which would be incompatible with Java's security requirements.
Java arrays are true objects (array types inherit from
<literal>java.lang.Object</literal>). An array-valued variable
is one that contains a reference (pointer) to an array object.
</para>
<para>
Referencing a Java array in C++ code is done using the
<literal>JArray</literal> template, which as defined as follows:
<programlisting>
class __JArray : public java::lang::Object
{
public:
int length;
};
template&lt;class T&gt;
class JArray : public __JArray
{
T data[0];
public:
T&amp; operator[](jint i) { return data[i]; }
};
</programlisting></para>
<para>
<funcsynopsis>
<funcdef>template&lt;class T&gt; T *<function>elements</function></funcdef>
<paramdef>JArray&lt;T&gt; &amp;<parameter>array</parameter></paramdef>
</funcsynopsis>
This template function can be used to get a pointer to the
elements of the <parameter>array</parameter>.
For instance, you can fetch a pointer
to the integers that make up an <literal>int[]</literal> like so:
<programlisting>
extern jintArray foo;
jint *intp = elements (foo);
</programlisting>
The name of this function may change in the future.</para>
<para>
There are a number of typedefs which correspond to typedefs from JNI.
Each is the type of an array holding objects of the appropriate type:
<programlisting>
typedef __JArray *jarray;
typedef JArray&lt;jobject&gt; *jobjectArray;
typedef JArray&lt;jboolean&gt; *jbooleanArray;
typedef JArray&lt;jbyte&gt; *jbyteArray;
typedef JArray&lt;jchar&gt; *jcharArray;
typedef JArray&lt;jshort&gt; *jshortArray;
typedef JArray&lt;jint&gt; *jintArray;
typedef JArray&lt;jlong&gt; *jlongArray;
typedef JArray&lt;jfloat&gt; *jfloatArray;
typedef JArray&lt;jdouble&gt; *jdoubleArray;
</programlisting>
</para>
<para>
You can create an array of objects using this function:
<funcsynopsis>
<funcdef>jobjectArray <function>JvNewObjectArray</function></funcdef>
<paramdef>jint <parameter>length</parameter></paramdef>
<paramdef>jclass <parameter>klass</parameter></paramdef>
<paramdef>jobject <parameter>init</parameter></paramdef>
</funcsynopsis>
Here <parameter>klass</parameter> is the type of elements of the array;
<parameter>init</parameter> is the initial
value to be put into every slot in the array.
</para>
<para>
For each primitive type there is a function which can be used
to create a new array holding that type. The name of the function
is of the form
`<literal>JvNew&lt;<replaceable>Type</replaceable>&gt;Array</literal>',
where `&lt;<replaceable>Type</replaceable>&gt;' is the name of
the primitive type, with its initial letter in upper-case. For
instance, `<literal>JvNewBooleanArray</literal>' can be used to create
a new array of booleans.
Each such function follows this example:
<funcsynopsis>
<funcdef>jbooleanArray <function>JvNewBooleanArray</function></funcdef>
<paramdef>jint <parameter>length</parameter></paramdef>
</funcsynopsis>
</para>
<para>
<funcsynopsis>
<funcdef>jsize <function>JvGetArrayLength</function></funcdef>
<paramdef>jarray <parameter>array</parameter></paramdef>
</funcsynopsis>
Returns the length of <parameter>array</parameter>.</para>
</sect1>
<sect1><title>Methods</title>
<para>
Java methods are mapped directly into C++ methods.
The header files generated by <literal>gcjh</literal>
include the appropriate method definitions.
Basically, the generated methods have the same names and
<quote>corresponding</quote> types as the Java methods,
and are called in the natural manner.</para>
<sect2><title>Overloading</title>
<para>
Both Java and C++ provide method overloading, where multiple
methods in a class have the same name, and the correct one is chosen
(at compile time) depending on the argument types.
The rules for choosing the correct method are (as expected) more complicated
in C++ than in Java, but given a set of overloaded methods
generated by <literal>gcjh</literal> the C++ compiler will choose
the expected one.</para>
<para>
Common assemblers and linkers are not aware of C++ overloading,
so the standard implementation strategy is to encode the
parameter types of a method into its assembly-level name.
This encoding is called <firstterm>mangling</firstterm>,
and the encoded name is the <firstterm>mangled name</firstterm>.
The same mechanism is used to implement Java overloading.
For C++/Java interoperability, it is important that both the Java
and C++ compilers use the <emphasis>same</emphasis> encoding scheme.
</para>
</sect2>
<sect2><title>Static methods</title>
<para>
Static Java methods are invoked in <acronym>CNI</acronym> using the standard
C++ syntax, using the `<literal>::</literal>' operator rather
than the `<literal>.</literal>' operator. For example:
</para>
<programlisting>
jint i = java::lang::Math::round((jfloat) 2.3);
</programlisting>
<para>
<!-- FIXME this next sentence seems ungammatical jsm -->
Defining a static native method uses standard C++ method
definition syntax. For example:
<programlisting>
#include &lt;java/lang/Integer.h&gt;
java::lang::Integer*
java::lang::Integer::getInteger(jstring str)
{
...
}
</programlisting>
</sect2>
<sect2><title>Object Constructors</title>
<para>
Constructors are called implicitly as part of object allocation
using the <literal>new</literal> operator. For example:
<programlisting>
java::lang::Int x = new java::lang::Int(234);
</programlisting>
</para>
<para>
<!-- FIXME rewrite needed here, mine may not be good jsm -->
Java does not allow a constructor to be a native method.
Instead, you could define a private method which
you can have the constructor call.
</para>
</sect2>
<sect2><title>Instance methods</title>
<para>
<!-- FIXME next para week, I would remove a few words from some sentences jsm -->
Virtual method dispatch is handled essentially the same way
in C++ and Java -- <abbrev>i.e.</abbrev> by doing an
indirect call through a function pointer stored in a per-class virtual
function table. C++ is more complicated because it has to support
multiple inheritance, but this does not effect Java classes.
However, G++ has historically used a different calling convention
that is not compatible with the one used by <acronym>gcj</acronym>.
During 1999, G++ will switch to a new ABI that is compatible with
<acronym>gcj</acronym>. Some platforms (including Linux) have already
changed. On other platforms, you will have to pass
the <literal>-fvtable-thunks</literal> flag to g++ when
compiling <acronym>CNI</acronym> code.
</para>
<para>
Calling a Java instance method in <acronym>CNI</acronym> is done
using the standard C++ syntax. For example:
<programlisting>
java::lang::Number *x;
if (x-&gt;doubleValue() &gt; 0.0) ...
</programlisting>
</para>
<para>
Defining a Java native instance method is also done the natural way:
<programlisting>
#include &lt;java/lang/Integer.h&gt;
jdouble
java::lang:Integer::doubleValue()
{
return (jdouble) value;
}
</programlisting>
</para>
</sect2>
<sect2><title>Interface method calls</title>
<para>
In Java you can call a method using an interface reference.
This is not yet supported in <acronym>CNI</acronym>.</para>
</sect2>
</sect1>
<sect1><title>Object allocation</title>
<para>
New Java objects are allocated using a
<firstterm>class-instance-creation-expression</firstterm>:
<programlisting>
new <replaceable>Type</replaceable> ( <replaceable>arguments</replaceable> )
</programlisting>
The same syntax is used in C++. The main difference is that
C++ objects have to be explicitly deleted; in Java they are
automatically deleted by the garbage collector.
Using <acronym>CNI</acronym>, you can allocate a new object
using standard C++ syntax. The C++ compiler is smart enough to
realize the class is a Java class, and hence it needs to allocate
memory from the garbage collector. If you have overloaded
constructors, the compiler will choose the correct one
using standard C++ overload resolution rules. For example:
<programlisting>
java::util::Hashtable *ht = new java::util::Hashtable(120);
</programlisting>
</para>
<para>
<funcsynopsis>
<funcdef>void *<function>_Jv_AllocBytes</function></funcdef>
<paramdef>jsize <parameter>size</parameter></paramdef>
</funcsynopsis>
Allocate <parameter>size</parameter> bytes. This memory is not
scanned by the garbage collector. However, it will be freed by
the GC if no references to it are discovered.
</para>
</sect1>
<sect1><title>Interfaces</title>
<para>
A Java class can <firstterm>implement</firstterm> zero or more
<firstterm>interfaces</firstterm>, in addition to inheriting from
a single base class.
An interface is a collection of constants and method specifications;
it is similar to the <firstterm>signatures</firstterm> available
as a G++ extension. An interface provides a subset of the
functionality of C++ abstract virtual base classes, but they
are currently implemented differently.
CNI does not currently provide any support for interfaces,
or calling methods from an interface pointer.
This is partly because we are planning to re-do how
interfaces are implemented in <acronym>gcj</acronym>.
</para>
</sect1>
<sect1><title>Strings</title>
<para>
<acronym>CNI</acronym> provides a number of utility functions for
working with Java <literal>String</literal> objects.
The names and interfaces are analogous to those of <acronym>JNI</acronym>.
</para>
<para>
<funcsynopsis>
<funcdef>jstring <function>JvNewString</function></funcdef>
<paramdef>const jchar *<parameter>chars</parameter></paramdef>
<paramdef>jsize <parameter>len</parameter></paramdef>
</funcsynopsis>
Creates a new Java String object, where
<parameter>chars</parameter> are the contents, and
<parameter>len</parameter> is the number of characters.
</para>
<para>
<funcsynopsis>
<funcdef>jstring <function>JvNewStringLatin1</function></funcdef>
<paramdef>const char *<parameter>bytes</parameter></paramdef>
<paramdef>jsize <parameter>len</parameter></paramdef>
</funcsynopsis>
Creates a new Java String object, where <parameter>bytes</parameter>
are the Latin-1 encoded
characters, and <parameter>len</parameter> is the length of
<parameter>bytes</parameter>, in bytes.
</para>
<para>
<funcsynopsis>
<funcdef>jstring <function>JvNewStringLatin1</function></funcdef>
<paramdef>const char *<parameter>bytes</parameter></paramdef>
</funcsynopsis>
Like the first JvNewStringLatin1, but computes <parameter>len</parameter>
using <literal>strlen</literal>.
</para>
<para>
<funcsynopsis>
<funcdef>jstring <function>JvNewStringUTF</function></funcdef>
<paramdef>const char *<parameter>bytes</parameter></paramdef>
</funcsynopsis>
Creates a new Java String object, where <parameter>bytes</parameter> are
the UTF-8 encoded characters of the string, terminated by a null byte.
</para>
<para>
<funcsynopsis>
<funcdef>jchar *<function>JvGetStringChars</function></funcdef>
<paramdef>jstring <parameter>str</parameter></paramdef>
</funcsynopsis>
Returns a pointer to the array of characters which make up a string.
</para>
<para>
<funcsynopsis>
<funcdef> int <function>JvGetStringUTFLength</function></funcdef>
<paramdef>jstring <parameter>str</parameter></paramdef>
</funcsynopsis>
Returns number of bytes required to encode contents
of <parameter>str</parameter> as UTF-8.
</para>
<para>
<funcsynopsis>
<funcdef> jsize <function>JvGetStringUTFRegion</function></funcdef>
<paramdef>jstring <parameter>str</parameter></paramdef>
<paramdef>jsize <parameter>start</parameter></paramdef>
<paramdef>jsize <parameter>len</parameter></paramdef>
<paramdef>char *<parameter>buf</parameter></paramdef>
</funcsynopsis>
This puts the UTF-8 encoding of a region of the
string <parameter>str</parameter> into
the buffer <parameter>buf</parameter>.
The region of the string to fetch is specifued by
<parameter>start</parameter> and <parameter>len</parameter>.
It is assumed that <parameter>buf</parameter> is big enough
to hold the result. Note
that <parameter>buf</parameter> is <emphasis>not</emphasis> null-terminated.
</para>
</sect1>
<sect1><title>Class Initialization</title>
<para>
Java requires that each class be automatically initialized at the time
of the first active use. Initializing a class involves
initializing the static fields, running code in class initializer
methods, and initializing base classes. There may also be
some implementation specific actions, such as allocating
<classname>String</classname> objects corresponding to string literals in
the code.</para>
<para>
The Gcj compiler inserts calls to <literal>JvInitClass</literal> (actually
<literal>_Jv_InitClass</literal>) at appropriate places to ensure that a
class is initialized when required. The C++ compiler does not
insert these calls automatically - it is the programmer's
responsibility to make sure classes are initialized. However,
this is fairly painless because of the conventions assumed by the Java
system.</para>
<para>
First, <literal>libgcj</literal> will make sure a class is initialized
before an instance of that object is created. This is one
of the responsibilities of the <literal>new</literal> operation. This is
taken care of both in Java code, and in C++ code. (When the G++
compiler sees a <literal>new</literal> of a Java class, it will call
a routine in <literal>libgcj</literal> to allocate the object, and that
routine will take care of initializing the class.) It follows that you can
access an instance field, or call an instance (non-static)
method and be safe in the knowledge that the class and all
of its base classes have been initialized.</para>
<para>
Invoking a static method is also safe. This is because the
Java compiler adds code to the start of a static method to make sure
the class is initialized. However, the C++ compiler does not
add this extra code. Hence, if you write a native static method
using CNI, you are responsible for calling <literal>JvInitClass</literal>
before doing anything else in the method (unless you are sure
it is safe to leave it out).</para>
<para>
Accessing a static field also requires the class of the
field to be initialized. The Java compiler will generate code
to call <literal>_Jv_InitClass</literal> before getting or setting the field.
However, the C++ compiler will not generate this extra code,
so it is your responsibility to make sure the class is
initialized before you access a static field.</para>
</sect1>
<sect1><title>Exception Handling</title>
<para>
While C++ and Java share a common exception handling framework,
things are not quite as integrated as we would like, yet.
The main issue is the incompatible exception <emphasis>values</emphasis>,
and that the <quote>run-time type information</quote> facilities of the
two languages are not integrated.</para>
<para>
Basically, this means that you cannot in C++ catch an exception
value (<classname>Throwable</classname>) thrown from Java code, nor
can you use <literal>throw</literal> on a Java exception value from C++ code,
and expect to be able to catch it in Java code.
We do intend to change this.</para>
<para>
You can throw a Java exception from C++ code by using
the <literal>JvThrow</literal> <acronym>CNI</acronym> function.
<funcsynopsis>
<funcdef>void <function>JvThrow</function></funcdef>
<paramdef>jobject <parameter>obj</parameter></paramdef>
</funcsynopsis>
Throws an exception <parameter>obj</parameter>, in a way compatible
with the Java exception-handling functions.
The class of <parameter>obj</parameter> must be a subclass of
<literal>Throwable</literal>.
</para>
<para>
Here is an example:
<programlisting>
if (i >= count)
JvThrow (new java::lang::IndexOutOfBoundsException());
</programlisting>
</para>
</sect1>
<sect1><title>Synchronization</title>
<para>
Each Java object has an implicit monitor.
The Java VM uses the instruction <literal>monitorenter</literal> to acquire
and lock a monitor, and <literal>monitorexit</literal> to release it.
The JNI has corresponding methods <literal>MonitorEnter</literal>
and <literal>MonitorExit</literal>. The corresponding CNI macros
are <literal>JvMonitorEnter</literal> and <literal>JvMonitorExit</literal>.
</para>
<para>
The Java source language does not provide direct access to these primitives.
Instead, there is a <literal>synchronized</literal> statement that does an
implicit <literal>monitorenter</literal> before entry to the block,
and does a <literal>monitorexit</literal> on exit from the block.
Note that the lock has to be released even the block is abnormally
terminated by an exception, which means there is an implicit
<literal>try</literal>-<literal>finally</literal>.
</para>
<para>
From C++, it makes sense to use a destructor to release a lock.
CNI defines the following utility class.
<programlisting>
class JvSynchronize() {
jobject obj;
JvSynchronize(jobject o) { obj = o; JvMonitorEnter(o); }
~JvSynchronize() { JvMonitorExit(obj); }
};
</programlisting>
The equivalent of Java's:
<programlisting>
synchronized (OBJ) { CODE; }
</programlisting>
can be simply expressed:
<programlisting>
{ JvSynchronize dummy(OBJ); CODE; }
</programlisting>
</para>
<para>
Java also has methods with the <literal>synchronized</literal> attribute.
This is equivalent to wrapping the entire method body in a
<literal>synchronized</literal> statement.
(Alternatively, an implementation could require the caller to do
the synchronization. This is not practical for a compiler, because
each virtual method call would have to test at run-time if
synchronization is needed.) Since in <literal>gcj</literal>
the <literal>synchronized</literal> attribute is handled by the
method implementation, it is up to the programmer
of a synchronized native method to handle the synchronization
(in the C++ implementation of the method).
In otherwords, you need to manually add <literal>JvSynchronize</literal>
in a <literal>native synchornized</literal> method.</para>
</sect1>
<sect1><title>Reflection</title>
<para>The types <literal>jfieldID</literal> and <literal>jmethodID</literal>
are as in JNI.</para>
<para>
The function <literal>JvFromReflectedField</literal>,
<literal>JvFromReflectedMethod</literal>,
<literal>JvToReflectedField</literal>, and
<literal>JvToFromReflectedMethod</literal> (as in Java 2 JNI)
will be added shortly, as will other functions corresponding to JNI.</para>
<sect1><title>Using gcjh</title>
<para>
The <command>gcjh</command> is used to generate C++ header files from
Java class files. By default, <command>gcjh</command> generates
a relatively straightforward C++ header file. However, there
are a few caveats to its use, and a few options which can be
used to change how it operates:
</para>
<variablelist>
<varlistentry>
<term><literal>--classpath</literal> <replaceable>path</replaceable></term>
<term><literal>--CLASSPATH</literal> <replaceable>path</replaceable></term>
<term><literal>-I</literal> <replaceable>dir</replaceable></term>
<listitem><para>
These options can be used to set the class path for gcjh.
Gcjh searches the class path the same way the compiler does;
these options have their familiar meanings.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>-d <replaceable>directory</replaceable></literal></term>
<listitem><para>
Puts the generated <literal>.h</literal> files
beneath <replaceable>directory</replaceable>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>-o <replaceable>file</replaceable></literal></term>
<listitem><para>
Sets the name of the <literal>.h</literal> file to be generated.
By default the <literal>.h</literal> file is named after the class.
This option only really makes sense if just a single class file
is specified.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>--verbose</literal></term>
<listitem><para>
gcjh will print information to stderr as it works.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>-M</literal></term>
<term><literal>-MM</literal></term>
<term><literal>-MD</literal></term>
<term><literal>-MMD</literal></term>
<listitem><para>
These options can be used to generate dependency information
for the generated header file. They work the same way as the
corresponding compiler options.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>-prepend <replaceable>text</replaceable></literal></term>
<listitem><para>
This causes the <replaceable>text</replaceable> to be put into the generated
header just after class declarations (but before declaration
of the current class). This option should be used with caution.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>-friend <replaceable>text</replaceable></literal></term>
<listitem><para>
This causes the <replaceable>text</replaceable> to be put into the class
declaration after a <literal>friend</literal> keyword.
This can be used to declare some
other class or function to be a friend of this class.
This option should be used with caution.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>-add <replaceable>text</replaceable></literal></term>
<listitem><para>
The <replaceable>text</replaceable> is inserted into the class declaration.
This option should be used with caution.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>-append <replaceable>text</replaceable></literal></term>
<listitem><para>
The <replaceable>text</replaceable> is inserted into the header file
after the class declaration. One use for this is to generate
inline functions. This option should be used with caution.
</listitem>
</varlistentry>
</variablelist>
<para>
All other options not beginning with a <literal>-</literal> are treated
as the names of classes for which headers should be generated.</para>
<para>
gcjh will generate all the required namespace declarations and
<literal>#include</literal>'s for the header file.
In some situations, gcjh will generate simple inline member functions.</para>
<para>
There are a few cases where gcjh will fail to work properly:</para>
<para>
gcjh assumes that all the methods and fields of a class have ASCII
names. The C++ compiler cannot correctly handle non-ASCII
identifiers. gcjh does not currently diagnose this problem.</para>
<para>
gcjh also cannot fully handle classes where a field and a method have
the same name. If the field is static, an error will result.
Otherwise, the field will be renamed in the generated header; `__'
will be appended to the field name.</para>
<para>
Eventually we hope to change the C++ compiler so that these
restrictions can be lifted.</para>
</sect1>
</article>

155
libjava/exception.cc Normal file
View file

@ -0,0 +1,155 @@
// Functions for Exception Support for Java.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#include "exception"
#include <stddef.h>
#include <java/lang/Class.h>
#include <java/lang/NullPointerException.h>
#include <cni.h>
#include <jvm.h>
// eh-common.h needs gansidecl.h.
#include "gansidecl.h"
#include "eh-common.h"
typedef struct {
__eh_info eh_info;
void *value;
} java_eh_info;
/* Language-specific EH info pointer, throw routine, and language/version
info routines. All defined in libgcc2. */
extern "C" java_eh_info **__get_eh_info ();
extern "C" void __throw () __attribute__ ((__noreturn__));
extern "C" short __get_eh_table_version (void *table);
extern "C" short __get_eh_table_language (void *table);
extern "C" void * malloc (size_t);
extern "C" void free (void *);
extern "C" void *
_Jv_type_matcher (java_eh_info *info, void* match_info,
void *exception_table)
{
if (__get_eh_table_language (exception_table) != EH_LANG_Java)
return NULL;
/* we don't worry about version info yet, there is only one version! */
if (match_info != NULL)
{
// The match_info is either a (java::lang::Class*) or
// match_info is one more than a (Utf8Const*).
if (sizeof(void*) != sizeof(size_t))
abort();
size_t mi = (size_t) match_info;
if ((mi & 1) != 0)
match_info = _Jv_FindClass ((Utf8Const*) (mi - 1), NULL);
if (! _Jv_IsInstanceOf ((jobject) info->value, (jclass) match_info))
return NULL;
}
return info->value;
}
/* Compiler hook to return a pointer to java exception object. The value
is cleared, so if the exception needs to be rethrown, it should be set
again */
extern "C" void *
_Jv_exception_info (void)
{
java_eh_info *info = *(__get_eh_info ());
void *ptr;
if (info == NULL)
abort ();
ptr = info->value;
/* clear the value so another throw is an error */
info->value = NULL;
return ptr;
}
/* Allocate an exception info structure for java. Called the first time
an exception is thrown. */
extern "C" void
_Jv_eh_alloc ()
{
/* FIXME: we should use _Jv_AllocBytes here. However, libgcc2
apparently can sometimes free() this value itself. */
java_eh_info *p = (java_eh_info *) malloc (sizeof (java_eh_info));
if (p == 0)
terminate ();
p->value = 0;
java_eh_info ** info_ptr = __get_eh_info ();
/* There should NOT be an exception info pointer already. */
if (*info_ptr != NULL)
abort ();
*info_ptr = p;
}
/* Deallocate the current exception info structure. Called at shutdown time. */
extern "C" void
_Jv_eh_free ()
{
java_eh_info ** info_ptr = __get_eh_info ();
if (*info_ptr == NULL)
abort ();
/* FIXME: ideally we should just let the GC handle this. */
free (*info_ptr);
*info_ptr = NULL;
}
/* Perform a throw, Java style. Throw will unwind through this call, so
there better not be any handlers or exception thrown here. */
/* Initialize an __eh_info structure with this libraries matching info. */
extern "C" void
_Jv_setup_eh_info (__eh_info *)
{
}
extern "C" void
_Jv_Throw (void *value)
{
if (value == NULL)
value = (void *) new java::lang::NullPointerException ();
java_eh_info *ehinfo = *(__get_eh_info ());
if (ehinfo == NULL)
{
_Jv_eh_alloc ();
ehinfo = *(__get_eh_info ());
}
ehinfo->eh_info.match_function = _Jv_type_matcher;
ehinfo->eh_info.language = EH_LANG_Java;
ehinfo->eh_info.version = 1;
ehinfo->value = value;
__throw();
}

View file

@ -0,0 +1,105 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.convert;
public abstract class BytesToUnicode
{
/** Buffer to read bytes from.
* The characters inbuffer[inpos] ... inbuffer[inlength-1] are available. */
public byte[] inbuffer;
/** Starting index in buffer to read bytes from. */
public int inpos;
/** End of valid bytes in buffer. */
public int inlength;
static Class defaultDecodingClass;
static synchronized void getDefaultDecodingClass()
{
// Test (defaultDecodingClass == null) again in case of race condition.
if (defaultDecodingClass == null)
{
String encoding = System.getProperty("file.encoding");
String className = "gnu.gcj.convert.Input_"+encoding;
try
{
defaultDecodingClass = Class.forName(className);
}
catch (ClassNotFoundException ex)
{
throw new NoClassDefFoundError("missing default encoding "
+ encoding + " (class "
+ className + " not found)");
}
}
}
public abstract String getName();
public static BytesToUnicode getDefaultDecoder()
{
try
{
if (defaultDecodingClass == null)
getDefaultDecodingClass();
return (BytesToUnicode) defaultDecodingClass.newInstance();
}
catch (Throwable ex)
{
return new Input_8859_1();
}
}
/** Get a byte-stream->char-stream converter given an encoding name. */
public static BytesToUnicode getDecoder (String encoding)
throws java.io.UnsupportedEncodingException
{
String className = "gnu.gcj.convert.Input_"+encoding;
Class decodingClass;
try
{
decodingClass = Class.forName(className);
return (BytesToUnicode) decodingClass.newInstance();
}
catch (Throwable ex)
{
throw new java.io.UnsupportedEncodingException(encoding
+ " (" + ex + ')');
}
}
/** Make input bytes available to the conversion.
* @param buffer source of input bytes
* @param pos index of first available byte
* @param length one more than index of last available byte
*/
public final void setInput(byte[] buffer, int pos, int length)
{
inbuffer = buffer;
inpos = pos;
inlength = length;
}
/** Convert bytes to chars.
* Input bytes are taken from this.inbuffer. The available input
* bytes start at inbuffer[inpos], and end at inbuffer[inlength-1].
* @param outbuffer buffer for the converted character
* @param outpos position in buffer to start putting converted characters
* @param outlength the maximum number of characters to read
* @return number of chars placed in outbuffer.
* Also, this.inpos is incremented by the number of bytes consumed.
*
* (Note the asymmetry in that the input upper bound is inbuffer[inlength-1],
* while the output upper bound is outbuffer[outpos+outlength-1]. The
* justification is that inlength is like the count field of a
* BufferedInputStream, while the outlength parameter is like the
* length parameter of a read request.)
*/
public abstract int read (char[] outbuffer, int outpos, int outlength);
}

View file

@ -0,0 +1,151 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.convert;
import java.io.*;
public class Convert
{
static void error (String message)
{
System.err.print("convert: ");
System.err.println(message);
System.err.println("Usage: convert [--from srcEncoding] [--to dstEncoding]");
System.err.println(" [inputfile [outputfile]]");
System.exit(-1);
}
static void missing (String arg)
{
error("missing arg after `" + arg + "' option");
}
public static void main (String[] args)
{
String inName = "-";
String outName = "-";
String inEncodingName = null;
String outEncodingName = "JavaSrc";
int seenNames = 0;
boolean reverse = false;
for (int i = 0; i < args.length; i++)
{
String arg = args[i];
if (arg.length() == 0)
error("zero-length argument");
if (arg.charAt(0) == '-')
{
if (arg.equals("-encoding") || arg.equals("--encoding")
|| args.equals("-from") || arg.equals("--from"))
{
if (++i == args.length) missing(arg);
inEncodingName = args[i];
}
else if (arg.equals("-to") || arg.equals("--to"))
{
if (++i == args.length) missing(arg);
outEncodingName = args[i];
}
else if (arg.equals("-i"))
{
if (++i == args.length) missing(arg);
inName = args[i];
}
else if (arg.equals("-o"))
{
if (++i == args.length) missing(arg);
outName = args[i];
}
else if (arg.equals("-reverse") || arg.equals("--reverse"))
{
reverse = true;
}
else if (arg.equals("-"))
{
switch (seenNames)
{
case 0:
inName = "-";
seenNames++;
break;
case 1:
outName = "-";
seenNames++;
break;
default:
error("too many `-' arguments");
}
}
else
error("unrecognized argument `" + arg + "'");
}
else
{
switch (seenNames)
{
case 0:
inName = arg;
seenNames++;
break;
case 1:
outName = arg;
seenNames++;
break;
default:
error("too many filename arguments");
}
}
}
if (reverse)
{
String tmp = inEncodingName;
inEncodingName = outEncodingName;
outEncodingName = tmp;
}
try
{
BytesToUnicode inDecoder
= inEncodingName == null ? BytesToUnicode.getDefaultDecoder()
: BytesToUnicode.getDecoder(inEncodingName);
UnicodeToBytes outEncoder
= outEncodingName == null ? UnicodeToBytes.getDefaultEncoder()
: UnicodeToBytes.getEncoder(outEncodingName);
InputStream inStream = inName == "-" ? System.in
: new FileInputStream(inName);
OutputStream outStream;
if (outName == "-")
outStream = System.out;
else
outStream = new FileOutputStream(outName);
InputStreamReader in
= new InputStreamReader(inStream, inEncodingName);
OutputStreamWriter out
= new OutputStreamWriter(outStream, outEncodingName);
char[] buffer = new char[2048];
for (;;)
{
int count = in.read(buffer);
if (count < 0)
break;
out.write(buffer, 0, count);
}
in.close();
out.close();
}
catch (java.io.IOException ex)
{
System.err.print("convert exception: ");
System.err.println(ex);
System.exit(-1);
}
}
}

View file

@ -0,0 +1,32 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.convert;
public class Input_8859_1 extends BytesToUnicode
{
public String getName() { return "8859_1"; }
public int read (char[] outbuffer, int outpos, int outlength)
{
int origpos = outpos;
// Make sure fields of this are in registers.
int inpos = this.inpos;
byte[] inbuffer = this.inbuffer;
int inavail = this.inlength - inpos;
int outavail = outlength - outpos;
if (outavail > inavail)
outavail = inavail;
while (--outavail >= 0)
{
outbuffer[outpos++] = (char) (inbuffer[inpos++] & 0xFF);
}
this.inpos = inpos;
return outpos - origpos;
}
}

View file

@ -0,0 +1,19 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.convert;
public class Input_EUCJIS extends BytesToUnicode
{
public String getName() { return "EUCJIS"; }
int codeset = 0;
int first_byte;
public native int read (char[] outbuffer, int outpos, int outlength);
}

View file

@ -0,0 +1,107 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.convert;
public class Input_UTF8 extends BytesToUnicode
{
public String getName() { return "UTF8"; }
int partial = 0;
int partial_bytes_expected = 0;
//int suggogate_second = -1;
public int read (char[] outbuffer, int outpos, int outlength)
{
int origpos = outpos;
for (;;)
{
if (outpos >= outlength)
break;
if (inpos >= inlength)
break;
int b = inbuffer[inpos++];
if (b >= 0)
outbuffer[outpos++] = (char) b;
else
{
if ((b & 0xC0) == 0x80) // Continuation byte
{
partial = (partial << 6) | (b & 0x3F);
--partial_bytes_expected;
if (partial_bytes_expected == 1)
{
if (partial > (0xFFFF>>6))
{
// The next continuation byte will cause the result
// to exceed 0xFFFF, so we must use a surrogate pair.
// The "Unicode scalar value" (see D28 in section 3.7
// of the Unicode Standard 2.0) is defined as:
// value == (hi-0xD800)*0x400+(lo-0xDC00)+0x10000,
// where (hi, lo) is the Unicode surrogate pair.
// After reading the first three bytes, we have:
// partial == (value >> 6).
// Substituting and simplifying, we get:
// partial == (hi-0xD800)*0x10+((lo-0xDC00)>>6)+0x400.
// The definition lo>=0xDC00 && lo<=0xDFFF implies
// that (lo-0xDC00)>>6 is in the range 0..15.
// Hence we can infer (partial-0x400)>>4 == (hi-0xDB00)
// and we can emit the high-surrogate without waiting
// for the final byte:
outbuffer[outpos++] = (char) (0xDA00+(partial>>4));
// Now we want to set it up so that when we read
// the final byte on the next iteration, we will
// get the low-surrogate without special handling.
// I.e. we want:
// lo == (next_partial << 6) | (next & 0x3F)
// where next is the next input byte and next_partial
// is the value of partial at the end of this
// iteration. This implies: next_partial == lo >> 6.
// We can simplify the previous:
// partial == (hi-0xD800)*0x10+((lo-0xDC00)>>6)+0x400,
// to: partial == (hi-0xD800)*0x10+(lo>>6)+0x90.
// Inserting the values of hi and next_partial,
// and simplifying, we get: partial ==
// ( (partial-0x400)&~0xF) + next_partial + 0x90.
// Solving for next_partial, we get:
// next_partial = partial+0x400-0x90-(partial&~0xF):
// or: next_partial = (partial&0xF) + 0x370. Hence:
partial = (partial & 0xF) + 0x370;
}
}
else if (partial_bytes_expected == 0)
{
outbuffer[outpos++] = (char) partial;
partial = 0;
partial_bytes_expected = 0;
}
}
else // prefix byte
{
if ((b & 0xE) == 0xC0)
{
partial = b & 0x1F;
partial_bytes_expected = 1;
}
else if ((b & 0xF) == 0xF0)
{
partial = b & 0xF;
partial_bytes_expected = 2;
}
else
{
partial = b & 7;
partial_bytes_expected = 3;
}
}
}
}
return outpos - origpos;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.convert;
public class Output_8859_1 extends UnicodeToBytes
{
public String getName() { return "8859_1"; }
/**
* @return number of chars converted. */
public int write (char[] inbuffer, int inpos, int inlength)
{
int count = this.count;
byte[] buf = this.buf;
int avail = buf.length - count;
if (inlength > avail)
inlength = avail;
for (int i = inlength; --i >= 0; )
{
buf[count++] = (byte) inbuffer[inpos++];
}
this.count = count;
return inlength;
}
}

View file

@ -0,0 +1,82 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.convert;
/** Convert Unicode to Ascii with \ u XXXX-escapes. */
public class Output_JavaSrc extends UnicodeToBytes
{
public String getName() { return "JavaSrc"; }
// Number of bytes remaining before pending_char has been written.
int todo;
int pending_char;
public int write (char[] inbuffer, int inpos, int inlength)
{
int start_pos = inpos;
int avail = buf.length - count;
for (;;)
{
if (avail == 0)
break;
switch (todo)
{
case 1:
if (pending_char == '\\')
{
buf[count++] = (byte) '\\';
avail--;
todo = 0;
continue;
}
/* ... else fall through ... */
case 2:
case 3:
case 4:
todo--;
int digit = ((int) pending_char >> (todo * 4)) & 0xF;
buf[count++] = (byte) Character.forDigit(digit, 16);
avail--;
continue;
case 5:
buf[count++] = (byte) 'u';
avail--;
todo = 4;
continue;
default:
;
}
if (inlength == 0)
break;
char ch = inbuffer[inpos++];
inlength--;
if (ch == '\\')
{
buf[count++] = (byte) '\\';
pending_char = ch;
todo = 1;
avail--;
}
else if (ch < 127)
{
buf[count++] = (byte) ch;
avail--;
}
else
{
buf[count++] = (byte) '\\';
pending_char = ch;
todo = 5;
avail--;
}
}
return inpos - start_pos;
}
}

View file

@ -0,0 +1,108 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.convert;
public class Output_UTF8 extends UnicodeToBytes
{
public String getName() { return "UTF8"; }
/** True if a surrogate pair should be emitted as a single UTF8 sequence.
* Otherwise, a surrogate pair is treated as two separate characters.
* Also, '\0' is emitted as {0} if true, and as {0xC0,0x80} if false. */
public boolean standardUTF8;
// Saves the previous char if it was a high-surrogate.
char hi_part;
// Value of imcomplete character.
int value;
// Number of continuation bytes still to emit.
int bytes_todo;
public int write (char[] inbuffer, int inpos, int inlength)
{
int start_pos = inpos;
int avail = buf.length - count;
for (;;)
{
if (inlength == 0 || avail == 0)
break;
// The algororith is made more complicated because we want to write
// at least one byte in the output buffer, if there is room for
// that byte, and at least one input character is available.
// This makes the code more robust, since client code will
// always "make progress", even in the complicated cases,
// where the output buffer only has room for only *part* of a
// multi-byte sequence, or the input char buffer only has half
// of a surrogate pair (when standardUTF8 is set), or both.
// Handle continuation characters we did not have room for before.
if (bytes_todo > 0)
{
do
{
bytes_todo--;
buf[count++] = (byte)
(((value >> (bytes_todo * 6)) & 0xC0) | 0x80);
avail--;
}
while (bytes_todo > 0 && avail > 0);
continue;
}
char ch = inbuffer[inpos++];
inlength--;
if (ch < 128 && (ch != 0 || standardUTF8))
{
avail--;
buf[count++] = (byte) ch;
}
else if (ch <= 0x07FF)
{
buf[count++] = (byte) (0xC0 | (ch >> 6));
if (--avail > 0)
{
buf[count++] = (byte) ((ch & 0x3F) | 0x80);
avail--;
}
else
{
value = ch;
bytes_todo = 1;
break;
}
}
else if (ch >= 0xD800 && ch <= 0xDFFF && standardUTF8)
{
if (ch <= 0xDBFF) // High surrogates
{
// The first byte is (0xF0 | value>>18), where value is the
// Unicode scalar value of the combine character - which
// we may not know yet. But from substituting:
// value == (hi-0xD800)*0x400+(lo-0xDC00)+0x10000,
// hi==ch, and cancelling we get:
buf[count++] = (byte) (0xF0 | ((ch-0xD800) >> 8));
avail--;
hi_part = ch;
}
else // Low surrogates
{
value = (hi_part - 0xD800) * 0x400 + (ch - 0xDC00) + 0x10000;
bytes_todo = 3;
}
}
else
{
buf[count++] = (byte) (0xE0 | (ch >> 12));
value = ch;
avail--;
bytes_todo = 2;
}
}
return inpos - start_pos;
}
}

View file

@ -0,0 +1,90 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.convert;
public abstract class UnicodeToBytes
{
/** Buffer to emit bytes to.
* The locations buf[count] ... buf[buf.length-1] are available. */
public byte[] buf;
public int count;
static Class defaultEncodingClass;
static synchronized void getDefaultEncodingClass()
{
// Test (defaultEncodingClass == null) again in case of race condition.
if (defaultEncodingClass == null)
{
String encoding = System.getProperty("file.encoding");
String className = "gnu.gcj.convert.Output_"+encoding;
try
{
defaultEncodingClass = Class.forName(className);
}
catch (ClassNotFoundException ex)
{
throw new NoClassDefFoundError("missing default encoding "
+ encoding + " (class "
+ className + " not found)");
}
}
}
public abstract String getName();
public static UnicodeToBytes getDefaultEncoder()
{
try
{
if (defaultEncodingClass == null)
getDefaultEncodingClass();
return (UnicodeToBytes) defaultEncodingClass.newInstance();
}
catch (Throwable ex)
{
return new Output_8859_1();
}
}
/** Get a char-stream->byte-stream converter given an encoding name. */
public static UnicodeToBytes getEncoder (String encoding)
throws java.io.UnsupportedEncodingException
{
String className = "gnu.gcj.convert.Output_"+encoding;
Class encodingClass;
try
{
encodingClass = Class.forName(className);
return (UnicodeToBytes) encodingClass.newInstance();
}
catch (Throwable ex)
{
throw new java.io.UnsupportedEncodingException(encoding + " ("
+ ex + ')');
}
}
public final void setOutput(byte[] buffer, int count)
{
this.buf = buffer;
this.count = count;
}
/** Convert chars to bytes.
* Converted bytes are written to buf, starting at count.
* @param inbuffer sources of characters to convert
* @param inpos index of initial character ininbuffer to convert
* @param inlength number of characters to convert
* @return number of chars converted
* Also, this.count is increment by the number of bytes converted.
*/
public abstract int write (char[] inbuffer, int inpos, int inlength);
}

View file

@ -0,0 +1,154 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <stdio.h>
struct chval
{
unsigned char b1; /* 1st byte */
unsigned char b2; /* 2nd byte */
unsigned short uc; /* unicode value */
};
#define MAP(B1, B2, C) { B1, B2, C },
struct chval chtab_0208[] = {
#include "JIS0208.h"
{ 255, 255, 0}
};
struct chval chtab_0212[] = {
#include "JIS0212.h"
{ 255, 255, 0}
};
#undef MAP
struct chval sorted[] = {
#define MAP(B1, B2, C) { B1, B2, C },
#include "JIS0208.h"
#undef MAP
#define MAP(B1, B2, C) { 0x80|B1, B2, C },
#include "JIS0212.h"
#undef MAP
};
struct chval *chtab;
int
compare (void *p1, void *p2)
{
struct chval *c1 = (struct chval *) p1;
struct chval *c2 = (struct chval *) p2;
return (int) c1->uc - (int) c2->uc;
}
int
main(int argc, char** argv)
{
FILE *out = stdout;
unsigned min1 = 256, max1 = 0, min2 = 256, max2 = 0, count = 0;
unsigned short low1_uc = 0xFFFF, high1_uc = 0;
unsigned short low2_uc = 0xFFFF, high2_uc = 0;
int i; int row, col;
if (strcmp (argv[1], "JIS0208") == 0)
chtab = chtab_0208;
else if (strcmp (argv[1], "JIS0212") == 0)
chtab = chtab_0212;
else if (strcmp (argv[1], "toJIS") == 0)
{
int i;
int count = sizeof(sorted)/sizeof(struct chval);
qsort (sorted, count, sizeof(struct chval),
compare);
for (i = 0; i < count; i++)
{
fprintf (out, " 0x%04x -> 0x%02x, 0x%02x\n",
sorted[i].uc, sorted[i].b1, sorted[i].b2);
}
exit(0);
}
else
{
fprintf (stderr, "bad argument!");
exit (-1);
}
for (i = 0; chtab[i].b1 != 255; i++)
{
if (chtab[i].b1 < min1) min1 = chtab[i].b1;
if (chtab[i].b2 < min2) min2 = chtab[i].b2;
if (chtab[i].b1 > max1) max1 = chtab[i].b1;
if (chtab[i].b2 > max2) max2 = chtab[i].b2;
count++;
}
fprintf(stderr, "1st byte ranges from %d to %d.\n", min1, max1);
fprintf(stderr, "2nd byte ranges from %d to %d.\n", min2, max2);
fprintf(out,"/* This file is automatically generated from %s.TXT. */\n",
argv[1]);
fprintf(out, "unsigned short %s_to_Unicode[%d][%d] = {\n",
argv[1], max1 - min1 + 1, max2 - min2 + 1);
i = 0;
for (row = min1; row <= max1; row++)
{
fprintf(out, "/* 1st byte: %d */ { ", row);
if (row < chtab[i].b1)
{
fprintf(out, "0 }, /* unused row */\n");
}
else if (row > chtab[i].b1)
{
fprintf (stderr, "error - char table out of order!\n");
exit (-1);
}
else
{
fprintf(out, "\n");
for (col = min2; col <= max2; col++)
{
if (row == chtab[i].b1 && col == chtab[i].b2)
{
unsigned uc = chtab[i].uc;
if (uc < 0x2000)
{
if (uc > high1_uc)
high1_uc = uc;
if (uc < low1_uc)
low1_uc = uc;
}
else
{
if (uc > high2_uc)
high2_uc = uc;
if (uc < low2_uc)
low2_uc = uc;
}
fprintf (out, " /* 2nd byte: %d */ 0x%04x",
chtab[i].b2, uc);
i++;
}
else if (row < chtab[i].b1
|| (row == chtab[i].b1 && col < chtab[i].b2))
{
fprintf (out, " 0");
}
else
{
fprintf (stderr, "error - char table our of order!\n");
exit (-1);
}
if (col != max2)
fprintf (out, ",\n");
}
fprintf(out, row == max1 ? "}\n" : "},\n");
}
}
fprintf(out, "};\n");
fprintf(stderr, "total number of characters is %d.\n", count);
fprintf(stderr, "Range is 0x%04x-0x%04x and 0x%04x-0x%04x.\n",
low1_uc, high1_uc, low2_uc, high2_uc);
return 0;
}

View file

@ -0,0 +1,101 @@
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#include <cni.h>
#include <gnu/gcj/convert/Input_EUCJIS.h>
#define ERROR_CHAR 0xFFFD
extern unsigned short JIS0208_to_Unicode[84][94];
extern unsigned short JIS0212_to_Unicode[76][94];
jint
gnu::gcj::convert::Input_EUCJIS::read(jcharArray outbuffer, jint outpos,
jint outlength)
{
jint start_outpos = outpos;
for (;;)
{
if (outpos >= outlength)
break;
if (inpos >= inlength)
break;
int b = ((unsigned char*) elements(inbuffer))[inpos++];
if (codeset == 0) // ASCII or JIS-Roman
{
if (b < 128)
{
#if 0
// Technically, we should translate 0x5c to Yen symbol;
// in practice, it is not clear.
if (b == 0x5c)
b = 0x00A5; // Yen sign.
#endif
elements(outbuffer)[outpos++] = (char) b;
}
else
{
if (b == 0x8E) // SS2
codeset = 2;
else if (b == 0x8F) // SS3
codeset = 3;
else
{
codeset = 1;
first_byte = b;
}
}
}
else if (codeset == 1) // JIS X 0208:1997
{
first_byte -= 0x80 + 33;
b -= 0x80 + 33;
if ((unsigned) first_byte >= 84 || (unsigned) b >= 94)
b = ERROR_CHAR;
else
{
b = JIS0208_to_Unicode[first_byte][b];
if (b == 0)
b = ERROR_CHAR;
}
elements(outbuffer)[outpos++] = b;
codeset = 0;
}
else if (codeset == 2) // Half-width katakana
{
if (b >= 0xA1 && b <= 0xDF)
b += 0xFF61 - 0xA1;
else
b = ERROR_CHAR;
elements(outbuffer)[outpos++] = b;
codeset = 0;
}
else if (codeset == 3) // second byte of JIS X 0212-1990
{
first_byte = b;
codeset = 4;
}
else // codeset == 4 // third byte of JIS X 0212-1990
{
first_byte -= 0x80 + 34;
b -= 0x80 + 33;
if ((unsigned) first_byte >= 76 || (unsigned) b >= 94)
b = ERROR_CHAR;
else
{
b = JIS0208_to_Unicode[first_byte][b];
if (b == 0)
b = ERROR_CHAR;
}
elements(outbuffer)[outpos++] = b;
codeset = 0;
}
}
return outpos - start_outpos;
}

View file

@ -0,0 +1,285 @@
// Connection.java - Implementation of HttpURLConnection for http protocol.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.protocol.http;
import java.net.*;
import java.io.*;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date March 29, 1999.
*/
/**
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
* Status: Minimal subset of functionality. Proxies and Redirects
* not yet handled. FileNameMap handling needs to be considered.
* useCaches, ifModifiedSince, and allowUserInteraction need
* consideration as well as doInput and doOutput.
*/
class Connection extends HttpURLConnection
{
protected Socket sock = null;
private static Hashtable defRequestProperties = new Hashtable();
private Hashtable requestProperties;
private Hashtable hdrHash = new Hashtable();
private Vector hdrVec = new Vector();
private boolean gotHeaders = false;
private BufferedInputStream bufferedIn;
public Connection(URL url)
{
super(url);
requestProperties = (Hashtable) defRequestProperties.clone();
}
// Override method in URLConnection.
public static void setDefaultRequestProperty(String key, String value)
{
defRequestProperties.put(key, value);
}
// Override method in URLConnection.
public static String getDefaultRequestProperty(String key)
{
return (String) defRequestProperties.get(key);
}
// Override method in URLConnection.
public void setRequestProperty(String key, String value)
{
if (connected)
throw new IllegalAccessError("Connection already established.");
requestProperties.put(key, value);
}
// Override method in URLConnection.
public String getRequestProperty(String key)
{
if (connected)
throw new IllegalAccessError("Connection already established.");
return (String) requestProperties.get(key);
}
// Implementation of abstract method.
public void connect() throws IOException
{
// Call is ignored if already connected.
if (connected)
return;
// Get address and port number.
int port;
InetAddress destAddr = InetAddress.getByName(url.getHost());
if ((port = url.getPort()) == -1)
port = 80;
// Open socket and output stream.
sock = new Socket(destAddr, port);
PrintWriter out = new PrintWriter(sock.getOutputStream());
// Send request including any request properties that were set.
out.print(getRequestMethod() + " " + url.getFile() + " HTTP/1.1\n");
out.print("Host: " + url.getHost() + ":" + port + "\n");
Enumeration reqKeys = requestProperties.keys();
Enumeration reqVals = requestProperties.elements();
while (reqKeys.hasMoreElements())
out.print(reqKeys.nextElement() + ": " + reqVals.nextElement() + "\n");
out.print("\n");
out.flush();
connected = true;
}
// Implementation of abstract method.
public void disconnect()
{
if (sock != null)
{
try
{
sock.close();
}
catch (IOException ex)
{
; // Ignore errors in closing socket.
}
sock = null;
}
connected = false;
}
// TODO: public boolean usingProxy()
public boolean usingProxy()
{
throw new InternalError("HttpURLConnection.usingProxy not implemented");
}
// Override default method in URLConnection.
public InputStream getInputStream() throws IOException
{
if (!connected)
connect();
if (bufferedIn == null)
bufferedIn = new BufferedInputStream(sock.getInputStream());
return bufferedIn;
}
// Override default method in URLConnection.
public OutputStream getOutputStream() throws IOException
{
if (!connected)
connect();
return sock.getOutputStream();
}
// Override default method in URLConnection.
public String getHeaderField(String name)
{
try
{
getHttpHeaders();
}
catch (IOException x)
{
return null;
}
return (String) hdrHash.get(name.toLowerCase());
}
// Override default method in URLConnection.
public String getHeaderField(int n)
{
try
{
getHttpHeaders();
}
catch (IOException x)
{
return null;
}
if (n < hdrVec.size())
return getField((String) hdrVec.elementAt(n));
return null;
}
// Override default method in URLConnection.
public String getHeaderFieldKey(int n)
{
try
{
getHttpHeaders();
}
catch (IOException x)
{
return null;
}
if (n < hdrVec.size())
return getKey((String) hdrVec.elementAt(n));
return null;
}
private String getKey(String str)
{
if (str == null)
return null;
int index = str.indexOf(':');
if (index >= 0)
return str.substring(0, index);
else
return null;
}
private String getField(String str)
{
if (str == null)
return null;
int index = str.indexOf(':');
if (index >= 0)
return str.substring(index + 1).trim();
else
return str;
}
private void getHttpHeaders() throws IOException
{
if (gotHeaders)
return;
gotHeaders = true;
connect();
// Originally tried using a BufferedReader here to take advantage of
// the readLine method and avoid the following, but the buffer read
// past the end of the headers so the first part of the content was lost.
// It is probably more robust than it needs to be, e.g. the byte[]
// is unlikely to overflow and a '\r' should always be followed by a '\n',
// but it is better to be safe just in case.
if (bufferedIn == null)
bufferedIn = new BufferedInputStream(sock.getInputStream());
int buflen = 100;
byte[] buf = new byte[buflen];
String line = "";
boolean gotnl = false;
byte[] ch = new byte[1];
ch[0] = (byte) '\n';
while (true)
{
// Check for leftover byte from non-'\n' after a '\r'.
if (ch[0] != '\n')
line = line + '\r' + new String(ch, 0, 1);
int i;
for (i = 0; i < buflen; i++)
{
bufferedIn.read(buf, i, 1);
if (buf[i] == '\r')
{
bufferedIn.read(ch, 0, 1);
if (ch[0] == '\n')
gotnl = true;
break;
}
}
line = line + new String(buf, 0, i);
// A '\r' '\n' combo indicates the end of the header entry.
// If it wasn't found, cycle back through the loop and append
// to 'line' until one is found.
if (gotnl)
{
// A zero length entry signals the end of the headers.
if (line.length() == 0)
break;
// Store the header and reinitialize for next cycle.
hdrVec.addElement(line);
String key = getKey(line);
if (key != null)
hdrHash.put(key.toLowerCase(), getField(line));
line = "";
ch[0] = (byte) '\n';
gotnl = false;
}
}
}
}

View file

@ -0,0 +1,35 @@
// Handler.java - URLStreamHandler for http protocol.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.protocol.http;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.io.IOException;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date March 26, 1999.
*/
/**
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
* Status: Minimal functionality.
*/
public class Handler extends URLStreamHandler
{
protected URLConnection openConnection(URL url) throws IOException
{
return new Connection(url);
}
}

View file

@ -0,0 +1,82 @@
// Base class for default BreakIterators.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.text;
import java.text.BreakIterator;
import java.text.CharacterIterator;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date March 22, 1999
*/
public abstract class BaseBreakIterator extends BreakIterator
{
public int current ()
{
return iter.getIndex();
}
public int first ()
{
iter.first();
return iter.getBeginIndex();
}
public int following (int pos)
{
int save = iter.getIndex();
iter.setIndex(pos);
int r = next ();
iter.setIndex(save);
return r;
}
public CharacterIterator getText ()
{
return iter;
}
public int last ()
{
iter.last();
return iter.getEndIndex();
}
public int next (int n)
{
int r = iter.getIndex ();
if (n > 0)
{
while (n > 0 && r != DONE)
{
r = next ();
--n;
}
}
else if (n < 0)
{
while (n < 0 && r != DONE)
{
r = previous ();
++n;
}
}
return r;
}
public void setText (CharacterIterator newText)
{
iter = newText;
}
protected CharacterIterator iter;
}

View file

@ -0,0 +1,188 @@
// Default character BreakIterator.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.text;
import java.text.BreakIterator;
import java.text.CharacterIterator;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date March 19, 1999
* Written using The Unicode Standard, Version 2.0.
*/
public class CharacterBreakIterator extends BaseBreakIterator
{
// Hangul Jamo constants from Unicode book.
private static final int LBase = 0x1100;
private static final int VBase = 0x1161;
private static final int TBase = 0x11a7;
private static final int LCount = 19;
private static final int VCount = 21;
private static final int TCount = 28;
// Information about surrogates.
private static final int highSurrogateStart = 0xD800;
private static final int highSurrogateEnd = 0xDBFF;
private static final int lowSurrogateStart = 0xDC00;
private static final int lowSurrogateEnd = 0xDFFF;
public Object clone ()
{
return new CharacterBreakIterator (this);
}
public CharacterBreakIterator ()
{
iter = null; // FIXME?
}
private CharacterBreakIterator (CharacterBreakIterator other)
{
iter = (CharacterIterator) other.iter.clone();
}
// Some methods to tell us different properties of characters.
private final boolean isL (char c)
{
return c >= LBase && c <= LBase + LCount;
}
private final boolean isV (char c)
{
return c >= VBase && c <= VBase + VCount;
}
private final boolean isT (char c)
{
return c >= TBase && c <= TBase + TCount;
}
private final boolean isLVT (char c)
{
return isL (c) || isV (c) || isT (c);
}
private final boolean isHighSurrogate (char c)
{
return c >= highSurrogateStart && c <= highSurrogateEnd;
}
private final boolean isLowSurrogate (char c)
{
return c >= lowSurrogateStart && c <= lowSurrogateEnd;
}
public int next ()
{
int end = iter.getEndIndex();
if (iter.getIndex() == end)
return DONE;
char c;
for (char prev = CharacterIterator.DONE; iter.getIndex() < end; prev = c)
{
c = iter.next();
if (c == CharacterIterator.DONE)
break;
int type = Character.getType(c);
// Break after paragraph separators.
if (type == Character.PARAGRAPH_SEPARATOR)
break;
// Now we need some lookahead.
char ahead = iter.next();
iter.previous();
if (ahead == CharacterIterator.DONE)
break;
int aheadType = Character.getType(ahead);
if (aheadType != Character.NON_SPACING_MARK
&& ! isLowSurrogate (ahead)
&& ! isLVT (ahead))
break;
if (! isLVT (c) && isLVT (ahead))
break;
if (isL (c) && ! isLVT (ahead)
&& aheadType != Character.NON_SPACING_MARK)
break;
if (isV (c) && ! isV (ahead) && !isT (ahead)
&& aheadType != Character.NON_SPACING_MARK)
break;
if (isT (c) && ! isT (ahead)
&& aheadType != Character.NON_SPACING_MARK)
break;
if (! isHighSurrogate (c) && isLowSurrogate (ahead))
break;
if (isHighSurrogate (c) && ! isLowSurrogate (ahead))
break;
if (! isHighSurrogate (prev) && isLowSurrogate (c))
break;
}
return iter.getIndex();
}
public int previous ()
{
if (iter.getIndex() == iter.getBeginIndex())
return DONE;
int start = iter.getBeginIndex();
while (iter.getIndex() >= iter.getBeginIndex())
{
char c = iter.previous();
if (c == CharacterIterator.DONE)
break;
int type = Character.getType(c);
if (type != Character.NON_SPACING_MARK
&& ! isLowSurrogate (c)
&& ! isLVT (c))
break;
// Now we need some lookahead.
char ahead = iter.previous();
if (ahead == CharacterIterator.DONE)
{
iter.next();
break;
}
char ahead2 = iter.previous();
iter.next();
iter.next();
if (ahead2 == CharacterIterator.DONE)
break;
int aheadType = Character.getType(ahead);
if (aheadType == Character.PARAGRAPH_SEPARATOR)
break;
if (isLVT (c) && ! isLVT (ahead))
break;
if (! isLVT (c) && type != Character.NON_SPACING_MARK
&& isL (ahead))
break;
if (! isV (c) && ! isT (c) && type != Character.NON_SPACING_MARK
&& isV (ahead))
break;
if (! isT (c) && type != Character.NON_SPACING_MARK
&& isT (ahead))
break;
if (isLowSurrogate (c) && ! isHighSurrogate (ahead))
break;
if (! isLowSurrogate (c) && isHighSurrogate (ahead))
break;
if (isLowSurrogate (ahead) && ! isHighSurrogate (ahead2))
break;
}
return iter.getIndex();
}
}

View file

@ -0,0 +1,168 @@
// Default word BreakIterator.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.text;
import java.text.BreakIterator;
import java.text.CharacterIterator;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date March 22, 1999
* Written using The Unicode Standard, Version 2.0.
*/
public class LineBreakIterator extends BaseBreakIterator
{
public Object clone ()
{
return new LineBreakIterator (this);
}
public LineBreakIterator ()
{
iter = null;
}
private LineBreakIterator (LineBreakIterator other)
{
iter = (CharacterIterator) other.iter.clone();
}
// Some methods to tell us different properties of characters.
private final boolean isNb (char c)
{
return (c == 0x00a0 // NO-BREAK SPACE
|| c == 0x2011 // NON-BREAKING HYPHEN
|| c == 0xfeff); // ZERO WITH NO-BREAK SPACE
}
private final boolean isClose (int type)
{
return (type == Character.END_PUNCTUATION
// Unicode book says "comma, period, ...", which I take to
// mean "Po" class.
|| type == Character.OTHER_PUNCTUATION);
}
private final boolean isIdeo (char c)
{
return (c >= 0x3040 && c <= 0x309f // Hiragana
|| c >= 0x30a0 && c <= 0x30ff // Katakana
|| c >= 0x4e00 && c <= 0x9fff // Han
|| c >= 0x3100 && c <= 0x312f); // Bopomofo
}
public int next ()
{
int end = iter.getEndIndex();
if (iter.getIndex() == end)
return DONE;
while (iter.getIndex() < end)
{
char c = iter.current();
int type = Character.getType(c);
char n = iter.next();
if (n == CharacterIterator.DONE
|| type == Character.PARAGRAPH_SEPARATOR
|| type == Character.LINE_SEPARATOR)
break;
// Handle two cases where we must scan for non-spacing marks.
int start = iter.getIndex();
if (type == Character.SPACE_SEPARATOR
|| type == Character.START_PUNCTUATION
|| isIdeo (c))
{
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.NON_SPACING_MARK)
n = iter.next();
if (n == CharacterIterator.DONE)
break;
if (type == Character.SPACE_SEPARATOR)
{
int nt = Character.getType(n);
if (nt != Character.NON_SPACING_MARK
&& nt != Character.SPACE_SEPARATOR
&& ! isNb (n))
break;
}
else if (type == Character.START_PUNCTUATION)
{
if (isIdeo (n))
{
// Open punctuation followed by non spacing marks
// and then ideograph does not have a break in
// it. So skip all this.
start = iter.getIndex();
}
}
else
{
// Ideograph preceded this character.
if (isClose (Character.getType(n)))
break;
}
}
iter.setIndex(start);
}
return iter.getIndex();
}
public int previous ()
{
int start = iter.getBeginIndex();
if (iter.getIndex() == start)
return DONE;
while (iter.getIndex() >= start)
{
char c = iter.previous();
if (c == CharacterIterator.DONE)
break;
int type = Character.getType(c);
char n = iter.previous();
if (n == CharacterIterator.DONE)
break;
iter.next();
int nt = Character.getType(n);
// Break after paragraph separators.
if (nt == Character.PARAGRAPH_SEPARATOR
|| nt == Character.LINE_SEPARATOR)
break;
// Skip non-spacing marks.
int init = iter.getIndex();
while (n != CharacterIterator.DONE && nt == Character.NON_SPACING_MARK)
{
n = iter.previous();
nt = Character.getType(n);
}
if (nt == Character.SPACE_SEPARATOR
&& type != Character.SPACE_SEPARATOR
&& type != Character.NON_SPACING_MARK
&& ! isNb (c))
break;
if (! isClose (type) && isIdeo (n))
break;
if (isIdeo (c) && nt != Character.START_PUNCTUATION)
break;
iter.setIndex(init);
}
return iter.getIndex();
}
}

View file

@ -0,0 +1,75 @@
// Generic English locale data for java.text.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.text;
import java.util.ListResourceBundle;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date March 4, 1999
*/
public final class LocaleData_en extends ListResourceBundle
{
// These are for DateFormatSymbols.
static final String[] ampmsDefault = {"AM", "PM" };
static final String[] erasDefault = {"BC", "AD" };
static final String localPatternCharsDefault = "GyMdkHmsSEDFwWahKz";
static final String[] monthsDefault = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December", ""
};
static final String[] shortMonthsDefault = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""
};
static final String[] shortWeekdaysDefault = {
"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static final String[] weekdaysDefault = {
"", "Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday", "Saturday"
};
private static final Object[][] contents =
{
// These are for DecimalFormatSymbols.
{ "decimalSeparator", "." },
{ "digit", "#" },
{ "exponential", "E" },
{ "groupingSeparator", "," },
{ "infinity", "\u221e" },
{ "minusSign", "-" },
{ "NaN", "\ufffd" },
{ "patternSeparator", ";" },
{ "percent", "%" },
{ "perMill", "\u2030" },
{ "zeroDigit", "0" },
// These are for NumberFormat.
{ "numberFormat", "#,##0.###" },
{ "percentFormat", "#,##0%" },
// These are for DateFormatSymbols.
{ "ampm", ampmsDefault },
{ "eras", erasDefault },
{ "datePatternChars", localPatternCharsDefault },
{ "months", monthsDefault },
{ "shortMonths", shortMonthsDefault },
{ "shortWeekdays", shortWeekdaysDefault },
{ "weekdays", weekdaysDefault }
};
protected Object[][] getContents ()
{
return contents;
}
}

View file

@ -0,0 +1,71 @@
// US English locale data for java.text.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.text;
import java.util.ListResourceBundle;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date March 4, 1999
*/
public final class LocaleData_en_US extends ListResourceBundle
{
// These are for DateFormatSymbols.
static String[][] zoneStringsDefault = {
{ "PST", "Pacific Standard Time", "PST",
/**/ "Pacific Daylight Time", "PDT", "San Francisco" },
{ "MST", "Mountain Standard Time", "MST",
/**/ "Mountain Daylight Time", "MDT", "Denver" },
{ "PNT", "Mountain Standard Time", "MST",
/**/ "Mountain Standard Time", "MST", "Phoenix" },
{ "CST", "Central Standard Time", "CST",
/**/ "Central Daylight Time", "CDT", "Chicago" },
{ "EST", "Eastern Standard Time", "EST",
/**/ "Eastern Daylight Time", "EDT", "Boston" },
{ "IET", "Eastern Standard Time", "EST",
/**/ "Eastern Standard Time", "EST", "Indianapolis" },
{ "PRT", "Atlantic Standard Time", "AST",
/**/ "Atlantic Daylight Time", "ADT", "Halifax" },
{ "HST", "Hawaii Standard Time", "HST",
/**/ "Hawaii Daylight Time", "HDT", "Honolulu" },
{ "AST", "Alaska Standard Time", "AST",
/**/ "Alaska Daylight Time", "ADT", "Anchorage" }
};
private static final Object[][] contents =
{
// These are for DecimalFormatSymbols.
{ "currency", "$" },
{ "intlCurrencySymbol", "$" }, // FIXME?
// These are for NumberFormat.
{ "currencyFormat", "$#,##0.00;($#,##0.00)" },
// These are for DateFormatSymbols.
{ "zoneStrings", zoneStringsDefault },
// These are for DateFormat.
{ "shortDateFormat", "M/d/yy" }, // Java's Y2K bug.
{ "mediumDateFormat", "d-MMM-yy" },
{ "longDateFormat", "MMMM d, yyyy" },
{ "fullDateFormat", "EEEE MMMM d, yyyy G" },
{ "shortTimeFormat", "h:mm a" },
{ "mediumTimeFormat", "h:mm:ss a" },
{ "longTimeFormat", "h:mm:ss a z" },
{ "fullTimeFormat", "h:mm:ss;S 'o''clock' a z" }
};
protected Object[][] getContents ()
{
return contents;
}
}

View file

@ -0,0 +1,226 @@
// Default sentence BreakIterator.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.text;
import java.text.BreakIterator;
import java.text.CharacterIterator;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date March 23, 1999
* Written using The Unicode Standard, Version 2.0.
*/
public class SentenceBreakIterator extends BaseBreakIterator
{
public Object clone ()
{
return new SentenceBreakIterator (this);
}
public SentenceBreakIterator ()
{
iter = null;
}
private SentenceBreakIterator (SentenceBreakIterator other)
{
iter = (CharacterIterator) other.iter.clone();
}
public int next ()
{
int end = iter.getEndIndex();
if (iter.getIndex() == end)
return DONE;
while (iter.getIndex() < end)
{
char c = iter.current();
if (c == CharacterIterator.DONE)
break;
int type = Character.getType(c);
char n = iter.next();
if (n == CharacterIterator.DONE)
break;
// Always break after paragraph separator.
if (type == Character.PARAGRAPH_SEPARATOR)
break;
if (c == '!' || c == '?')
{
// Skip close punctuation.
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.END_PUNCTUATION)
n = iter.next();
// Skip spaces.
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.SPACE_SEPARATOR)
n = iter.next();
// Skip optional paragraph separator.
if (n != CharacterIterator.DONE
&& Character.getType(n) == Character.PARAGRAPH_SEPARATOR)
n = iter.next();
// There's always a break somewhere after `!' or `?'.
break;
}
if (c == '.')
{
int save = iter.getIndex();
// Skip close punctuation.
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.END_PUNCTUATION)
n = iter.next();
// Skip spaces. We keep count because we need at least
// one for this period to represent a terminator.
int spcount = 0;
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.SPACE_SEPARATOR)
{
n = iter.next();
++spcount;
}
if (spcount > 0)
{
int save2 = iter.getIndex();
// Skip over open puncutation.
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.START_PUNCTUATION)
n = iter.next();
// Next character must not be lower case.
if (n == CharacterIterator.DONE
|| ! Character.isLowerCase(n))
{
iter.setIndex(save2);
break;
}
}
iter.setIndex(save);
}
}
return iter.getIndex();
}
private final int previous_internal ()
{
int start = iter.getBeginIndex();
if (iter.getIndex() == start)
return DONE;
while (iter.getIndex() >= start)
{
char c = iter.previous();
if (c == CharacterIterator.DONE)
break;
char n = iter.previous();
if (n == CharacterIterator.DONE)
break;
iter.next();
int nt = Character.getType(n);
if (! Character.isLowerCase(c)
&& (nt == Character.START_PUNCTUATION
|| nt == Character.SPACE_SEPARATOR))
{
int save = iter.getIndex();
int save_nt = nt;
char save_n = n;
// Skip open punctuation.
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.START_PUNCTUATION)
n = iter.previous();
if (n == CharacterIterator.DONE)
break;
if (Character.getType(n) == Character.SPACE_SEPARATOR)
{
// Must have at least once space after the `.'.
int save2 = iter.getIndex();
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.SPACE_SEPARATOR)
n = iter.previous();
// Skip close punctuation.
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.END_PUNCTUATION)
n = iter.previous();
if (n == CharacterIterator.DONE || n == '.')
{
// Communicate location of actual end.
period = iter.getIndex();
iter.setIndex(save2);
break;
}
}
iter.setIndex(save);
nt = save_nt;
n = save_n;
}
if (nt == Character.PARAGRAPH_SEPARATOR)
{
// Communicate location of actual end.
period = iter.getIndex();
break;
}
else if (nt == Character.SPACE_SEPARATOR
|| nt == Character.END_PUNCTUATION)
{
int save = iter.getIndex();
// Skip spaces.
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.SPACE_SEPARATOR)
n = iter.previous();
// Skip close punctuation.
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.END_PUNCTUATION)
n = iter.previous();
int here = iter.getIndex();
iter.setIndex(save);
if (n == CharacterIterator.DONE || n == '!' || n == '?')
{
// Communicate location of actual end.
period = here;
break;
}
}
else if (n == '!' || n == '?')
{
// Communicate location of actual end.
period = iter.getIndex();
break;
}
}
return iter.getIndex();
}
public int previous ()
{
// We want to skip over the first sentence end to the second one.
// However, at the end of the string we want the first end.
int here = iter.getIndex();
period = here;
int first = previous_internal ();
if (here == iter.getEndIndex() || first == DONE)
return first;
iter.setIndex(period);
return previous_internal ();
}
// This is used for communication between previous and
// previous_internal.
private int period;
}

View file

@ -0,0 +1,224 @@
// Default word BreakIterator.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.text;
import java.text.BreakIterator;
import java.text.CharacterIterator;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date March 22, 1999
* Written using The Unicode Standard, Version 2.0.
*/
public class WordBreakIterator extends BaseBreakIterator
{
public Object clone ()
{
return new WordBreakIterator (this);
}
public WordBreakIterator ()
{
iter = null;
}
private WordBreakIterator (WordBreakIterator other)
{
iter = (CharacterIterator) other.iter.clone();
}
// Some methods to tell us different properties of characters.
private final boolean isHira (char c)
{
return c >= 0x3040 && c <= 0x309f;
}
private final boolean isKata (char c)
{
return c >= 0x30a0 && c <= 0x30ff;
}
private final boolean isHan (char c)
{
return c >= 0x4e00 && c <= 0x9fff;
}
public int next ()
{
int end = iter.getEndIndex();
if (iter.getIndex() == end)
return DONE;
while (iter.getIndex() < end)
{
char c = iter.current();
if (c == CharacterIterator.DONE)
break;
int type = Character.getType(c);
char n = iter.next();
if (n == CharacterIterator.DONE)
break;
// Break after paragraph separators.
if (type == Character.PARAGRAPH_SEPARATOR
|| type == Character.LINE_SEPARATOR)
break;
// Break between letters and non-letters.
// FIXME: we treat apostrophe as part of a word. This
// is an English-ism.
boolean is_letter = Character.isLetter(c);
if (c != '\'' && ! is_letter && type != Character.NON_SPACING_MARK
&& Character.isLetter(n))
break;
// Always break after certain symbols, such as punctuation.
// This heuristic is derived from hints in the JCL book and is
// not part of Unicode. It seems to be right, however.
// FIXME: we treat apostrophe as part of a word. This
// is an English-ism.
if (c != '\''
&& (type == Character.DASH_PUNCTUATION
|| type == Character.START_PUNCTUATION
|| type == Character.END_PUNCTUATION
|| type == Character.CONNECTOR_PUNCTUATION
|| type == Character.OTHER_PUNCTUATION
|| type == Character.MATH_SYMBOL
|| type == Character.CURRENCY_SYMBOL
|| type == Character.MODIFIER_SYMBOL
|| type == Character.OTHER_SYMBOL
|| type == Character.FORMAT
|| type == Character.CONTROL))
break;
boolean is_hira = isHira (c);
boolean is_kata = isKata (c);
boolean is_han = isHan (c);
// Special case Japanese.
if (! is_hira && ! is_kata && ! is_han
&& type != Character.NON_SPACING_MARK
&& (isHira (n) || isKata (n) || isHan (n)))
break;
if (is_hira || is_kata || is_han || is_letter)
{
// Now we need to do some lookahead. We might need to do
// quite a bit of lookahead, so we save our position and
// restore it later.
int save = iter.getIndex();
// Skip string of non spacing marks.
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.NON_SPACING_MARK)
n = iter.next();
if (n == CharacterIterator.DONE)
break;
if ((is_hira && ! isHira (n))
|| (is_kata && ! isHira (n) && ! isKata (n))
|| (is_han && ! isHira (n) && ! isHan (n))
// FIXME: we treat apostrophe as part of a word. This
// is an English-ism.
|| (is_letter && ! Character.isLetter(n) && n != '\''))
break;
iter.setIndex(save);
}
}
return iter.getIndex();
}
public int previous ()
{
int start = iter.getBeginIndex();
if (iter.getIndex() == start)
return DONE;
while (iter.getIndex() >= start)
{
char c = iter.previous();
if (c == CharacterIterator.DONE)
break;
boolean is_hira = isHira (c);
boolean is_kata = isKata (c);
boolean is_han = isHan (c);
boolean is_letter = Character.isLetter(c);
char n = iter.previous();
if (n == CharacterIterator.DONE)
break;
iter.next();
int type = Character.getType(n);
// Break after paragraph separators.
if (type == Character.PARAGRAPH_SEPARATOR
|| type == Character.LINE_SEPARATOR)
break;
// Break between letters and non-letters.
// FIXME: we treat apostrophe as part of a word. This
// is an English-ism.
if (n != '\'' && ! Character.isLetter(n)
&& type != Character.NON_SPACING_MARK
&& is_letter)
break;
// Always break after certain symbols, such as punctuation.
// This heuristic is derived from hints in the JCL book and is
// not part of Unicode. It seems to be right, however.
// FIXME: we treat apostrophe as part of a word. This
// is an English-ism.
if (n != '\''
&& (type == Character.DASH_PUNCTUATION
|| type == Character.START_PUNCTUATION
|| type == Character.END_PUNCTUATION
|| type == Character.CONNECTOR_PUNCTUATION
|| type == Character.OTHER_PUNCTUATION
|| type == Character.MATH_SYMBOL
|| type == Character.CURRENCY_SYMBOL
|| type == Character.MODIFIER_SYMBOL
|| type == Character.OTHER_SYMBOL
|| type == Character.FORMAT
|| type == Character.CONTROL))
break;
// Special case Japanese.
if ((is_hira || is_kata || is_han)
&& ! isHira (n) && ! isKata (n) && ! isHan (n)
&& type != Character.NON_SPACING_MARK)
break;
// We might have to skip over non spacing marks to see what's
// on the other side.
if (! is_hira || (! is_letter && c != '\''))
{
int save = iter.getIndex();
while (n != CharacterIterator.DONE
&& Character.getType(n) == Character.NON_SPACING_MARK)
n = iter.previous();
iter.setIndex(save);
// This is a strange case: a bunch of non-spacing marks at
// the beginning. We treat the current location as a word
// break.
if (n == CharacterIterator.DONE)
break;
if ((isHira (n) && ! is_hira)
|| (isKata (n) && ! is_hira && ! is_kata)
|| (isHan (n) && ! is_hira && ! is_han)
// FIXME: we treat apostrophe as part of a word. This
// is an English-ism.
|| (! is_letter && c != '\'' && Character.isLetter(n)))
break;
}
}
return iter.getIndex();
}
}

View file

@ -0,0 +1,24 @@
// -*- c++ -*-
// boehm-gc.h - Defines for Boehm collector.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JV_BOEHM_GC__
#define __JV_BOEHM_GC__
#define JV_MARKOBJ_DECL void *_Jv_MarkObj (void *, void *, void *, void *)
#define JV_MARKARRAY_DECL void *_Jv_MarkArray (void *, void *, void *, void *)
extern "C"
{
JV_MARKOBJ_DECL;
JV_MARKARRAY_DECL;
};
#endif /* __JV_BOEHM_GC__ */

133
libjava/include/cni.h Normal file
View file

@ -0,0 +1,133 @@
// cni.h -*- c++ -*-
// This file describes the Cygnus Native Interface, CNI.
// It provides a nicer interface to many of the things in javaprims.h.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JAVA_CNI_H__
#define __JAVA_CNI_H__
#include <java/lang/Object.h>
#include <java/lang/Class.h>
#include <java-threads.h>
#include <java-array.h>
extern inline jobject
JvAllocObject (jclass cls)
{
return _Jv_AllocObject (cls, cls->size());
}
extern inline jobject
JvAllocObject (jclass cls, jsize sz)
{
return _Jv_AllocObject (cls, sz);
}
extern "C" jstring _Jv_NewStringUTF (const char *bytes);
extern "C" void _Jv_InitClass (jclass);
extern inline void
JvInitClass (jclass cls)
{
return _Jv_InitClass (cls);
}
extern inline jstring
JvAllocString (jsize sz)
{
return _Jv_AllocString (sz);
}
extern inline jstring
JvNewString (const jchar *chars, jsize len)
{
return _Jv_NewString (chars, len);
}
extern inline jstring
JvNewStringLatin1 (const char *bytes, jsize len)
{
return _Jv_NewStringLatin1 (bytes, len);
}
extern inline jstring
JvNewStringLatin1 (const char *bytes)
{
return _Jv_NewStringLatin1 (bytes, strlen (bytes));
}
extern inline jchar *
_Jv_GetStringChars (jstring str)
{
return (jchar*)((char*) str->data + str->boffset);
}
extern inline jchar*
JvGetStringChars (jstring str)
{
return _Jv_GetStringChars (str);
}
extern inline jsize
JvGetStringUTFLength (jstring string)
{
return _Jv_GetStringUTFLength (string);
}
extern inline jsize
JvGetStringUTFRegion (jstring str, jsize start, jsize len, char *buf)
{
return _Jv_GetStringUTFRegion (str, start, len, buf);
}
extern inline jstring
JvNewStringUTF (const char *bytes)
{
return _Jv_NewStringUTF (bytes);
}
extern class _Jv_PrimClass _Jv_byteClass, _Jv_shortClass, _Jv_intClass,
_Jv_longClass, _Jv_booleanClass, _Jv_charClass, _Jv_floatClass,
_Jv_doubleClass, _Jv_voidClass;
#define JvPrimClass(TYPE) ((jclass) & _Jv_##TYPE##Class)
class JvSynchronize
{
private:
jobject obj;
public:
JvSynchronize (const jobject &o) : obj (o)
{ _Jv_MonitorEnter (obj); }
~JvSynchronize ()
{ _Jv_MonitorExit (obj); }
};
// Throw some exception.
extern void JvThrow (jobject obj) __attribute__ ((__noreturn__));
extern inline void
JvThrow (jobject obj)
{
_Jv_Throw ((void *) obj);
}
/* Call malloc, but throw exception if insufficient memory. */
extern inline void *
JvMalloc (jsize size)
{
return _Jv_Malloc (size);
}
extern inline void
JvFree (void *ptr)
{
return _Jv_Free (ptr);
}
#endif /* __JAVA_CNI_H__ */

252
libjava/include/config.h.in Normal file
View file

@ -0,0 +1,252 @@
/* include/config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if using alloca.c. */
#undef C_ALLOCA
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
#undef CRAY_STACKSEG_END
/* Define if you have alloca, as a function or macro. */
#undef HAVE_ALLOCA
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#undef HAVE_ALLOCA_H
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#undef STACK_DIRECTION
/* Define this if you want runtime debugging enabled. */
#undef DEBUG
/* Define if using POSIX threads that have the mutexattr functions. */
#undef HAVE_PTHREAD_MUTEXATTR_INIT
/* Define this if you prefer size over speed for java.lang.Character. */
#undef COMPACT_CHARACTER
/* Define if you have memcpy. */
#undef HAVE_MEMCPY
/* Define if you have memmove. */
#undef HAVE_MEMMOVE
/* Define if you have strerror. */
#undef HAVE_STRERROR
/* Define if you have __int32_t and __uint32_t. */
#undef HAVE_INT32_DEFINED
/* Define if you're running eCos. */
#undef ECOS
/* */
#undef HAVE_LOCALTIME
/* */
#undef HAVE_MKTIME
/* Define if using POSIX threads on Linux. */
#undef LINUX_THREADS
/* Define if you have the `ctime_r' function. */
#undef HAVE_CTIME_R
/* Define if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R
/* Define if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R
/* Define if inet6 structures are defined in netinet/in.h. */
#undef HAVE_INET6
/* Define it socklen_t typedef is in sys/socket.h. */
#undef HAVE_SOCKLEN_T
/* Define if Boehm GC in use. */
#undef HAVE_BOEHM_GC
/* Define if gethostname is declared in <unistd.h>. */
#undef HAVE_GETHOSTNAME_DECL
/* Define if gethostbyname_r returns `int'. */
#undef GETHOSTBYNAME_R_RETURNS_INT
/* Define if gethostbyaddr_r returns `int'. */
#undef GETHOSTBYADDR_R_RETURNS_INT
/* Define if struct tm has tm_gmtoff field. */
#undef STRUCT_TM_HAS_GMTOFF
/* Define if global `timezone' exists. */
#undef HAVE_TIMEZONE
/* Define if you have the appropriate function. */
#undef HAVE_ACCESS
#undef HAVE_STAT
#undef HAVE_MKDIR
#undef HAVE_RENAME
#undef HAVE_RMDIR
#undef HAVE_UNLINK
#undef HAVE_REALPATH
#undef HAVE_READDIR_R
#undef HAVE_GETHOSTBYNAME_R
#undef HAVE_GETHOSTBYADDR_R
/* Define if you have the access function. */
#undef HAVE_ACCESS
/* Define if you have the ctime function. */
#undef HAVE_CTIME
/* Define if you have the ctime_r function. */
#undef HAVE_CTIME_R
/* Define if you have the fsync function. */
#undef HAVE_FSYNC
/* Define if you have the ftime function. */
#undef HAVE_FTIME
/* Define if you have the gethostbyaddr_r function. */
#undef HAVE_GETHOSTBYADDR_R
/* Define if you have the gethostbyname_r function. */
#undef HAVE_GETHOSTBYNAME_R
/* Define if you have the gethostname function. */
#undef HAVE_GETHOSTNAME
/* Define if you have the getpwuid_r function. */
#undef HAVE_GETPWUID_R
/* Define if you have the gettimeofday function. */
#undef HAVE_GETTIMEOFDAY
/* Define if you have the gmtime_r function. */
#undef HAVE_GMTIME_R
/* Define if you have the inet_addr function. */
#undef HAVE_INET_ADDR
/* Define if you have the inet_aton function. */
#undef HAVE_INET_ATON
/* Define if you have the inet_pton function. */
#undef HAVE_INET_PTON
/* Define if you have the ioctl function. */
#undef HAVE_IOCTL
/* Define if you have the localtime_r function. */
#undef HAVE_LOCALTIME_R
/* Define if you have the memcpy function. */
#undef HAVE_MEMCPY
/* Define if you have the memmove function. */
#undef HAVE_MEMMOVE
/* Define if you have the mkdir function. */
#undef HAVE_MKDIR
/* Define if you have the open function. */
#undef HAVE_OPEN
/* Define if you have the pthread_mutexattr_setkind_np function. */
#undef HAVE_PTHREAD_MUTEXATTR_SETKIND_NP
/* Define if you have the pthread_mutexattr_settype function. */
#undef HAVE_PTHREAD_MUTEXATTR_SETTYPE
/* Define if you have the readdir_r function. */
#undef HAVE_READDIR_R
/* Define if you have the realpath function. */
#undef HAVE_REALPATH
/* Define if you have the rename function. */
#undef HAVE_RENAME
/* Define if you have the rmdir function. */
#undef HAVE_RMDIR
/* Define if you have the sched_yield function. */
#undef HAVE_SCHED_YIELD
/* Define if you have the select function. */
#undef HAVE_SELECT
/* Define if you have the sleep function. */
#undef HAVE_SLEEP
/* Define if you have the stat function. */
#undef HAVE_STAT
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define if you have the time function. */
#undef HAVE_TIME
/* Define if you have the uname function. */
#undef HAVE_UNAME
/* Define if you have the unlink function. */
#undef HAVE_UNLINK
/* Define if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define if you have the <sys/filio.h> header file. */
#undef HAVE_SYS_FILIO_H
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Name of package */
#undef PACKAGE
/* Version number of package */
#undef VERSION

View file

@ -0,0 +1,78 @@
// java-array.h - Header file for CNI arrays. -*- c++ -*-
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JAVA_ARRAY_H__
#define __JAVA_ARRAY_H__
#pragma interface
#include <java/lang/Object.h>
extern "Java" {
class __JArray : public java::lang::Object
{
public:
int length;
friend jsize JvGetArrayLength (__JArray*);
};
template<class T>
class JArray : public __JArray
{
T data[0];
public:
friend T* elements<>(JArray<T>& x);
friend T* elements<>(JArray<T>* x);
// T* getData() { return data; }
// T& operator[](jint i) { return data[i]; }
};
template<class T>
T* elements(JArray<T>& x) { return x.data; }
template<class T>
T* elements(JArray<T>* x) { return x->data; }
}; // end extern "Java"
/* These typesdefs match those in JNI. */
typedef __JArray *jarray;
typedef JArray<jobject> *jobjectArray;
typedef JArray<jboolean> *jbooleanArray;
typedef JArray<jbyte> *jbyteArray;
typedef JArray<jchar> *jcharArray;
typedef JArray<jshort> *jshortArray;
typedef JArray<jint> *jintArray;
typedef JArray<jlong> *jlongArray;
typedef JArray<jfloat> *jfloatArray;
typedef JArray<jdouble> *jdoubleArray;
typedef JArray<jstring> *jstringArray;
// Temporary work-around for gcjh bug. FIXME
typedef JArray<jcharArray> *jobjectArrayjchar;
extern "C" jbooleanArray JvNewBooleanArray (jint length);
extern "C" jbyteArray JvNewByteArray (jint length);
extern "C" jcharArray JvNewCharArray (jint length);
extern "C" jshortArray JvNewShortArray (jint length);
extern "C" jintArray JvNewIntArray (jint length);
extern "C" jlongArray JvNewLongArray (jint length);
extern "C" jfloatArray JvNewFloatArray (jint length);
extern "C" jdoubleArray JvNewDoubleArray (jint length);
extern "C" jobjectArray _Jv_NewObjectArray(jsize length, jclass, jobject init);
inline jobjectArray JvNewObjectArray (jsize length, jclass cls, jobject init)
{ return _Jv_NewObjectArray (length, cls, init); }
extern "C" jstringArray JvConvertArgv(int argc, const char **argv);
extern "C" void JvRunMain (jclass klass, int argc, const char **argv);
inline jsize JvGetArrayLength (jarray array) { return array->length; }
#endif /* __JAVA_ARRAY_H__ */

View file

@ -0,0 +1,38 @@
// java-assert.h - Header file holding assertion definitions. -*- c++ -*-
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JAVA_ASSERT_H__
#define __JAVA_ASSERT_H__
// This is a libgcj implementation header.
void _Jv_Abort (const char *, const char *, int, const char *)
__attribute__ ((__noreturn__));
#ifdef DEBUG
#define _Jv_AssertDoCall(Message) _Jv_Abort (__FUNCTION__, __FILE__, __LINE__, Message)
#define JvAssertMessage(Expr, Message) \
do { if (! (Expr)) _Jv_AssertDoCall (Message); } while (0)
#define JvAssert(Expr) \
do { if (! (Expr)) _Jv_AssertDoCall (# Expr); } while (0)
#define JvFail(Message) _Jv_AssertDoCall (Message)
#else /* DEBUG */
#define _Jv_AssertDoCall(Message)
#define JvAssertMessage(Expr, Message)
#define JvAssert(Expr)
#define JvFail(Message) _Jv_Abort (0, 0, 0, Message)
#endif /* not DEBUG */
#endif /* __JAVA_ASSERT_H__ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,158 @@
// java-field.h - Header file for fieldID instances. -*- c++ -*-
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JAVA_FIELD_H__
#define __JAVA_FIELD_H__
#include <java/lang/Class.h>
#include <java/lang/reflect/Field.h>
#define _Jv_FIELD_UNRESOLVED_FLAG 0x8000
#define _Jv_FIELD_CONSTANT_VALUE 0x4000
struct _Jv_Field
{
#ifndef COMPACT_FIELDS
struct _Jv_Utf8Const* name;
#endif
/* The type of the field, if isResolved().
If !isResolved(): The fields's signature as a (Utf8Const*). */
jclass type;
_Jv_ushort flags;
#ifdef COMPACT_FIELDS
short nameIndex; /* ofsfet in class's name table */
#else
_Jv_ushort bsize; /* not really needed ... */
#endif
union {
int boffset; /* offset in bytes for instance field */
void* addr; /* address of static field */
} u;
#ifdef __cplusplus
jboolean isResolved ()
{ return ! (flags & _Jv_FIELD_UNRESOLVED_FLAG); }
public:
int getOffset () { return u.boffset; }
jobject getObjectField (jobject obj)
{ return *(jobject *)((char *)obj + getOffset ()); }
jfieldID getNextInstanceField () { return this + 1; }
jboolean isRef () { return ! isResolved () || ! type->isPrimitive (); }
// FIXME - may need to mask off internal flags.
int getModifiers() { return flags; }
#ifdef COMPACT_FIELDS
_Jv_Utf8Const * getNameUtf8Const (jclass cls)
{ return clas->fieldNames + nameIndex; }
#else
_Jv_Utf8Const * getNameUtf8Const (jclass) { return name; }
#endif
#endif
};
#ifdef __cplusplus
inline jbyte
_Jv_GetStaticByteField (jclass, _Jv_Field* field)
{
return * (jbyte *) field->u.addr;
}
inline jshort
_Jv_GetStaticShortField (jclass, _Jv_Field* field)
{
return * (jshort *) field->u.addr;
}
inline jint
_Jv_GetStaticIntField (jclass, _Jv_Field* field)
{
return * (jint *) field->u.addr;
}
inline jlong
_Jv_GetStaticLongField (jclass, _Jv_Field* field)
{
return * (jlong *) field->u.addr;
}
inline jobject
_Jv_GetObjectField (jobject obj, _Jv_Field* field)
{
return field->getObjectField (obj);
}
inline jbyte
_Jv_GetByteField (jobject obj, _Jv_Field* field)
{
return * (jbyte *) ((char*) obj + field->getOffset ());
}
inline jshort
_Jv_GetShortField (jobject obj, _Jv_Field* field)
{
return * (jshort *) ((char*) obj + field->getOffset ());
}
inline jint
_Jv_GetIntField (jobject obj, _Jv_Field* field)
{
return * (jint *) ((char*) obj + field->getOffset ());
}
inline jlong
_Jv_GetLongField (jobject obj, _Jv_Field* field)
{
return * (jlong *) ((char*) obj + field->getOffset ());
}
extern inline jfieldID
_Jv_FromReflectedField (java::lang::reflect::Field *field)
{
return (jfieldID) ((char *) field->declaringClass->fields + field->offset);
}
#ifdef __JAVA_CNI_H__
extern inline jfieldID
JvGetFirstInstanceField (jclass klass)
{
return &(klass->fields[klass->static_field_count]);
}
extern inline jint
JvNumInstanceFields (jclass klass)
{
return klass->field_count - klass->static_field_count;
}
extern inline jboolean
JvFieldIsRef (jfieldID field)
{
return field->isRef ();
}
extern inline jobject
JvGetObjectField (jobject obj, _Jv_Field* field)
{
return _Jv_GetObjectField (obj, field);
}
#endif /* defined (__JAVA_CNI_H__) */
#endif
#endif /* __JAVA_FIELD_H */

View file

@ -0,0 +1,16 @@
// java-method.h - Header file for methodID instances. -*- c++ -*-
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
extern inline jmethodID
_Jv_FromReflectedMethod(java::lang::reflect::Method *method)
{
return (jmethodID)
((char *) method->declaringClass->methods + method->offset);
}

262
libjava/include/javaprims.h Normal file
View file

@ -0,0 +1,262 @@
// javaprims.h - Main external header file for libgcj. -*- c++ -*-
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JAVAPRIMS_H__
#define __JAVAPRIMS_H__
// To force selection of correct types that will mangle consistently
// across platforms.
extern "Java"
{
typedef __java_byte jbyte;
typedef __java_short jshort;
typedef __java_int jint;
typedef __java_long jlong;
typedef __java_float jfloat;
typedef __java_double jdouble;
typedef __java_char jchar;
typedef __java_boolean jboolean;
typedef jint jsize;
// The following class declarations are automatically generated by
// the `classes.pl' script.
namespace java
{
namespace io
{
class BufferedInputStream;
class BufferedOutputStream;
class BufferedReader;
class BufferedWriter;
class ByteArrayInputStream;
class ByteArrayOutputStream;
class CharArrayReader;
class CharArrayWriter;
class CharConversionException;
class DataInput;
class DataInputStream;
class DataOutput;
class DataOutputStream;
class EOFException;
class File;
class FileDescriptor;
class FileInputStream;
class FileNotFoundException;
class FileOutputStream;
class FileReader;
class FileWriter;
class FilenameFilter;
class FilterInputStream;
class FilterOutputStream;
class FilterReader;
class FilterWriter;
class IOException;
class InputStream;
class InputStreamReader;
class InterruptedIOException;
class LineNumberInputStream;
class LineNumberReader;
class OutputStream;
class OutputStreamWriter;
class PipedInputStream;
class PipedOutputStream;
class PipedReader;
class PipedWriter;
class PrintStream;
class PrintWriter;
class PushbackInputStream;
class PushbackReader;
class RandomAccessFile;
class Reader;
class SequenceInputStream;
class Serializable;
class StreamTokenizer;
class StringBufferInputStream;
class StringReader;
class StringWriter;
class SyncFailedException;
class UTFDataFormatException;
class UnsupportedEncodingException;
class Writer;
};
namespace lang
{
class AbstractMethodError;
class ArithmeticException;
class ArrayIndexOutOfBoundsException;
class ArrayStoreException;
class Boolean;
class Byte;
class Character;
class Class;
class ClassCastException;
class ClassCircularityError;
class ClassFormatError;
class ClassLoader;
class ClassNotFoundException;
class CloneNotSupportedException;
class Cloneable;
class Comparable;
class Compiler;
class Double;
class Error;
class Exception;
class ExceptionInInitializerError;
class FirstThread;
class Float;
class IllegalAccessError;
class IllegalAccessException;
class IllegalArgumentException;
class IllegalMonitorStateException;
class IllegalStateException;
class IllegalThreadStateException;
class IncompatibleClassChangeError;
class IndexOutOfBoundsException;
class InstantiationError;
class InstantiationException;
class Integer;
class InternalError;
class InterruptedException;
class LinkageError;
class Long;
class Math;
class NegativeArraySizeException;
class NoClassDefFoundError;
class NoSuchFieldError;
class NoSuchFieldException;
class NoSuchMethodError;
class NoSuchMethodException;
class NullPointerException;
class Number;
class NumberFormatException;
class Object;
class OutOfMemoryError;
class Process;
class Runnable;
class Runtime;
class RuntimeException;
class SecurityException;
class SecurityManager;
class Short;
class StackOverflowError;
class String;
class StringBuffer;
class StringIndexOutOfBoundsException;
class System;
class Thread;
class ThreadDeath;
class ThreadGroup;
class Throwable;
class UnknownError;
class UnsatisfiedLinkError;
class UnsupportedOperationException;
class VerifyError;
class VirtualMachineError;
class Void;
namespace reflect
{
class AccessibleObject;
class Array;
class Constructor;
class Field;
class InvocationTargetException;
class Member;
class Method;
class Modifier;
};
};
namespace util
{
class BitSet;
class Calendar;
class ConcurrentModificationException;
class Date;
class Dictionary;
class EmptyStackException;
class Enumeration;
class EventListener;
class EventObject;
class GregorianCalendar;
class Hashtable;
class HashtableEntry;
class HashtableEnumeration;
class ListResourceBundle;
class Locale;
class MissingResourceException;
class NoSuchElementException;
class Observable;
class Observer;
class Properties;
class Random;
class ResourceBundle;
class SimpleTimeZone;
class Stack;
class StringTokenizer;
class TimeZone;
class TooManyListenersException;
class Vector;
class VectorEnumeration;
namespace zip
{
class Adler32;
class CRC32;
class Checksum;
class Deflater;
class DeflaterOutputStream;
class ZipConstants;
class ZipEntry;
class ZipEnumeration;
class ZipException;
class ZipFile;
class ZipOutputStream;
};
};
};
};
typedef struct java::lang::Object* jobject;
typedef class java::lang::Class* jclass;
typedef class java::lang::Throwable* jthrowable;
typedef class java::lang::String* jstring;
struct _Jv_JNIEnv;
typedef struct _Jv_Field *jfieldID;
typedef struct _Jv_Method *jmethodID;
extern "C" jobject _Jv_AllocObject (jclass, jint);
extern "C" jboolean _Jv_IsInstanceOf(jobject, jclass);
extern "C" jstring _Jv_AllocString(jsize);
extern "C" jstring _Jv_NewString (const jchar*, jsize);
extern "C" jchar* _Jv_GetStringChars (jstring str);
extern "C" jint _Jv_MonitorEnter (jobject);
extern "C" jint _Jv_MonitorExit (jobject);
extern "C" jstring _Jv_NewStringLatin1(const char*, jsize);
extern "C" jsize _Jv_GetStringUTFLength (jstring);
extern "C" jsize _Jv_GetStringUTFRegion (jstring, jsize, jsize, char *);
extern "C" void _Jv_Throw (void *) __attribute__ ((__noreturn__));
extern "C" void* _Jv_Malloc (jsize);
extern "C" void _Jv_Free (void*);
typedef unsigned short _Jv_ushort __attribute__((__mode__(__HI__)));
typedef unsigned int _Jv_uint __attribute__((__mode__(__SI__)));
struct _Jv_Utf8Const
{
_Jv_ushort hash;
_Jv_ushort length; /* In bytes, of data portion, without final '\0'. */
char data[1]; /* In Utf8 format, with final '\0'. */
};
#endif /* __JAVAPRIMS_H__ */

302
libjava/include/jni.h Normal file
View file

@ -0,0 +1,302 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JAVA_JNI_H__
#define __JAVA_JNI_H__
#ifdef __GNUC__
# define __need___va_list
# include <stdarg.h>
# define _Jv_va_list __gnuc_va_list
#else
# include <stdarg.h>
# define _Jv_va_list va_list
#endif
#ifdef __cplusplus
// This is wrong, because it pollutes the name-space too much!
#include <javaprims.h>
typedef struct _Jv_JNIEnv JNIEnv;
#else
typedef int jbyte __attribute__((__mode__(__QI__)));
typedef int jshort __attribute__((__mode__(__HI__)));
typedef int jint __attribute__((__mode__(__SI__)));
typedef int jlong __attribute__((__mode__(__DI__)));
typedef bool jboolean __attribute__((__mode__(__QI__)));
typedef unsigned short jchar __attribute__((__mode__(__HI__)));
typedef float jfloat;
typedef double jdouble;
typedef jint jsize;
typedef const struct JNINativeInterface *JNIEnv;
#endif
typedef union jvalue
{
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;
typedef void * (*_Jv_func)(...);
struct JNINativeInterface
{
_Jv_func reserved0;
_Jv_func reserved1;
_Jv_func reserved2;
_Jv_func reserved3;
_Jv_func GetVersion;
_Jv_func DefineClass;
_Jv_func FindClass;
_Jv_func reserved4;
_Jv_func reserved5;
_Jv_func reserved6;
jclass (*GetSuperclass) (JNIEnv*, jclass);
jboolean (*IsAssignableFrom) (JNIEnv*, jclass, jclass);
_Jv_func reserved7;
jint (*Throw) (JNIEnv*, jthrowable);
_Jv_func ThrowNew;
_Jv_func ExceptionOccurred;
_Jv_func ExceptionDescribe;
_Jv_func ExceptionClear;
_Jv_func FatalError;
_Jv_func reserved8;
_Jv_func reserved9;
_Jv_func NewGlobalRef;
_Jv_func DeleteGlobalRef;
_Jv_func DeleteLocalRef;
_Jv_func IsSameObject;
_Jv_func reserved10;
_Jv_func reserved11;
_Jv_func AllocObject;
_Jv_func NewObject;
_Jv_func NewObjectV;
_Jv_func NewObjectA;
_Jv_func GetObjectClass;
_Jv_func IsInstanceOf;
_Jv_func GetMethodID;
_Jv_func CallObjectMethod;
_Jv_func CallObjectMethodV;
_Jv_func CallObjectMethodA;
_Jv_func CallBooleanMethod;
_Jv_func CallBooleanMethodV;
_Jv_func CallBooleanMethodA;
_Jv_func CallByteMethod;
_Jv_func CallByteMethodV;
_Jv_func CallByteMethodA;
_Jv_func CallCharMethod;
_Jv_func CallCharMethodV;
_Jv_func CallCharMethodA;
_Jv_func CallShortMethod;
_Jv_func CallShortMethodV;
_Jv_func CallShortMethodA;
_Jv_func CallIntMethod;
_Jv_func CallIntMethodV;
_Jv_func CallIntMethodA;
_Jv_func CallLongMethod;
_Jv_func CallLongMethodV;
_Jv_func CallLongMethodA;
_Jv_func CallFloatMethod;
_Jv_func CallFloatMethodV;
_Jv_func CallFloatMethodA;
_Jv_func CallDoubleMethod;
_Jv_func CallDoubleMethodV;
_Jv_func CallDoubleMethodA;
_Jv_func CallVoidMethod;
_Jv_func CallVoidMethodV;
_Jv_func CallVoidMethodA;
_Jv_func CallNonvirtualObjectMethod;
_Jv_func CallNonvirtualObjectMethodV;
_Jv_func CallNonvirtualObjectMethodA;
jboolean (*CallNonvirtualBooleanMethod) (JNIEnv*, jobject, jclass, jmethodID, ...);
jboolean (*CallNonvirtualBooleanMethodV) (JNIEnv*, jobject, jclass, jmethodID, _Jv_va_list);
jboolean (*CallNonvirtualBooleanMethodA) (JNIEnv*, jobject, jclass, jmethodID, jvalue*);
_Jv_func CallNonvirtualByteMethod;
_Jv_func CallNonvirtualByteMethodV;
_Jv_func CallNonvirtualByteMethodA;
_Jv_func CallNonvirtualCharMethod;
_Jv_func CallNonvirtualCharMethodV;
_Jv_func CallNonvirtualCharMethodA;
_Jv_func CallNonvirtualShortMethod;
_Jv_func CallNonvirtualShortMethodV;
_Jv_func CallNonvirtualShortMethodA;
_Jv_func CallNonvirtualIntMethod;
_Jv_func CallNonvirtualIntMethodV;
_Jv_func CallNonvirtualIntMethodA;
_Jv_func CallNonvirtualLongMethod;
_Jv_func CallNonvirtualLongMethodV;
_Jv_func CallNonvirtualLongMethodA;
_Jv_func CallNonvirtualFloatMethod;
_Jv_func CallNonvirtualFloatMethodV;
_Jv_func CallNonvirtualFloatMethodA;
_Jv_func CallNonvirtualDoubleMethod;
jdouble (*CallNonvirtualDoubleMethodV) (JNIEnv*, jobject, jclass, jmethodID, _Jv_va_list);
_Jv_func CallNonvirtualDoubleMethodA;
_Jv_func CallNonvirtualVoidMethod;
_Jv_func CallNonvirtualVoidMethodV;
_Jv_func CallNonvirtualVoidMethodA;
_Jv_func GetFieldID;
jobject (*GetObjectField) (JNIEnv*, jobject, jfieldID);
jboolean (*GetBooleanField) (JNIEnv*, jobject, jfieldID);
jbyte (*GetByteField) (JNIEnv*, jobject, jfieldID);
jchar (*GetCharField) (JNIEnv*, jobject, jfieldID);
jshort (*GetShortField) (JNIEnv*, jobject, jfieldID);
jint (*GetIntField) (JNIEnv*, jobject, jfieldID);
jlong (*GetLongField) (JNIEnv*, jobject, jfieldID);
jfloat (*GetFloatField) (JNIEnv*, jobject, jfieldID);
jdouble (*GetDoubleField) (JNIEnv*, jobject, jfieldID);
_Jv_func SetObjectField;
_Jv_func SetBooleanField;
_Jv_func SetByteField;
_Jv_func SetCharField;
_Jv_func SetShortField;
_Jv_func SetIntField;
_Jv_func SetLongField;
_Jv_func SetFloatField;
_Jv_func SetDoubleField;
_Jv_func GetStaticMethodID;
_Jv_func CallStaticObjectMethod;
_Jv_func CallStaticObjectMethodV;
_Jv_func CallStaticObjectMethodA;
_Jv_func CallStaticBooleanMethod;
_Jv_func CallStaticBooleanMethodV;
_Jv_func CallStaticBooleanMethodA;
_Jv_func CallStaticByteMethod;
_Jv_func CallStaticByteMethodV;
_Jv_func CallStaticByteMethodA;
_Jv_func CallStaticCharMethod;
_Jv_func CallStaticCharMethodV;
_Jv_func CallStaticCharMethodA;
_Jv_func CallStaticShortMethod;
_Jv_func CallStaticShortMethodV;
_Jv_func CallStaticShortMethodA;
_Jv_func CallStaticIntMethod;
_Jv_func CallStaticIntMethodV;
_Jv_func CallStaticIntMethodA;
_Jv_func CallStaticLongMethod;
_Jv_func CallStaticLongMethodV;
_Jv_func CallStaticLongMethodA;
_Jv_func CallStaticFloatMethod;
_Jv_func CallStaticFloatMethodV;
_Jv_func CallStaticFloatMethodA;
_Jv_func CallStaticDoubleMethod;
_Jv_func CallStaticDoubleMethodV;
_Jv_func CallStaticDoubleMethodA;
_Jv_func CallStaticVoidMethod;
_Jv_func CallStaticVoidMethodV;
_Jv_func CallStaticVoidMethodA;
_Jv_func GetStaticFieldID;
_Jv_func GetStaticObjectField;
_Jv_func GetStaticBooleanField;
_Jv_func GetStaticByteField;
_Jv_func GetStaticCharField;
_Jv_func GetStaticShortField;
_Jv_func GetStaticIntField;
_Jv_func GetStaticLongField;
_Jv_func GetStaticFloatField;
_Jv_func GetStaticDoubleField;
_Jv_func SetStaticObjectField;
_Jv_func SetStaticBooleanField;
_Jv_func SetStaticByteField;
_Jv_func SetStaticCharField;
_Jv_func SetStaticShortField;
_Jv_func SetStaticIntField;
_Jv_func SetStaticLongField;
_Jv_func SetStaticFloatField;
_Jv_func SetStaticDoubleField;
_Jv_func NewString;
jint (*GetStringLength) (JNIEnv*, jstring);
_Jv_func GetStringChars;
_Jv_func ReleaseStringChars;
_Jv_func NewStringUTF;
_Jv_func GetStringUTFLength;
_Jv_func GetStringUTFChars;
_Jv_func ReleaseStringUTFChars;
_Jv_func GetArrayLength;
_Jv_func NewObjectArray;
_Jv_func GetObjectArrayElement;
_Jv_func SetObjectArrayElement;
_Jv_func NewBooleanArray;
_Jv_func NewByteArray;
_Jv_func NewCharArray;
_Jv_func NewShortArray;
_Jv_func NewIntArray;
_Jv_func NewLongArray;
_Jv_func NewFloatArray;
_Jv_func NewDoubleArray;
_Jv_func GetBooleanArrayElements;
_Jv_func GetByteArrayElements;
_Jv_func GetCharArrayElements;
_Jv_func GetShortArrayElements;
_Jv_func GetIntArrayElements;
_Jv_func GetLongArrayElements;
_Jv_func GetFloatArrayElements;
_Jv_func GetDoubleArrayElements;
_Jv_func ReleaseBooleanArrayElements;
_Jv_func ReleaseByteArrayElements;
_Jv_func ReleaseCharArrayElements;
_Jv_func ReleaseShortArrayElements;
_Jv_func ReleaseIntArrayElements;
_Jv_func ReleaseLongArrayElements;
_Jv_func ReleaseFloatArrayElements;
_Jv_func ReleaseDoubleArrayElements;
_Jv_func GetBooleanArrayRegion;
_Jv_func GetByteArrayRegion;
_Jv_func GetCharArrayRegion;
_Jv_func GetShortArrayRegion;
_Jv_func GetIntArrayRegion;
_Jv_func GetLongArrayRegion;
_Jv_func GetFloatArrayRegion;
_Jv_func GetDoubleArrayRegion;
_Jv_func SetBooleanArrayRegion;
_Jv_func SetByteArrayRegion;
_Jv_func SetCharArrayRegion;
_Jv_func SetShortArrayRegion;
_Jv_func SetIntArrayRegion;
_Jv_func SetLongArrayRegion;
_Jv_func SetFloatArrayRegion;
_Jv_func SetDoubleArrayRegion;
_Jv_func RegisterNatives;
_Jv_func UnregisterNatives;
_Jv_func MonitorEnter;
_Jv_func MonitorExit;
_Jv_func GetJavaVM;
};
#ifdef __cplusplus
struct _Jv_JNIEnv
{
struct JNINativeInterface *p;
jclass GetSuperclass (jclass cl);
jsize GetStringLength (jstring str);
};
extern inline jclass
_Jv_JNIEnv::GetSuperclass (jclass cl)
{ return p->GetSuperclass (this, cl); }
extern inline jsize
_Jv_JNIEnv::GetStringLength (jstring str)
{ return p->GetStringLength (this, str); }
#endif
#endif /* __JAVA_JNI_H__ */

101
libjava/include/jvm.h Normal file
View file

@ -0,0 +1,101 @@
// jvm.h - Header file for private implementation information. -*- c++ -*-
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JAVA_JVM_H__
#define __JAVA_JVM_H__
#include <java-assert.h>
#include <java-field.h>
/* Structure of the virtual table. */
struct _Jv_VTable
{
jclass clas;
void *method[1];
};
/* Extract a character from a Java-style Utf8 string.
* PTR points to the current character.
* LIMIT points to the end of the Utf8 string.
* PTR is incremented to point after the character thta gets returns.
* On an error, -1 is returned. */
#define UTF8_GET(PTR, LIMIT) \
((PTR) >= (LIMIT) ? -1 \
: *(PTR) < 128 ? *(PTR)++ \
: (*(PTR)&0xE0) == 0xC0 && ((PTR)+=2)<=(LIMIT) && ((PTR)[-1]&0xC0) == 0x80 \
? (((PTR)[-2] & 0x1F) << 6) + ((PTR)[-1] & 0x3F) \
: (*(PTR) & 0xF0) == 0xE0 && ((PTR) += 3) <= (LIMIT) \
&& ((PTR)[-2] & 0xC0) == 0x80 && ((PTR)[-1] & 0xC0) == 0x80 \
? (((PTR)[-3]&0x0F) << 12) + (((PTR)[-2]&0x3F) << 6) + ((PTR)[-1]&0x3F) \
: ((PTR)++, -1))
extern int _Jv_strLengthUtf8(char* str, int len);
typedef struct _Jv_Utf8Const Utf8Const;
_Jv_Utf8Const *_Jv_makeUtf8Const (char *s, int len);
extern jboolean _Jv_equalUtf8Consts (_Jv_Utf8Const *, _Jv_Utf8Const *);
extern jboolean _Jv_equal (_Jv_Utf8Const *, jstring, jint);
#define StringClass _CL_Q34java4lang6String
extern java::lang::Class StringClass;
/* Type of pointer used as finalizer. */
typedef void _Jv_FinalizerFunc (jobject);
/* Allocate space for a new Java object. */
void *_Jv_AllocObj (jsize size);
/* Allocate space for an array of Java objects. */
void *_Jv_AllocArray (jsize size);
/* Allocate space that is known to be pointer-free. */
void *_Jv_AllocBytes (jsize size);
/* Initialize the GC. */
void _Jv_InitGC (void);
/* Register a finalizer. */
void _Jv_RegisterFinalizer (void *object, _Jv_FinalizerFunc *method);
/* Run finalizers for objects ready to be finalized.. */
void _Jv_RunFinalizers (void);
/* Run all finalizers. Should be called only before exit. */
void _Jv_RunAllFinalizers (void);
/* Perform a GC. */
void _Jv_RunGC (void);
/* Return approximation of total size of heap. */
long _Jv_GCTotalMemory (void);
/* Return approximation of total free memory. */
long _Jv_GCFreeMemory (void);
/* Allocate some unscanned bytes. Throw exception if out of memory. */
void *_Jv_AllocBytesChecked (jsize size);
// This function is used to determine the hash code of an object.
inline jint
_Jv_HashCode (jobject obj)
{
return (jint) obj;
}
extern "C" void _Jv_ThrowBadArrayIndex (jint bad_index);
extern "C" jobject _Jv_NewArray (jint type, jint size);
extern "C" jobject _Jv_NewMultiArray (jclass klass, jint dims, ...);
extern "C" void *_Jv_CheckCast (jclass klass, jobject obj);
extern "C" void *_Jv_LookupInterfaceMethod (jclass klass, Utf8Const *name,
Utf8Const *signature);
extern "C" void _Jv_CheckArrayStore (jobject array, jobject obj);
extern "C" void _Jv_RegisterClass (jclass klass);
extern "C" void _Jv_RegisterClasses (jclass *classes);
extern jclass _Jv_FindClass (_Jv_Utf8Const *name,
java::lang::ClassLoader *loader);
extern jclass _Jv_FindClassFromSignature (char *,
java::lang::ClassLoader *loader);
extern jobject _Jv_NewMultiArray (jclass, jint ndims, jint* dims);
#endif /* __JAVA_JVM_H__ */

17
libjava/include/no-gc.h Normal file
View file

@ -0,0 +1,17 @@
// -*- c++ -*-
// no-gc.h - Defines for no garbage collector.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JV_NO_GC__
#define __JV_NO_GC__
// Nothing.
#endif /* __JV_NO_GC__ */

View file

@ -0,0 +1,154 @@
// -*- c++ -*-
// no-threads.h - Defines for using no threads.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JV_NO_THREADS__
#define __JV_NO_THREADS__
#include "config.h"
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
//
// Typedefs.
//
typedef int _Jv_ConditionVariable_t;
typedef int _Jv_Mutex_t;
typedef int _Jv_Thread_t;
typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
//
// Condition variables.
//
inline void
_Jv_CondInit (_Jv_ConditionVariable_t *)
{
}
// Waiting is ok provided there is a timeout. Otherwise we will just
// wait forever.
inline int
_Jv_CondWait (_Jv_ConditionVariable_t *, _Jv_Mutex_t *,
jlong millis, jint nanos)
{
if (millis == 0 && nanos == 0)
JvFail ("_Jv_CondWait without timeout");
#ifdef HAVE_SLEEP
int seconds = millis / 1000;
if (seconds > 0)
sleep (seconds);
#endif
return 0;
}
inline int
_Jv_CondNotify (_Jv_ConditionVariable_t *, _Jv_Mutex_t *)
{
// It is ok to notify -- it just has no effect.
return 0;
}
inline int
_Jv_CondNotifyAll (_Jv_ConditionVariable_t *, _Jv_Mutex_t *)
{
// It is ok to notify -- it just has no effect.
return 0;
}
//
// Mutexes.
//
inline void
_Jv_MutexInit (_Jv_Mutex_t *)
{
}
inline int
_Jv_MutexLock (_Jv_Mutex_t *)
{
return 0;
}
inline int
_Jv_MutexUnlock (_Jv_Mutex_t *)
{
return 0;
}
//
// Thread creation and manipulation.
//
inline void
_Jv_InitThreads (void)
{
}
inline void
_Jv_ThreadInitData (_Jv_Thread_t **data, java::lang::Thread *)
{
*data = NULL;
}
inline java::lang::Thread *
_Jv_ThreadCurrent (void)
{
extern java::lang::Thread *_Jv_OnlyThread;
return _Jv_OnlyThread;
}
inline void
_Jv_ThreadYield (void)
{
}
inline void
_Jv_ThreadSetPriority (_Jv_Thread_t *, jint)
{
}
inline void
_Jv_ThreadCancel (_Jv_Thread_t *, void *)
{
JvFail ("_Jv_ThreadCancel");
}
// Like Cancel, but doesn't run cleanups.
inline void
_Jv_ThreadDestroy (_Jv_Thread_t *)
{
JvFail ("_Jv_ThreadDestroy");
}
void _Jv_ThreadStart (java::lang::Thread *, _Jv_Thread_t *,
_Jv_ThreadStartFunc *meth);
inline void
_Jv_ThreadWait (void)
{
}
inline void
_Jv_ThreadInterrupt (_Jv_Thread_t *)
{
}
#endif /* __JV_NO_THREADS__ */

View file

@ -0,0 +1,210 @@
// -*- c++ -*-
// posix-threads.h - Defines for using POSIX threads.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JV_POSIX_THREADS__
#define __JV_POSIX_THREADS__
// NOTE: This file may only reference those pthread functions which
// are known not to be overridden by the Boehm GC. If in doubt, scan
// boehm-gc/gc.h. This is yucky but lets us avoid including gc.h
// everywhere (which would be truly yucky).
#include <pthread.h>
#include <sched.h>
#if defined (HAVE_PTHREAD_MUTEXATTR_SETTYPE) || defined (HAVE_PTHREAD_MUTEXATTR_SETKIND_NP)
# define HAVE_RECURSIVE_MUTEX 1
#endif
//
// Typedefs.
//
typedef pthread_cond_t _Jv_ConditionVariable_t;
#ifdef HAVE_RECURSIVE_MUTEX
typedef pthread_mutex_t _Jv_Mutex_t;
#else
// Some systems do not have recursive mutexes, so we must simulate
// them. Solaris is one such system.
typedef struct
{
// Mutex used when locking this structure transiently.
pthread_mutex_t mutex;
// Mutex the thread holds the entire time this mutex is held. This
// is used to make condition variables work properly.
pthread_mutex_t mutex2;
// Condition variable used when waiting for this lock.
pthread_cond_t cond;
// Thread holding this mutex. If COUNT is 0, no thread is holding.
pthread_t thread;
// Number of times mutex is held. If 0, the lock is not held.
int count;
} _Jv_Mutex_t;
#endif /* HAVE_RECURSIVE_MUTEX */
typedef struct
{
// Flag values are defined in implementation.
int flags;
// Actual thread id.
pthread_t thread;
// Exception we want to throw when cancelled.
void *exception;
} _Jv_Thread_t;
typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
//
// Condition variables.
//
inline void
_Jv_CondInit (_Jv_ConditionVariable_t *cv)
{
pthread_cond_init (cv, 0);
}
#ifndef LINUX_THREADS
// pthread_cond_destroy does nothing on Linux and it is a win to avoid
// defining this macro.
#define _Jv_HaveCondDestroy
inline void
_Jv_CondDestroy (_Jv_ConditionVariable_t *cv)
{
pthread_cond_destroy (cv);
}
#endif /* LINUX_THREADS */
int _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
jlong millis, jint nanos);
inline int
_Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *)
{
// FIXME: check to see if mutex is held by current thread.
return pthread_cond_signal (cv);
}
inline int
_Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *)
{
// FIXME: check to see if mutex is held by current thread.
return pthread_cond_broadcast (cv);
}
//
// Mutexes.
//
#ifdef RECURSIVE_MUTEX_IS_DEFAULT
inline void
_Jv_MutexInit (_Jv_Mutex_t *mu)
{
pthread_mutex_init (mu, NULL);
}
#else
void _Jv_MutexInit (_Jv_Mutex_t *mu);
#endif
#ifndef LINUX_THREADS
// pthread_mutex_destroy does nothing on Linux and it is a win to avoid
// defining this macro.
#define _Jv_HaveMutexDestroy
#ifdef HAVE_RECURSIVE_MUTEX
inline void
_Jv_MutexDestroy (_Jv_Mutex_t *mu)
{
pthread_mutex_destroy (mu);
}
#else /* HAVE_RECURSIVE_MUTEX */
extern void _Jv_MutexDestroy (_Jv_Mutex_t *mu);
#endif /* HAVE_RECURSIVE_MUTEX */
#endif /* LINUX_THREADS */
#ifdef HAVE_RECURSIVE_MUTEX
inline int
_Jv_MutexLock (_Jv_Mutex_t *mu)
{
return pthread_mutex_lock (mu);
}
inline int
_Jv_MutexUnlock (_Jv_Mutex_t *mu)
{
return pthread_mutex_unlock (mu);
}
#else /* HAVE_RECURSIVE_MUTEX */
extern int _Jv_MutexLock (_Jv_Mutex_t *mu);
extern int _Jv_MutexUnlock (_Jv_Mutex_t *mu);
#endif /* HAVE_RECURSIVE_MUTEX */
//
// Thread creation and manipulation.
//
void _Jv_InitThreads (void);
void _Jv_ThreadInitData (_Jv_Thread_t **data, java::lang::Thread *thread);
inline java::lang::Thread *
_Jv_ThreadCurrent (void)
{
extern pthread_key_t _Jv_ThreadKey;
return (java::lang::Thread *) pthread_getspecific (_Jv_ThreadKey);
}
inline void
_Jv_ThreadYield (void)
{
#ifdef HAVE_SCHED_YIELD
sched_yield ();
#endif /* HAVE_SCHED_YIELD */
}
void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio);
void _Jv_ThreadCancel (_Jv_Thread_t *data, void *error);
// Like Cancel, but doesn't run cleanups.
inline void
_Jv_ThreadDestroy (_Jv_Thread_t *)
{
JvFail ("_Jv_ThreadDestroy");
}
void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
_Jv_ThreadStartFunc *meth);
void _Jv_ThreadWait (void);
void _Jv_ThreadInterrupt (_Jv_Thread_t *data);
#endif /* __JV_POSIX_THREADS__ */

View file

@ -0,0 +1,139 @@
// -*- c++ -*-
// quick-threads.h - Defines for using QuickThreads.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __JV_QUICK_THREADS__
#define __JV_QUICK_THREADS__
#include <coop.h>
//
// Typedefs.
//
typedef coop_c _Jv_ConditionVariable_t;
typedef coop_m _Jv_Mutex_t;
typedef coop_t *_Jv_Thread_t;
typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
//
// Condition variables.
//
inline void
_Jv_CondInit (_Jv_ConditionVariable_t *cv)
{
coop_condition_variable_init (cv);
}
inline int
_Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
jlong millis, jint nanos)
{
return coop_condition_variable_wait (cv, mu, millis * 1000 + nanos / 1000);
}
inline int
_Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu)
{
return coop_condition_variable_signal (cv, mu);
}
inline int
_Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu)
{
return coop_condition_variable_signal_all (cv, mu);
}
//
// Mutexes.
//
inline void
_Jv_MutexInit (_Jv_Mutex_t *mu)
{
coop_mutex_init (mu);
}
inline int
_Jv_MutexLock (_Jv_Mutex_t *mu)
{
coop_mutex_lock (mu);
return 0;
}
inline int
_Jv_MutexUnlock (_Jv_Mutex_t *mu)
{
return coop_mutex_unlock (mu);
}
//
// Thread creation and manipulation.
//
void _Jv_InitThreads (void);
inline void
_Jv_ThreadInitData (_Jv_Thread_t **data, java::lang::Thread *)
{
*data = new _Jv_Thread_t;
**data = (coop_t *) 0;
}
inline java::lang::Thread *
_Jv_ThreadCurrent (void)
{
extern int _Jv_ThreadKey;
return (java::lang::Thread *) coop_getspecific (_Jv_ThreadKey);
}
inline void
_Jv_ThreadYield (void)
{
coop_yield ();
}
inline void
_Jv_ThreadSetPriority (_Jv_Thread_t *, jint)
{
}
inline void
_Jv_ThreadCancel (_Jv_Thread_t *data, void *error)
{
coop_terminate (*data, error);
}
// Like Cancel, but doesn't run cleanups.
inline void
_Jv_ThreadDestroy (_Jv_Thread_t *data)
{
coop_terminate (*data, 0);
}
void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
_Jv_ThreadStartFunc *meth);
inline void
_Jv_ThreadWait (void)
{
coop_start ();
}
inline void
_Jv_ThreadInterrupt (_Jv_Thread_t *)
{
}
#endif /* __JV_QUICK_THREADS__ */

View file

@ -0,0 +1,168 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 8, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class BufferedInputStream extends FilterInputStream
{
/* Internal buffer array for data. */
protected byte[] buf;
/* Index one greater than the last valid byte in the buffer. */
protected int count = 0;
/* The current position in the buffer. */
protected int pos = 0;
/* The value of pos the last time mark() was called. */
protected int markpos = -1;
/* The maximum read-ahead allowed before calls to reset() fail. */
protected int marklimit = 0;
public BufferedInputStream(InputStream in)
{
this(in, 2048);
}
public BufferedInputStream(InputStream in, int size)
{
super(in);
if (size <= 0)
throw new IllegalArgumentException();
buf = new byte[size];
}
public synchronized int available() throws IOException
{
return count - pos + super.available();
}
public void close() throws IOException
{
// Free up the array memory.
buf = null;
super.close();
}
public synchronized void mark(int readlimit)
{
marklimit = readlimit;
markpos = pos;
}
public boolean markSupported()
{
return true;
}
public synchronized int read() throws IOException
{
if (pos >= count && !refill())
return -1; // EOF
if (markpos >= 0 && pos - markpos > marklimit)
markpos = -1;
return ((int) buf[pos++]) & 0xFF;
}
public synchronized int read(byte[] b, int off, int len) throws IOException
{
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
if (pos >= count && !refill())
return -1; // No bytes were read before EOF.
int remain = Math.min(count - pos, len);
System.arraycopy(buf, pos, b, off, remain);
pos += remain;
if (markpos >= 0 && pos - markpos > marklimit)
markpos = -1;
return remain;
}
public synchronized void reset() throws IOException
{
if (markpos < 0)
throw new IOException();
pos = markpos;
}
public synchronized long skip(long n) throws IOException
{
final long origN = n;
while (n > 0L)
{
if (pos >= count && !refill())
if (n < origN)
break;
else
return -1; // No bytes were read before EOF.
int numread = (int) Math.min((long) (count - pos), n);
pos += numread;
n -= numread;
if (markpos >= 0 && pos - markpos > marklimit)
markpos = -1;
}
return origN - n;
}
private boolean refill() throws IOException
{
if (markpos < 0)
count = pos = 0;
else if (markpos > 0)
{
// Shift the marked bytes (if any) to the beginning of the array
// but don't grow it. This saves space in case a reset is done
// before we reach the max capacity of this array.
System.arraycopy(buf, markpos, buf, 0, count - markpos);
count -= markpos;
pos -= markpos;
markpos = 0;
}
else if (marklimit >= buf.length) // BTW, markpos == 0
{
// Need to grow the buffer now to have room for marklimit bytes.
// Note that the new buffer is one greater than marklimit.
// This is so that there will be one byte past marklimit to be read
// before having to call refill again, thus allowing marklimit to be
// invalidated. That way refill doesn't have to check marklimit.
byte[] newbuf = new byte[marklimit + 1];
System.arraycopy(buf, 0, newbuf, 0, count);
buf = newbuf;
}
int numread = super.read(buf, count, buf.length - count);
if (numread < 0) // EOF
return false;
count += numread;
return true;
}
}

View file

@ -0,0 +1,76 @@
// BufferedOutputStream.java - A buffered stream
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1.
*/
public class BufferedOutputStream extends FilterOutputStream
{
public BufferedOutputStream (OutputStream ox)
{
this (ox, 512);
}
public BufferedOutputStream (OutputStream ox, int size)
{
super (ox);
buf = new byte[size];
}
public synchronized void flush () throws IOException
{
out.write(buf, 0, count);
count = 0;
out.flush();
}
public synchronized void write (int b) throws IOException
{
if (count < buf.length)
buf[count++] = (byte) b;
else
{
out.write(buf, 0, count);
count = 0;
out.write(b);
}
}
public synchronized void write (byte[] b, int off, int len)
throws IOException, NullPointerException, IndexOutOfBoundsException
{
// If LEN < 0 then the downstream write will fail for us.
if (len >= 0 && count + len < buf.length)
{
System.arraycopy(b, off, buf, count, len);
count += len;
}
else
{
out.write(buf, 0, count);
count = 0;
out.write(b, off, len);
}
}
// The buffer.
protected byte[] buf;
// Number of valid bytes in BUF.
protected int count;
}

View file

@ -0,0 +1,373 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date April 22, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class BufferedReader extends Reader
{
Reader in;
char[] buffer;
/* Index of current read position. Must be >= 0 and <= limit. */
/* There is a special case where pos may be equal to limit+1; this
* is used as an indicator that a readLine was done with a '\r' was
* the very last char in the buffer. Since we don't want to read-ahead
* and potentially block, we set pos this way to indicate the situation
* and deal with it later. Doing it this way rather than having a
* separate boolean field to indicate the condition has the advantage
* that it is self-clearing on things like mark/reset.
*/
int pos;
/* Limit of valid data in buffer. Must be >= pos and <= buffer.length. */
/* This can be < pos in the one special case described above. */
int limit;
/* The value -1 means there is no mark, or the mark has been invalidated.
Otherwise, markPos is the index in the buffer of the marked position.
Must be >= 0 and <= pos.
Note we do not explicitly store the read-limit.
The implicit read-limit is (buffer.length - markPos), which is
guaranteed to be >= the read-limit requested in the call to mark. */
int markPos = -1;
public BufferedReader(Reader in)
{
this(in, 8192);
}
public BufferedReader(Reader in, int size)
{
super(in.lock);
this.in = in;
buffer = new char[size];
}
public void close() throws IOException
{
synchronized (lock)
{
if (in != null)
in.close();
in = null;
buffer = null;
}
}
public boolean markSupported()
{
return true;
}
public void mark(int readLimit) throws IOException
{
synchronized (lock)
{
// In this method we need to be aware of the special case where
// pos + 1 == limit. This indicates that a '\r' was the last char
// in the buffer during a readLine. We'll want to maintain that
// condition after we shift things around and if a larger buffer is
// needed to track readLimit, we'll have to make it one element
// larger to ensure we don't invalidate the mark too early, if the
// char following the '\r' is NOT a '\n'. This is ok because, per
// the spec, we are not required to invalidate when passing readLimit.
//
// Note that if 'pos > limit', then doing 'limit -= pos' will cause
// limit to be negative. This is the only way limit will be < 0.
if (pos + readLimit > limit)
{
char[] old_buffer = buffer;
int extraBuffSpace = 0;
if (pos > limit)
extraBuffSpace = 1;
if (readLimit + extraBuffSpace > limit)
buffer = new char[readLimit + extraBuffSpace];
limit -= pos;
if (limit >= 0)
{
System.arraycopy(old_buffer, pos, buffer, 0, limit);
pos = 0;
}
}
if (limit < 0)
{
// Maintain the relationship of 'pos > limit'.
pos = 1;
limit = markPos = 0;
}
else
markPos = pos;
// Now pos + readLimit <= buffer.length. thus if we need to read
// beyond buffer.length, then we are allowed to invalidate markPos.
}
}
public void reset() throws IOException
{
synchronized (lock)
{
if (markPos < 0)
throw new IOException("mark never set or invalidated");
// Need to handle the extremely unlikely case where a readLine was
// done with a '\r' as the last char in the buffer; which was then
// immediately followed by a mark and a reset with NO intervening
// read of any sort. In that case, setting pos to markPos would
// lose that info and a subsequent read would thus not skip a '\n'
// (if one exists). The value of limit in this rare case is zero.
// We can assume that if limit is zero for other reasons, then
// pos is already set to zero and doesn't need to be readjusted.
if (limit > 0)
pos = markPos;
}
}
public boolean ready() throws IOException
{
synchronized (lock)
{
return pos < limit || in.ready();
}
}
public int read(char[] buf, int offset, int count) throws IOException
{
synchronized (lock)
{
// Once again, we need to handle the special case of a readLine
// that has a '\r' at the end of the buffer. In this case, we'll
// need to skip a '\n' if it is the next char to be read.
// This special case is indicated by 'pos > limit'.
boolean retAtEndOfBuffer = false;
int avail = limit - pos;
if (count > avail)
{
if (avail > 0)
count = avail;
else // pos >= limit
{
if (limit == buffer.length)
markPos = -1; // read too far - invalidate the mark.
if (pos > limit)
{
// Set a boolean and make pos == limit to simplify things.
retAtEndOfBuffer = true;
--pos;
}
if (markPos < 0)
{
// Optimization: can read directly into buf.
if (count >= buffer.length && !retAtEndOfBuffer)
return in.read(buf, offset, count);
pos = limit = 0;
}
avail = in.read(buffer, limit, buffer.length - limit);
if (retAtEndOfBuffer && avail > 0 && buffer[limit] == '\n')
{
--avail;
limit++;
}
if (avail < count)
{
if (avail <= 0)
return avail;
count = avail;
}
limit += avail;
}
}
System.arraycopy(buffer, pos, buf, offset, count);
pos += count;
return count;
}
}
/* Read more data into the buffer. Update pos and limit appropriatly.
Assumes pos==limit initially. May invalidate the mark if read too much.
Return number of chars read (never 0), or -1 on eof. */
private int fill() throws IOException
{
// Handle the special case of a readLine that has a '\r' at the end of
// the buffer. In this case, we'll need to skip a '\n' if it is the
// next char to be read. This special case is indicated by 'pos > limit'.
boolean retAtEndOfBuffer = false;
if (pos > limit)
{
retAtEndOfBuffer = true;
--pos;
}
if (markPos >= 0 && limit == buffer.length)
markPos = -1;
if (markPos <= 0)
pos = limit = 0;
int count = in.read(buffer, limit, buffer.length - limit);
if (count > 0)
limit += count;
if (retAtEndOfBuffer && buffer[pos] == '\n')
{
--count;
pos++;
}
return count;
}
public int read() throws IOException
{
synchronized (lock)
{
if (pos >= limit && fill () <= 0)
return -1;
return buffer[pos++];
}
}
/* Return the end of the line starting at this.pos and ending at limit.
* The index returns is *before* any line terminators, or limit
* if no line terminators were found.
*/
private int lineEnd(int limit)
{
int i = pos;
for (; i < limit; i++)
{
char ch = buffer[i];
if (ch == '\n' || ch == '\r')
break;
}
return i;
}
public String readLine() throws IOException
{
// Handle the special case where a previous readLine (with no intervening
// reads/skips) had a '\r' at the end of the buffer.
// In this case, we'll need to skip a '\n' if it's the next char to be read.
// This special case is indicated by 'pos > limit'.
if (pos > limit)
{
int ch = read();
if (ch < 0)
return null;
if (ch != '\n')
--pos;
}
int i = lineEnd(limit);
if (i < limit)
{
String str = new String(buffer, pos, i - pos);
pos = i + 1;
// If the last char in the buffer is a '\r', we must remember
// to check if the next char to be read after the buffer is refilled
// is a '\n'. If so, skip it. To indicate this condition, we set pos
// to be limit + 1, which normally is never possible.
if (buffer[i] == '\r')
if (pos == limit || buffer[pos] == '\n')
pos++;
return str;
}
StringBuffer sbuf = new StringBuffer(200);
sbuf.append(buffer, pos, i - pos);
pos = i;
// We only want to return null when no characters were read before
// EOF. So we must keep track of this separately. Otherwise we
// would treat an empty `sbuf' as an EOF condition, which is wrong
// when there is just a newline.
boolean eof = false;
for (;;)
{
int ch = read();
if (ch < 0)
{
eof = true;
break;
}
if (ch == '\n' || ch == '\r')
{
// Check here if a '\r' was the last char in the buffer; if so,
// mark it as in the comment above to indicate future reads
// should skip a newline that is the next char read after
// refilling the buffer.
if (ch == '\r')
if (pos == limit || buffer[pos] == '\n')
pos++;
break;
}
i = lineEnd(limit);
sbuf.append(buffer, pos - 1, i - (pos - 1));
pos = i;
}
return (sbuf.length() == 0 && eof) ? null : sbuf.toString();
}
public long skip(long count) throws IOException
{
if (count <= 0)
return 0;
synchronized (lock)
{
// Yet again, we need to handle the special case of a readLine
// that has a '\r' at the end of the buffer. In this case, we need
// to ignore a '\n' if it is the next char to be read.
// This special case is indicated by 'pos > limit' (i.e. avail < 0).
// To simplify things, if we're dealing with the special case for
// readLine, just read the next char (since the fill method will
// skip the '\n' for us). By doing this, we'll have to back up pos.
// That's easier than trying to keep track of whether we've skipped
// one element or not.
int ch;
if (pos > limit)
if ((ch = read()) < 0)
return 0;
else
--pos;
int avail = limit - pos;
if (count < avail)
{
pos += count;
return count;
}
pos = limit;
long todo = count - avail;
if (todo > buffer.length)
{
markPos = -1;
todo -= in.skip(todo);
}
else
{
while (todo > 0)
{
avail = fill();
if (avail <= 0)
break;
if (avail > todo)
avail = (int) todo;
pos += avail;
todo -= avail;
}
}
return count - todo;
}
}
}

View file

@ -0,0 +1,129 @@
// BufferedWriter.java - Filtered character output stream.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 25, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1.
*/
// Why not extend FilterWriter?
public class BufferedWriter extends Writer
{
public BufferedWriter (Writer out)
{
this (out, 8192);
}
public BufferedWriter (Writer ox, int size)
{
super (ox);
out = ox;
buffer = new char[size];
count = 0;
}
public void close () throws IOException
{
localFlush ();
out.close();
}
public void flush () throws IOException
{
localFlush ();
out.flush();
}
public void newLine () throws IOException
{
write (System.getProperty("line.separator"));
}
public void write (int oneChar) throws IOException
{
synchronized (lock)
{
buffer[count++] = (char) oneChar;
if (count == buffer.length)
localFlush ();
}
}
public void write (char[] buf, int offset, int len) throws IOException
{
if (offset < 0 || len < 0 || offset + len > buf.length)
throw new ArrayIndexOutOfBoundsException ();
synchronized (lock)
{
// Bypass buffering if there is too much incoming data.
if (count + len > buffer.length)
{
localFlush ();
out.write(buf, offset, len);
}
else
{
System.arraycopy(buf, offset, buffer, count, len);
count += len;
if (count == buffer.length)
localFlush ();
}
}
}
public void write (String str, int offset, int len) throws IOException
{
if (offset < 0 || len < 0 || offset + len < str.length())
throw new ArrayIndexOutOfBoundsException ();
synchronized (lock)
{
if (count + len > buffer.length)
{
localFlush ();
out.write(str, offset, len);
}
else
{
str.getChars(offset, offset + len, buffer, count);
count += len;
if (count == buffer.length)
localFlush ();
}
}
}
private final void localFlush () throws IOException
{
if (count > 0)
{
synchronized (lock)
{
out.write(buffer, 0, count);
count = 0;
}
}
}
// The downstream writer.
private Writer out;
// The character buffer.
char[] buffer;
// Number of valid chars in buffer.
int count;
}

View file

@ -0,0 +1,113 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 7, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct
*/
public class ByteArrayInputStream extends InputStream
{
/* An array of bytes provided by the creator of the stream. */
protected byte[] buf;
/* Position of the next byte in buf to be read. */
protected int pos;
/* The currently marked position in the stream. */
protected int mark;
/* The index in buf one greater than the last valid character. */
protected int count;
public ByteArrayInputStream(byte[] buffer)
{
this(buffer, 0, buffer.length);
}
public ByteArrayInputStream(byte[] buffer, int offset, int length)
{
buf = buffer;
count = offset + length;
if (count > buf.length)
count = buf.length;
pos = offset;
// TBD: What should we do if pos is neg. or > count? E.g. throw exc. or:
// if (pos < 0 || pos > count)
// pos = 0;
mark = pos;
}
public synchronized int available()
{
return count - pos;
}
public synchronized void mark(int readAheadLimit)
{
// readAheadLimit is ignored per Java Class Lib. book, p.220.
mark = pos;
}
public boolean markSupported()
{
return true;
}
public synchronized int read()
{
if (pos < 0)
throw new ArrayIndexOutOfBoundsException(pos);
if (pos < count)
return ((int) buf[pos++]) & 0xFF;
return -1;
}
public synchronized int read(byte[] b, int off, int len)
{
/* Don't need to check pos value, arraycopy will check it. */
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
if (pos >= count)
return -1;
int numBytes = Math.min(count - pos, len);
System.arraycopy(buf, pos, b, off, numBytes);
pos += numBytes;
return numBytes;
}
public synchronized void reset()
{
pos = mark;
}
public synchronized long skip(long n)
{
// Even though the var numBytes is a long, in reality it can never
// be larger than an int since the result of subtracting 2 positive
// ints will always fit in an int. Since we have to return a long
// anyway, numBytes might as well just be a long.
long numBytes = Math.min((long) (count - pos), n < 0 ? 0L : n);
pos += numBytes;
return numBytes;
}
}

View file

@ -0,0 +1,108 @@
// ByteArrayOutputStream.java - Write bytes to an array.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1.
*/
public class ByteArrayOutputStream extends OutputStream
{
public ByteArrayOutputStream ()
{
this (32);
}
public ByteArrayOutputStream (int size)
{
buf = new byte[size];
count = 0;
}
public synchronized void reset ()
{
count = 0;
}
public int size ()
{
return count;
}
public synchronized byte[] toByteArray ()
{
byte[] ret = new byte[count];
System.arraycopy(buf, 0, ret, 0, count);
return ret;
}
public String toString ()
{
return new String (buf, 0, count);
}
public String toString (String enc) throws UnsupportedEncodingException
{
return new String (buf, 0, count, enc);
}
// This is deprecated in the JCL book.
public String toString (int hibyte)
{
return new String (buf, 0, count, hibyte);
}
// Resize buffer to accomodate new bytes.
private void resize (int add)
{
if (count + add >= buf.length)
{
int newlen = buf.length * 2;
if (count + add > newlen)
newlen = count + add;
byte[] newbuf = new byte[newlen];
System.arraycopy(buf, 0, newbuf, 0, count);
buf = newbuf;
}
}
public synchronized void write (int oneByte)
{
resize (1);
buf[count++] = (byte) oneByte;
}
public synchronized void write (byte[] buffer, int offset, int add)
{
// If ADD < 0 then arraycopy will throw the appropriate error for
// us.
if (add >= 0)
resize (add);
System.arraycopy(buffer, offset, buf, count, add);
count += add;
}
public synchronized void writeTo (OutputStream out) throws IOException
{
out.write(buf, 0, count);
}
// The byte buffer.
protected byte[] buf;
// Number of valid bytes in buffer.
protected int count;
}

View file

@ -0,0 +1,152 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 16, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct
*/
public class CharArrayReader extends Reader
{
/* An array of chars provided by the creator of the stream. */
protected char[] buf;
/* Position of the next char in buf to be read. */
protected int pos;
/* The currently marked position in the stream. */
protected int markedPos;
/* The index in buf one greater than the last valid character. */
protected int count;
public CharArrayReader(char[] buffer)
{
this(buffer, 0, buffer.length);
}
public CharArrayReader(char[] buffer, int offset, int length)
{
super();
buf = buffer;
count = offset + length;
if (count > buf.length)
count = buf.length;
pos = offset;
// TBD: What should we do if pos is neg. or > count? E.g. throw exc. or:
// if (pos < 0 || pos > count)
// pos = 0;
markedPos = pos;
}
public void close()
{
synchronized (lock)
{
buf = null;
}
}
public void mark(int readAheadLimit)
{
synchronized (lock)
{
// readAheadLimit is ignored per Java Class Lib. book, p. 318.
markedPos = pos;
}
}
public boolean markSupported()
{
return true;
}
public int read() throws IOException
{
synchronized (lock)
{
if (buf == null)
throw new IOException();
if (pos < 0)
throw new ArrayIndexOutOfBoundsException(pos);
if (pos < count)
return ((int) buf[pos++]) & 0xFFFF;
return -1;
}
}
public int read(char[] b, int off, int len) throws IOException
{
synchronized (lock)
{
if (buf == null)
throw new IOException();
/* Don't need to check pos value, arraycopy will check it. */
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
if (pos >= count)
return -1;
int numChars = Math.min(count - pos, len);
System.arraycopy(buf, pos, b, off, numChars);
pos += numChars;
return numChars;
}
}
public boolean ready() throws IOException
{
if (buf == null)
throw new IOException();
return true;
}
public void reset() throws IOException
{
synchronized (lock)
{
if (buf == null)
throw new IOException();
pos = markedPos;
}
}
public long skip(long n) throws IOException
{
synchronized (lock)
{
if (buf == null)
throw new IOException();
// Even though the var numChars is a long, in reality it can never
// be larger than an int since the result of subtracting 2 positive
// ints will always fit in an int. Since we have to return a long
// anyway, numChars might as well just be a long.
long numChars = Math.min((long) (count - pos), n < 0 ? 0L : n);
pos += numChars;
return numChars;
}
}
}

View file

@ -0,0 +1,122 @@
// CharArrayWriter.java - Character array output stream.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 25, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to 1.1.
*/
public class CharArrayWriter extends Writer
{
public CharArrayWriter ()
{
this (32);
}
public CharArrayWriter (int size)
{
super ();
buf = new char[size];
}
public void close ()
{
// JCL says this does nothing. This seems to violate the Writer
// contract, in that other methods should still throw and
// IOException after a close. Still, we just follow JCL.
}
public void flush ()
{
}
public synchronized void reset ()
{
count = 0;
}
public int size ()
{
return count;
}
public char[] toCharArray ()
{
char[] nc = new char[count];
System.arraycopy(buf, 0, nc, 0, count);
return nc;
}
public String toString ()
{
return new String (buf, 0, count);
}
public void write (int oneChar)
{
synchronized (lock)
{
resize (1);
buf[count++] = (char) oneChar;
}
}
public void write (char[] buffer, int offset, int len)
{
synchronized (lock)
{
if (len >= 0)
resize (len);
System.arraycopy(buffer, offset, buf, count, len);
count += len;
}
}
public void write (String str, int offset, int len)
{
synchronized (lock)
{
if (len >= 0)
resize (len);
str.getChars(offset, offset + len, buf, count);
count += len;
}
}
public void writeTo (Writer out) throws IOException
{
out.write(buf, 0, count);
}
private final void resize (int len)
{
if (count + len >= buf.length)
{
int newlen = buf.length * 2;
if (count + len > newlen)
newlen = count + len;
char[] newbuf = new char[newlen];
System.arraycopy(buf, 0, newbuf, 0, count);
buf = newbuf;
}
}
// The character buffer.
protected char[] buf;
// Number of valid characters in buffer.
protected int count;
}

View file

@ -0,0 +1,34 @@
// CharConversionException.java - Problem converting char to byte encoding.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 25, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to 1.1.
*/
public class CharConversionException extends IOException
{
public CharConversionException ()
{
super ();
}
public CharConversionException (String s)
{
super (s);
}
}

View file

@ -0,0 +1,41 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 2, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public interface DataInput
{
public boolean readBoolean() throws IOException;
public byte readByte() throws IOException;
public char readChar() throws IOException;
public double readDouble() throws IOException;
public float readFloat() throws IOException;
public void readFully(byte[] b)
throws IOException, NullPointerException;
public void readFully(byte[] b, int off, int len)
throws IOException, NullPointerException, IndexOutOfBoundsException;
public int readInt() throws IOException;
public String readLine() throws IOException;
public long readLong() throws IOException;
public short readShort() throws IOException;
public int readUnsignedByte() throws IOException;
public int readUnsignedShort() throws IOException;
public String readUTF() throws IOException;
public int skipBytes(int n) throws IOException;
}

View file

@ -0,0 +1,249 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 20, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class DataInputStream extends FilterInputStream implements DataInput
{
public DataInputStream(InputStream in)
{
super(in);
}
public final int read(byte[] b) throws IOException
{
return super.read(b, 0, b.length);
}
public final int read(byte[] b, int off, int len) throws IOException
{
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
return super.read(b, off, len);
}
public final boolean readBoolean() throws IOException
{
return (readByte() != 0);
}
public final byte readByte() throws IOException
{
int i = read();
if (i < 0)
throw new EOFException();
return (byte) i;
}
public final char readChar() throws IOException
{
return (char) ((readByte() << 8) | readUnsignedByte());
}
public final double readDouble() throws IOException
{
return Double.longBitsToDouble(readLong());
}
public final float readFloat() throws IOException
{
return Float.intBitsToFloat(readInt());
}
public final void readFully(byte[] b) throws IOException
{
readFully(b, 0, b.length);
}
public final void readFully(byte[] b, int off, int len) throws IOException
{
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
while (len > 0)
{
// super.read will block until some data is available.
int numread = super.read(b, off, len);
if (numread < 0)
throw new EOFException();
len -= numread;
off += numread;
}
}
public final int readInt() throws IOException
{
int retval = 0;
for (int i = 0; i < 4; i++)
retval |= readUnsignedByte() << (24 - i * 8);
return retval;
}
// Deprecated as of JDK 1.1
public final String readLine() throws IOException
{
StringBuffer strb = new StringBuffer();
while (true)
{
char ch = (char) read();
if (ch < 0 || (ch &= 0xFF) == '\n')
break;
if (ch == '\r')
{
// FIXME: The following code tries to adjust the stream back one
// character if the next char read is '\n'. As a last resort,
// it tries to mark the position before reading but the bottom
// line is that it is possible that this method will not properly
// deal with a '\r' '\n' combination thus not fulfilling the
// DataInput contract for readLine. It's not a particularly
// safe approach threadwise since it is unsynchronized and
// since it might mark an input stream behind the users back.
// Along the same vein it could try the same thing for
// ByteArrayInputStream and PushbackInputStream, but that is
// probably overkill since this is deprecated & BufferedInputStream
// is the most likely type of input stream.
//
// The alternative is to somehow push back the next byte if it
// isn't a '\n' or to have the reading methods of this class
// keep track of whether the last byte read was '\r' by readLine
// and then skip the very next byte if it is '\n'. Either way,
// this would increase the complexity of the non-deprecated methods
// and since it is undesirable to make non-deprecated methods
// less efficient, the following seems like the most reasonable
// approach.
if (in instanceof BufferedInputStream && (read() & 0xFF) != '\n')
{
BufferedInputStream bin = (BufferedInputStream) in;
if (bin.pos > 0)
bin.pos--;
}
else if (markSupported())
{
mark(1);
if ((read() & 0xFF) != '\n')
reset();
}
break;
}
strb.append(ch);
}
return strb.length() > 0 ? strb.toString() : null;
}
public final long readLong() throws IOException
{
long retval = 0L;
for (int i = 0; i < 8; i++)
retval |= (long) readUnsignedByte() << (56 - i * 8);
return retval;
}
public final short readShort() throws IOException
{
return (short) ((readByte() << 8) | readUnsignedByte());
}
public final int readUnsignedByte() throws IOException
{
int i = read();
if (i < 0)
throw new EOFException();
return (i & 0xFF);
}
public final int readUnsignedShort() throws IOException
{
return (readUnsignedByte() << 8) | readUnsignedByte();
}
public final String readUTF() throws IOException
{
return readUTF(this);
}
public final static String readUTF(DataInput in) throws IOException
{
final int UTFlen = in.readUnsignedShort();
byte[] buf = new byte[UTFlen];
StringBuffer strbuf = new StringBuffer();
// This blocks until the entire string is available rather than
// doing partial processing on the bytes that are available and then
// blocking. An advantage of the latter is that Exceptions
// could be thrown earlier. The former is a bit cleaner.
in.readFully(buf, 0, UTFlen);
for (int i = 0; i < UTFlen; )
{
if ((buf[i] & 0x80) == 0) // bit pattern 0xxxxxxx
strbuf.append((char) (buf[i++] & 0xFF));
else if ((buf[i] & 0xE0) == 0xC0) // bit pattern 110xxxxx
{
if (i + 1 >= UTFlen || (buf[i+1] & 0xC0) != 0x80)
throw new UTFDataFormatException();
strbuf.append((char) (((buf[i++] & 0x1F) << 6) |
(buf[i++] & 0x3F)));
}
else if ((buf[i] & 0xF0) == 0xE0) // bit pattern 1110xxxx
{
if (i + 2 >= UTFlen ||
(buf[i+1] & 0xC0) != 0x80 || (buf[i+2] & 0xC0) != 0x80)
throw new UTFDataFormatException();
strbuf.append((char) (((buf[i++] & 0x0F) << 12) |
((buf[i++] & 0x3F) << 6) |
(buf[i++] & 0x3F)));
}
else // must be ((buf[i] & 0xF0) == 0xF0 || (buf[i] & 0xC0) == 0x80)
throw new UTFDataFormatException(); // bit patterns 1111xxxx or
// 10xxxxxx
}
return strbuf.toString();
}
public final int skipBytes(int n) throws IOException
{
// The contract in the Java Lang. Spec. says that this never
// throws an EOFException and infers that it doesn't block (since
// it may skip less than the requested number of bytes).
// BUT, the JCL book specifically says that this method blocks
// and can throw an EOFException. Finally, the Java 1.2 online
// doc simply refers to the general contract. As such, we will
// stick to the contract and assume for now that the JCL book
// is incorrect.
// Since we're only skipping at most an int number of bytes, the cast
// of return value to an int is fine.
if (n > 0)
{
n = Math.min(n, available());
return (int) super.skip((long) n);
}
return 0;
}
}

View file

@ -0,0 +1,44 @@
// DataOutput.java - Interface for data output conversions.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1.
*/
public interface DataOutput
{
public abstract void write (int b) throws IOException;
public abstract void write (byte[] b)
throws IOException, NullPointerException;
public abstract void write (byte[] b, int off, int len)
throws IOException, NullPointerException, IndexOutOfBoundsException;
public abstract void writeBoolean (boolean v) throws IOException;
public abstract void writeByte (int v) throws IOException;
public abstract void writeShort (int v) throws IOException;
public abstract void writeChar (int v) throws IOException;
public abstract void writeInt (int v) throws IOException;
public abstract void writeLong (long v) throws IOException;
public abstract void writeFloat (float v) throws IOException;
public abstract void writeDouble (double v) throws IOException;
public abstract void writeBytes (String s)
throws IOException, NullPointerException;
public abstract void writeChars (String s)
throws IOException, NullPointerException;
public abstract void writeUTF (String s)
throws IOException, NullPointerException;
}

View file

@ -0,0 +1,165 @@
// DataOutputStream.java - Output filter that implements DataOutput
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1.
*/
public class DataOutputStream extends FilterOutputStream implements DataOutput
{
public DataOutputStream (OutputStream out)
{
super (out);
written = 0;
}
public void flush () throws IOException
{
out.flush();
}
public final int size ()
{
return written;
}
public synchronized void write (int b) throws IOException
{
out.write(b);
++written;
}
public synchronized void write (byte[] b, int off, int len)
throws IOException, NullPointerException, IndexOutOfBoundsException
{
out.write(b, off, len);
written += len - off;
}
public final void writeBoolean (boolean v) throws IOException
{
write (v ? 1 : 0);
}
public final void writeByte (int v) throws IOException
{
write (v & 0xff);
}
public final void writeShort (int v) throws IOException
{
write ((byte) (0xff & (v >> 8)));
write ((byte) (0xff & v));
}
public final void writeChar (int v) throws IOException
{
write ((byte) (0xff & (v >> 8)));
write ((byte) (0xff & v));
}
public final void writeInt (int v) throws IOException
{
write ((byte) (0xff & (v >> 24)));
write ((byte) (0xff & (v >> 16)));
write ((byte) (0xff & (v >> 8)));
write ((byte) (0xff & v));
}
public final void writeLong (long v) throws IOException
{
write ((byte) (0xff & (v >> 56)));
write ((byte) (0xff & (v >> 48)));
write ((byte) (0xff & (v >> 40)));
write ((byte) (0xff & (v >> 32)));
write ((byte) (0xff & (v >> 24)));
write ((byte) (0xff & (v >> 16)));
write ((byte) (0xff & (v >> 8)));
write ((byte) (0xff & v));
}
public final void writeFloat (float v) throws IOException
{
writeInt (Float.floatToIntBits(v));
}
public final void writeDouble (double v) throws IOException
{
writeLong (Double.doubleToLongBits(v));
}
public final void writeBytes (String s) throws IOException
{
int len = s.length();
for (int i = 0; i < len; ++i)
writeByte (s.charAt(i));
}
public final void writeChars (String s) throws IOException
{
int len = s.length();
for (int i = 0; i < len; ++i)
writeChar (s.charAt(i));
}
public final void writeUTF (String s) throws IOException
{
int len = s.length();
int sum = 0;
for (int i = 0; i < len && sum <= 65535; ++i)
{
char c = s.charAt(i);
if (c >= '\u0001' && c <= '\u007f')
sum += 1;
else if (c == '\u0000' || (c >= '\u0080' && c <= '\u07ff'))
sum += 2;
else
sum += 3;
}
if (sum > 65535)
throw new UTFDataFormatException ();
writeShort (sum);
for (int i = 0; i < len; ++i)
{
char c = s.charAt(i);
if (c >= '\u0001' && c <= '\u007f')
write (c);
else if (c == '\u0000' || (c >= '\u0080' && c <= '\u07ff'))
{
write (0xc0 | (0x1f & (c >> 6)));
write (0x80 | (0x3f & c));
}
else
{
// JSL says the first byte should be or'd with 0xc0, but
// that is a typo. Unicode says 0xe0, and that is what is
// consistent with DataInputStream.
write (0xe0 | (0x0f & (c >> 12)));
write (0x80 | (0x3f & (c >> 6)));
write (0x80 | (0x3f & c));
}
}
}
// Number of bytes written so far.
protected int written;
}

View file

@ -0,0 +1,34 @@
// EOFException.java - End of file exception
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to 1.1.
*/
public class EOFException extends IOException
{
public EOFException ()
{
super ();
}
public EOFException (String s)
{
super (s);
}
}

288
libjava/java/io/File.java Normal file
View file

@ -0,0 +1,288 @@
// File.java - File name
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1; 1.2 functionality missing.
* A known bug: most calls to the security manager can generate
* IOException since we use the canonical path.
*/
public class File implements Serializable
{
public boolean canRead ()
{
return access (checkRead (), READ);
}
public boolean canWrite ()
{
SecurityManager s = System.getSecurityManager();
String p = safeCanonicalPath ();
// FIXME: it isn't entirely clear what to do if we can't find the
// canonical path.
if (p == null)
return false;
if (s != null)
s.checkWrite(p);
return access (p, WRITE);
}
private final native boolean performDelete (String canon);
public boolean delete ()
{
SecurityManager s = System.getSecurityManager();
String p = safeCanonicalPath ();
// FIXME: what is right?
if (p == null)
return false;
if (s != null)
s.checkDelete(p);
return performDelete (p);
}
public boolean equals (Object obj)
{
if (! (obj instanceof File))
return false;
File other = (File) obj;
return path.compareTo(other.path) == 0;
}
public boolean exists ()
{
return access (checkRead (), EXISTS);
}
public File (String p)
{
if (p == null)
throw new NullPointerException ();
path = p;
}
public File (String dirPath, String name)
{
if (name == null)
throw new NullPointerException ();
if (dirPath != null)
{
// Try to be smart about the number of separator characters.
if (dirPath.charAt(dirPath.length() - 1) == separatorChar)
path = dirPath + name;
else
path = dirPath + separatorChar + name;
}
else
path = name;
}
public File (File dir, String name)
{
this (dir == null ? null : dir.path, name);
}
public String getAbsolutePath ()
{
if (isAbsolute ())
return path;
return System.getProperty("user.dir") + separatorChar + path;
}
public native String getCanonicalPath () throws IOException;
public String getName ()
{
int last = path.lastIndexOf(separatorChar);
if (last == -1)
last = 0;
return path.substring(last);
}
public String getParent ()
{
int last = path.lastIndexOf(separatorChar);
if (last == -1)
return null;
return path.substring(0, last);
}
public String getPath ()
{
return path;
}
public int hashCode ()
{
// FIXME: test.
return path.hashCode();
}
public native boolean isAbsolute ();
public boolean isDirectory ()
{
return stat (checkRead (), DIRECTORY);
}
public boolean isFile ()
{
return stat (checkRead (), ISFILE);
}
public long lastModified ()
{
return attr (checkRead (), MODIFIED);
}
public long length ()
{
return attr (checkRead (), LENGTH);
}
private final native String[] performList (String canon,
FilenameFilter filter);
public String[] list (FilenameFilter filter)
{
return performList (checkRead (), filter);
}
public String[] list ()
{
return performList (checkRead (), null);
}
public String toString ()
{
return path;
}
private final native boolean performMkdir ();
public boolean mkdir ()
{
SecurityManager s = System.getSecurityManager();
if (s != null)
{
// NOTE: in theory we should use the canonical path. In
// practice, we can't compute the canonical path until we've
// made this completely. Lame.
s.checkWrite(path);
}
return performMkdir ();
}
private static boolean mkdirs (File x)
{
if (x.isDirectory())
return true;
String p = x.getPath();
x.setPath(x.getParent());
if (! mkdirs (x))
return false;
x.setPath(p);
return x.mkdir();
}
public boolean mkdirs ()
{
SecurityManager s = System.getSecurityManager();
if (s != null)
{
// NOTE: in theory we should use the canonical path. In
// practice, we can't compute the canonical path until we've
// made this completely. Lame.
s.checkWrite(path);
}
if (isDirectory ())
return false;
return mkdirs (new File (path));
}
private final native boolean performRenameTo (File dest);
public boolean renameTo (File dest)
{
SecurityManager s = System.getSecurityManager();
if (s != null)
{
// FIXME: JCL doesn't specify which path to check. We check the
// source since we can canonicalize it.
s.checkWrite(safeCanonicalPath());
}
return performRenameTo (dest);
}
public static final String pathSeparator
= System.getProperty("path.separator");
public static final char pathSeparatorChar = pathSeparator.charAt(0);
public static final String separator = System.getProperty("file.separator");
public static final char separatorChar = separator.charAt(0);
// The path.
private String path;
// mkdirs() uses this to avoid repeated allocations.
private final void setPath (String n)
{
path = n;
}
private final String checkRead ()
{
SecurityManager s = System.getSecurityManager();
String p = safeCanonicalPath ();
if (p == null)
return null;
if (s != null)
s.checkRead(p);
return p;
}
// Return canonical path, or null.
private final String safeCanonicalPath ()
{
String p = null;
try
{
p = getCanonicalPath ();
}
catch (IOException x)
{
// Nothing.
}
return p;
}
// QUERY arguments to access function.
private final static int READ = 0;
private final static int WRITE = 1;
private final static int EXISTS = 2;
// QUERY arguments to stat function.
private final static int DIRECTORY = 0;
private final static int ISFILE = 1;
// QUERY arguments to attr function.
private final static int MODIFIED = 0;
private final static int LENGTH = 1;
private final native long attr (String p, int query);
private final native boolean access (String p, int query);
private final native boolean stat (String p, int query);
}

View file

@ -0,0 +1,87 @@
// FileDescriptor.java - Open file or device
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to 1.1
*/
// For now we assume a POSIXy file system. This can be changed later
// if need be.
public final class FileDescriptor
{
public static final FileDescriptor in = new FileDescriptor (0);
public static final FileDescriptor out = new FileDescriptor (1);
public static final FileDescriptor err = new FileDescriptor (2);
public native void sync () throws SyncFailedException;
public native boolean valid ();
// These are mode values for open().
static final int READ = 1;
static final int WRITE = 2;
static final int APPEND = 4;
// These are WHENCE values for seek.
static final int SET = 0;
static final int CUR = 1;
// Open a file. MODE is a combination of the above mode flags.
FileDescriptor (String path, int mode) throws IOException
{
fd = open (path, mode);
}
public FileDescriptor ()
{
fd = -1;
}
native int open (String path, int mode) throws IOException;
native void write (int b) throws IOException;
native void write (byte[] b, int offset, int len)
throws IOException, NullPointerException, IndexOutOfBoundsException;
native void close () throws IOException;
native int seek (long pos, int whence) throws IOException;
native long length () throws IOException;
native long getFilePointer () throws IOException;
native int read () throws IOException;
native int read (byte[] bytes, int offset, int len) throws IOException;
native int available () throws IOException;
// When collected, close.
protected void finalize () throws IOException
{
if (valid ())
close ();
}
// Attach to an already-opened file. This is not private because we
// need access to it from other packages, for instance java.net.
// Ordinarily that wouldn't work, either, but in our case we know
// the access comes from C++, where "package private" is translated
// into "public". Eww.
FileDescriptor (int desc)
{
fd = desc;
}
// System's notion of file descriptor.
private int fd;
}

View file

@ -0,0 +1,96 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 28, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class FileInputStream extends InputStream
{
/* Contains the file descriptor for referencing the actual file. */
private FileDescriptor fd;
public FileInputStream(String name) throws FileNotFoundException, IOException
{
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkRead(name);
fd = new FileDescriptor(name, FileDescriptor.READ);
}
public FileInputStream(File file) throws FileNotFoundException, IOException
{
this(file.getPath());
}
public FileInputStream(FileDescriptor fdObj)
{
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkRead(fdObj);
fd = fdObj;
}
public int available() throws IOException
{
return fd.available();
}
public void close() throws IOException
{
if (fd == null)
return;
fd.close();
fd = null;
}
protected void finalize() throws IOException
{
if (fd != null)
fd.finalize();
}
public final FileDescriptor getFD() throws IOException
{
if (!fd.valid())
throw new IOException();
return fd;
}
public int read() throws IOException
{
return fd.read();
}
public int read(byte[] b) throws IOException
{
return fd.read(b, 0, b.length);
}
public int read(byte[] b, int off, int len) throws IOException
{
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
return fd.read(b, off, len);
}
public long skip(long n) throws IOException
{
return fd.seek(n, FileDescriptor.CUR);
}
}

View file

@ -0,0 +1,34 @@
// FileNotFoundException.java
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to 1.1.
*/
public class FileNotFoundException extends IOException
{
public FileNotFoundException ()
{
super ();
}
public FileNotFoundException (String s)
{
super (s);
}
}

View file

@ -0,0 +1,93 @@
// FileOutputStream.java - Write bytes to a file.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1.
*/
public class FileOutputStream extends OutputStream
{
public FileOutputStream (String path, boolean append)
throws SecurityException, IOException
{
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkWrite(path);
fd = new FileDescriptor (path, (append
? FileDescriptor.APPEND
: FileDescriptor.WRITE));
}
public FileOutputStream (String path) throws SecurityException, IOException
{
this (path, false);
}
public FileOutputStream (File file) throws SecurityException, IOException
{
this (file.getPath(), false);
}
public FileOutputStream (FileDescriptor fdObj) throws SecurityException
{
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkWrite(fdObj);
fd = fdObj;
}
protected void finalize () throws IOException
{
// We don't actually need this, but we include it because it is
// mentioned in the JCL.
}
public final FileDescriptor getFD () throws IOException
{
if (! fd.valid())
throw new IOException ();
return fd;
}
public void write (int b) throws IOException
{
fd.write (b);
}
public void write (byte[] b) throws IOException, NullPointerException
{
fd.write (b, 0, b.length);
}
public void write (byte[] b, int off, int len)
throws IOException, NullPointerException, IndexOutOfBoundsException
{
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException ();
fd.write (b, off, len);
}
public void close () throws IOException
{
if (fd.valid())
fd.close();
}
// Instance variables.
private FileDescriptor fd;
}

View file

@ -0,0 +1,35 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date April 22, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition.
* Status: Believed complete and correct.
*/
public class FileReader extends InputStreamReader
{
public FileReader(String filename) throws IOException
{
super(new FileInputStream(filename));
}
public FileReader(File file) throws IOException
{
super(new FileInputStream(file));
}
public FileReader(FileDescriptor fd)
{
super(new FileInputStream(fd));
}
}

View file

@ -0,0 +1,44 @@
// FileWriter.java - Character output to a file.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 25, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1.
*/
public class FileWriter extends OutputStreamWriter
{
public FileWriter (String fileName) throws IOException
{
super (new FileOutputStream (fileName));
}
public FileWriter (String fileName, boolean append) throws IOException
{
super (new FileOutputStream (fileName, append));
}
public FileWriter (File file) throws IOException
{
super (new FileOutputStream (file));
}
public FileWriter (FileDescriptor fd)
{
super (new FileOutputStream (fd));
}
}

View file

@ -0,0 +1,26 @@
// FilenameFilter.java - Compute subset of list of file names
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to 1.1.
*/
public interface FilenameFilter
{
public abstract boolean accept (File dir, String name);
}

View file

@ -0,0 +1,75 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 8, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class FilterInputStream extends InputStream
{
/* The input stream to be filtered. */
protected InputStream in;
protected FilterInputStream(InputStream in)
{
this.in = in;
}
public int available() throws IOException
{
return in.available();
}
public void close() throws IOException
{
in.close();
}
public synchronized void mark(int readlimit)
{
in.mark(readlimit);
}
public boolean markSupported()
{
return in.markSupported();
}
public int read() throws IOException
{
return in.read();
}
public int read(byte[] b) throws IOException
{
return read(b, 0, b.length);
}
public int read(byte[] b, int off, int len) throws IOException
{
return in.read(b, off, len);
}
public synchronized void reset() throws IOException
{
in.reset();
}
public long skip(long n) throws IOException
{
return in.skip(n);
}
}

View file

@ -0,0 +1,61 @@
// FilterOutputStream.java - A filtered stream
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1.
*/
public class FilterOutputStream extends OutputStream
{
public void close () throws IOException
{
flush ();
out.close();
}
public FilterOutputStream (OutputStream ox)
{
out = ox;
}
public void flush () throws IOException
{
out.flush();
}
public void write (int b) throws IOException
{
out.write(b);
}
public void write (byte[] b) throws IOException, NullPointerException
{
// Don't do checking here, per Java Lang Spec.
out.write (b);
}
public void write (byte[] b, int off, int len)
throws IOException, NullPointerException, IndexOutOfBoundsException
{
// Don't do checking here, per Java Lang Spec.
out.write(b, off, len);
}
// The output stream.
protected OutputStream out;
}

View file

@ -0,0 +1,72 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 15, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public abstract class FilterReader extends Reader
{
/* The input stream to be filtered. */
protected Reader in;
protected FilterReader(Reader in)
{
super(in.lock);
this.in = in;
}
public void close() throws IOException
{
in.close();
in = null;
}
public synchronized void mark(int readlimit) throws IOException
{
in.mark(readlimit);
}
public boolean markSupported()
{
return in.markSupported();
}
public int read() throws IOException
{
return in.read();
}
public int read(char[] b, int off, int len) throws IOException
{
return in.read(b, off, len);
}
public boolean ready() throws IOException
{
return in.ready();
}
public synchronized void reset() throws IOException
{
in.reset();
}
public long skip(long n) throws IOException
{
return in.skip(n);
}
}

View file

@ -0,0 +1,59 @@
// FilterWriter.java - Filtered character output stream.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 25, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1.
*/
public abstract class FilterWriter extends Writer
{
public void close () throws IOException
{
out.close();
}
protected FilterWriter (Writer ox)
{
// FIXME: should we really share locks like this?
super (ox);
out = ox;
}
public void flush () throws IOException
{
out.flush();
}
public void write (int oneChar) throws IOException
{
out.write(oneChar);
}
public void write (char[] buffer, int offset, int count) throws IOException
{
out.write(buffer, offset, count);
}
public void write (String str, int offset, int count) throws IOException
{
out.write(str, offset, count);
}
// Where our writes should go.
protected Writer out;
}

View file

@ -0,0 +1,34 @@
// IOException.java - Base class for I/O Exceptions
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to 1.1.
*/
public class IOException extends Exception
{
public IOException ()
{
super ();
}
public IOException (String s)
{
super (s);
}
}

View file

@ -0,0 +1,104 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 2, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public abstract class InputStream
{
public InputStream()
{
}
public int available() throws IOException
{
return 0;
}
public void close() throws IOException
{
// Do nothing
}
public void mark(int readlimit)
{
// Do nothing
}
public boolean markSupported()
{
return false;
}
public abstract int read() throws IOException;
public int read(byte[] b) throws IOException
{
return read(b, 0, b.length);
}
public int read(byte[] b, int off, int len) throws IOException
{
if (off < 0 || len < 0 || off + len > b.length)
throw new IndexOutOfBoundsException();
if (b.length == 0)
return 0;
int i, ch;
for (i = 0; i < len; ++i)
try
{
if ((ch = read()) < 0)
return i == 0 ? -1 : i; // EOF
b[off + i] = (byte) ch;
}
catch (IOException ex)
{
// Only reading the first byte should cause an IOException.
if (i == 0)
throw ex;
return i;
}
return i;
}
public void reset() throws IOException
{
throw new IOException("mark/reset not supported");
}
public long skip(long n) throws IOException
{
// Throw away n bytes by reading them into a temp byte[].
// Limit the temp array to 2Kb so we don't grab too much memory.
final int buflen = n > 2048 ? 2048 : (int) n;
byte[] tmpbuf = new byte[buflen];
final long origN = n;
while (n > 0L)
{
int numread = read(tmpbuf, 0, n > buflen ? buflen : (int) n);
if (numread <= 0)
break;
n -= numread;
}
return origN - n;
}
}

View file

@ -0,0 +1,151 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
import gnu.gcj.convert.*;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date April 22, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct, but only supports 8859_1.
*/
public class InputStreamReader extends Reader
{
BufferedInputStream in;
// Buffer of chars read from in and converted but not consumed.
char[] work;
// Next available character (in work buffer) to read.
int wpos;
// Last available character (in work buffer) to read.
int wcount;
BytesToUnicode converter;
public InputStreamReader(InputStream in)
{
this(in, BytesToUnicode.getDefaultDecoder());
}
public InputStreamReader(InputStream in, String enc)
throws UnsupportedEncodingException
{
this(in, BytesToUnicode.getDecoder(enc));
}
private InputStreamReader(InputStream in, BytesToUnicode decoder)
{
super(in);
this.in = in instanceof BufferedInputStream ? (BufferedInputStream) in
: new BufferedInputStream(in, 250);
converter = decoder;
converter.setInput(this.in.buf, 0, 0);
}
public void close() throws IOException
{
synchronized (lock)
{
if (in != null)
in.close();
in = null;
work = null;
wpos = wcount = 0;
}
}
public String getEncoding() { return converter.getName(); }
public boolean ready() throws IOException
{
synchronized (lock)
{
if (wpos < wcount)
return true;
if (work == null)
{
work = new char[100];
wpos = 0;
wcount = 0;
}
for (;;)
{
if (in.available() <= 0)
return false;
in.mark(1);
int b = in.read();
if (b < 0)
return true;
in.reset();
converter.setInput(in.buf, in.pos, in.count);
wpos = 0;
wcount = converter.read(work, 0, work.length);
in.skip(converter.inpos - in.pos);
if (wcount > 0)
return true;
}
}
}
public int read(char buf[], int offset, int length) throws IOException
{
synchronized (lock)
{
int wavail = wcount - wpos;
if (wavail > 0)
{
if (length > wavail)
length = wavail;
System.arraycopy(work, wpos, buf, offset, length);
wpos += length;
return length;
}
else
{
for (;;)
{
in.mark(1);
int b = in.read();
if (b < 0)
return -1;
in.reset();
converter.setInput(in.buf, in.pos, in.count);
int count = converter.read (buf, offset, length);
in.skip(converter.inpos - in.pos);
if (count > 0)
return count;
}
}
}
}
public int read() throws IOException
{
synchronized (lock)
{
int wavail = wcount - wpos;
if (wavail > 0)
return work[wpos++];
if (work == null)
{
work = new char[100];
wpos = 0;
wcount = 0;
}
int count = read(work, wpos, work.length-wpos);
if (count <= 0)
return -1;
wcount = wpos + count;
return work[wpos++];
}
}
}

View file

@ -0,0 +1,36 @@
// InterruptedIOException.java
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to 1.1.
*/
public class InterruptedIOException extends IOException
{
public InterruptedIOException ()
{
super ();
}
public InterruptedIOException (String s)
{
super (s);
}
public int bytesTransferred = 0;
}

View file

@ -0,0 +1,143 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date November 11, 1998.
* @deprecated
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct. Deprecated in JDK 1.1.
*/
public class LineNumberInputStream extends FilterInputStream
{
/* The current line number. */
private int lineNumber = 0;
/* The line number when the stream was marked. */
private int markLineNumber = 0;
/* Flag to indicate a '\r' was just read so that an immediately subsequent
* '\n' can be ignored. */
private boolean justReadReturnChar = false;
public LineNumberInputStream(InputStream in)
{
super(in);
}
public int available() throws IOException
{
// We can only guarantee half the characters that might be available
// without blocking because "\r\n" is treated as a single character.
return in.available() / 2;
}
public int getLineNumber()
{
return lineNumber;
}
public void mark(int readlimit)
{
in.mark(readlimit);
markLineNumber = lineNumber;
}
public int read() throws IOException
{
// Treat "\r\n" as a single character. A '\r' may have been read by
// a previous call to read so we keep an internal flag to avoid having
// to read ahead.
int ch = in.read();
if (ch == '\n')
if (justReadReturnChar)
{
ch = in.read();
justReadReturnChar = false;
}
else
lineNumber++;
else if (ch == '\r')
{
ch = '\n';
justReadReturnChar = true;
lineNumber++;
}
else
justReadReturnChar = false;
return ch;
}
public int read(byte[] b, int off, int len) throws IOException
{
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
// This case always succeeds.
if (len == 0)
return 0;
// The simplest, though not necessarily the most time efficient thing
// to do is simply call read(void) len times. Since this is a deprecated
// class, that should be ok.
final int origOff = off;
while (len-- > 0)
{
int ch = read();
if (ch < 0)
break;
b[off++] = (byte) ch;
}
// This is safe since we already know that some bytes were
// actually requested.
return off == origOff ? -1 : off - origOff;
}
public void reset() throws IOException
{
in.reset();
lineNumber = markLineNumber;
justReadReturnChar = false;
}
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
}
public long skip(long n) throws IOException
{
if (n <= 0)
return 0L;
final long origN = n;
do
{
int ch = read();
if (ch < 0)
break;
if (ch == '\n' || ch == '\r')
lineNumber++;
}
while (--n > 0);
return origN - n;
}
}

View file

@ -0,0 +1,245 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date April 22, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*
* This implementation has the feature that if '\r' is read, it
* does not look for a '\n', but immediately returns '\n'.
* On the next read(), if a '\n' is read, it is skipped.
* This has the advantage that we do not read (and hang) unnecessarily.
*
* This implementation is also minimal in the number of fields it uses.
*/
public class LineNumberReader extends BufferedReader
{
/** The current line number. */
int lineNumber;
public LineNumberReader(Reader in)
{
super(in, 8192);
}
public LineNumberReader(Reader in, int size)
{
super(in, size);
}
public int getLineNumber()
{
return lineNumber;
}
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
}
private static int countLines (char[] buffer, int off, int len)
{
int count = 0;
char prev = '\0';
for (int i = 0; i < len; i++)
{
char ch = buffer[i+off];
if ((ch == '\n' && prev != '\r') || ch == '\r')
count++;
prev = ch;
}
return count;
}
public void mark(int readLimit) throws IOException
{
synchronized (lock)
{
// This is basically the same as BufferedReader.mark.
// However, if the previous character was a '\r', we need to
// save that 'r', in case the next character is a '\n'.
if (pos + readLimit > limit)
{
int saveCR = (pos > 0 && buffer[pos-1] == '\r') ? 1 : 0;
char[] old_buffer = buffer;
if (readLimit > limit)
buffer = new char[saveCR + readLimit];
int copy_start = pos - saveCR;
limit -= copy_start;
System.arraycopy(old_buffer, copy_start, buffer, 0, limit);
pos = saveCR;
}
markPos = pos;
}
}
public void reset() throws IOException
{
synchronized (lock)
{
if (markPos < 0)
throw new IOException("mark never set or invalidated");
if (markPos > 0 && pos > markPos && buffer[markPos-1] == '\r'
&& buffer[markPos] == '\n')
lineNumber--;
lineNumber -= countLines(buffer, pos, markPos);
pos = markPos;
}
}
public int read() throws IOException
{
synchronized (lock)
{
skipRedundantLF();
if (pos >= limit)
{
if (markPos >= 0 && limit == buffer.length)
markPos = -1;
if (markPos <= 0)
pos = limit = 0;
int count = in.read(buffer, limit, buffer.length - limit);
if (count <= 0)
return -1;
limit += count;
}
char ch = buffer[pos++];
if (ch == '\r' || ch == '\n')
{
lineNumber++;
return '\n';
}
return (int) ch;
}
}
public int read(char[] buf, int offset, int count) throws IOException
{
if (count <= 0)
{
if (count < 0)
throw new IndexOutOfBoundsException();
return 0;
}
synchronized (lock)
{
int first = read();
if (first < 0)
return -1;
int start_offset = offset;
buf[offset++] = (char) first;
if (buffer[pos-1] == '\r' && pos < limit && buffer[pos] == '\n')
pos++;
count--;
while (count-- > 0 && pos < limit)
{
char ch = buffer[pos++];
if (ch == '\r')
{
lineNumber++;
ch = '\n';
if (pos < limit && buffer[pos] == '\n')
pos++;
}
else if (ch == '\n')
lineNumber++;
buf[offset++] = ch;
}
return offset - start_offset;
}
}
private void skipRedundantLF() throws IOException
{
if (pos > 0 && buffer[pos-1] == '\r')
{
if (pos < limit)
{ // fast case
if (buffer[pos] == '\n')
pos++;
}
else
{ // use read() to deal with the general case.
// Set pos and limit to zero to avoid infinite recursion in read.
// May need to invalidate markPos if we've exceeded the buffer.
if (pos >= buffer.length)
markPos = -1;
pos = limit = 0;
int ch = read();
if (ch >= 0 && ch != '\n')
pos--;
}
}
}
public String readLine() throws IOException
{
// BufferedReader.readLine already does this. Shouldn't need to keep
// track of newlines (since the read method deals with this for us).
// But if the buffer is large, we may not call the read method at all
// and super.readLine can't increment lineNumber itself.
// Though it may seem kludgy, the safest thing to do is to save off
// lineNumber and increment it explicitly when we're done (iff we
// ended with a '\n' or '\r' as opposed to EOF).
//
// Also, we need to undo the special casing done by BufferedReader.readLine
// when a '\r' is the last char in the buffer. That situation is marked
// by 'pos > limit'.
int tmpLineNumber = lineNumber;
skipRedundantLF();
String str = super.readLine();
if (pos > limit)
--pos;
int ch;
if (pos > 0 && ((ch = buffer[pos - 1]) == '\n' || ch == '\r'))
lineNumber = tmpLineNumber + 1;
return str;
}
public long skip(long count) throws IOException
{
if (count <= 0)
return 0;
long to_do = count;
do
{
int ch = read();
if (ch < 0)
break;
to_do--;
if (ch == '\n' || ch == '\r')
lineNumber++;
else
{
long fence = pos + to_do;
if (limit < fence)
fence = limit;
int end = pos;
for (; end < fence; end++)
{
char endch = buffer[end];
if (endch == '\n' || endch == '\r')
break;
}
to_do -= end - pos;
pos = end;
}
}
while (to_do > 0);
return count - to_do;
}
}

View file

@ -0,0 +1,48 @@
// OutputStream.java - Send output bytes to output sink.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1.
*/
public abstract class OutputStream
{
public abstract void write (int b) throws IOException;
public void write (byte[] b) throws IOException, NullPointerException
{
write (b, 0, b.length);
}
public void write (byte[] b, int off, int len)
throws IOException, NullPointerException, IndexOutOfBoundsException
{
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException ();
for (int i = 0; i < len; ++i)
write (b[off + i]);
}
public void flush () throws IOException
{
}
public void close () throws IOException
{
}
}

View file

@ -0,0 +1,155 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
import gnu.gcj.convert.UnicodeToBytes;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date April 17, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct, but only supports 8859_1.
*/
public class OutputStreamWriter extends Writer
{
BufferedOutputStream out;
UnicodeToBytes converter;
/* Temporary buffer. */
private char[] work;
private int wcount;
public String getEncoding() { return converter.getName(); }
private OutputStreamWriter(OutputStream out, UnicodeToBytes encoder)
{
super(out);
this.out = out instanceof BufferedOutputStream ? (BufferedOutputStream) out
: new BufferedOutputStream(out, 2048);
this.converter = encoder;
}
public OutputStreamWriter(OutputStream out, String enc)
throws UnsupportedEncodingException
{
this(out, UnicodeToBytes.getEncoder(enc));
}
public OutputStreamWriter(OutputStream out)
{
this(out, UnicodeToBytes.getDefaultEncoder());
}
public void close() throws IOException
{
synchronized (lock)
{
flush();
if (out != null)
{
out.close();
out = null;
}
work = null;
}
}
public void flush() throws IOException
{
synchronized (lock)
{
if (wcount > 0)
{
writeChars(work, 0, wcount);
wcount = 0;
}
out.flush();
}
}
public void write(char[] buf, int offset, int count)
throws IOException
{
synchronized (lock)
{
if (wcount > 0)
{
writeChars(work, 0, wcount);
wcount = 0;
}
writeChars(buf, offset, count);
}
}
private void writeChars(char[] buf, int offset, int count)
throws IOException
{
while (count > 0)
{
if (out.count != 0)
{
out.flush();
if (out.count != 0)
throw new IOException("unable to flush output byte buffer");
}
converter.setOutput(out.buf, out.count);
int converted = converter.write(buf, offset, count);
offset += converted;
count -= converted;
out.count = converter.count;
}
}
public void write(String str, int offset, int count)
throws IOException
{
synchronized (lock)
{
if (work == null)
work = new char[100];
int wlength = work.length;
while (count > 0)
{
int size = count;
if (wcount + size > wlength)
{
if (2*wcount > wlength)
{
writeChars(work, 0, wcount);
wcount = 0;
}
if (wcount + size > wlength)
size = wlength - wcount;
}
str.getChars(offset, offset+size, work, wcount);
offset += size;
count -= size;
wcount += size;
}
}
}
public void write(int ch) throws IOException
{
synchronized (lock)
{
if (work == null)
work = new char[100];
if (wcount >= work.length)
{
writeChars(work, 0, wcount);
wcount = 0;
}
work[wcount++] = (char) ch;
}
}
}

View file

@ -0,0 +1,242 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 29, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class PipedInputStream extends InputStream
{
/* The size of the pipe's circular input buffer. */
protected static final int PIPE_SIZE = 1024;
/* The circular buffer into which incoming data is placed. */
protected byte[] buffer;
/* The index in the buffer at which the next byte of data will be stored. */
protected int in = -1;
/* The index in the buffer at which the next byte of data will be read. */
protected int out = 0;
/* The output stream this is connected to; used to check for errors. */
private PipedOutputStream po = null;
/* Flag to indicate that the output stream was closed. */
private boolean outClosed = false;
public PipedInputStream(PipedOutputStream src) throws IOException
{
buffer = new byte[PIPE_SIZE];
connect(src);
}
public PipedInputStream()
{
buffer = new byte[PIPE_SIZE];
}
public synchronized int available() throws IOException
{
if (in < 0)
return 0;
if (in > out)
return in - out;
// Buffer has wrapped around.
return buffer.length - out + in;
}
public void close() throws IOException
{
buffer = null;
po = null;
// Mark as empty for available method.
in = -1;
}
public void connect(PipedOutputStream src) throws IOException
{
if (buffer == null)
throw new IOException("pipe closed");
if (po != null)
if (po == src)
return;
else
throw new IOException("pipe already connected");
po = src;
try
{
src.connect(this);
}
catch (IOException ex)
{
po = null;
throw ex;
}
}
public synchronized int read() throws IOException
{
// TBD: Spec says to throw IOException if thread writing to output stream
// died. What does this really mean? Theoretically, multiple threads
// could be writing to this object. Do you track the first, last, or
// all of them?
if (po == null)
if (buffer == null)
throw new IOException("pipe closed");
else
throw new IOException("pipe unconnected");
// Block until there's something to read or output stream was closed.
while (in < 0)
try
{
if (outClosed)
return -1;
wait();
}
catch (InterruptedException ex)
{
throw new InterruptedIOException();
}
// Let other threads know there's room to write now.
notifyAll();
int retval = buffer[out++] & 0xFF;
// Wrap back around if at end of the array.
if (out >= buffer.length)
out = 0;
// When the last byte available is read, mark the buffer as empty.
if (out == in)
{
in = -1;
out = 0;
}
return retval;
}
public synchronized int read(byte[] b, int off, int len) throws IOException
{
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
// TBD: Spec says to throw IOException if thread writing to output stream
// died. What does this really mean? Theoretically, multiple threads
// could be writing to this object. Do you track the first, last, or
// all of them?
if (po == null)
if (buffer == null)
throw new IOException("pipe closed");
else
throw new IOException("pipe unconnected");
// Block until there's something to read or output stream was closed.
while (in < 0)
try
{
if (outClosed)
return -1;
wait();
}
catch (InterruptedException ex)
{
throw new InterruptedIOException();
}
// Let other threads know there's room to write now.
notifyAll();
int numRead;
len = Math.min(len, available());
if (in <= out && len >= (numRead = buffer.length - out))
{
// Buffer has wrapped around; need to copy in 2 steps.
// Copy to the end of the buffer first; second copy may be of zero
// bytes but that is ok. Doing it that way saves having to check
// later if 'out' has grown to buffer.length.
System.arraycopy(buffer, out, b, off, numRead);
len -= numRead;
off += numRead;
out = 0;
}
else
numRead = 0;
System.arraycopy(buffer, out, b, off, len);
numRead += len;
out += len;
// When the last byte available is read, mark the buffer as empty.
if (out == in)
{
in = -1;
out = 0;
}
return numRead;
}
protected synchronized void receive(int b) throws IOException
{
if (buffer == null)
throw new IOException("pipe closed");
// TBD: Spec says to throw IOException if thread reading from input stream
// died. What does this really mean? Theoretically, multiple threads
// could be reading to this object (why else would 'read' be synchronized?).
// Do you track the first, last, or all of them?
if (b < 0)
{
outClosed = true;
notifyAll(); // In case someone was blocked in a read.
return;
}
// Block until there's room in the pipe.
while (in == out)
try
{
wait();
}
catch (InterruptedException ex)
{
throw new InterruptedIOException();
}
// Check if buffer is empty.
if (in < 0)
in = 0;
buffer[in++] = (byte) b;
// Wrap back around if at end of the array.
if (in >= buffer.length)
in = 0;
// Let other threads know there's something to read when this returns.
notifyAll();
}
}

View file

@ -0,0 +1,94 @@
// PipedOutputStream.java - Write bytes to a pipe.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Believed complete and correct.
*/
public class PipedOutputStream extends OutputStream
{
public void close () throws IOException
{
closed = true;
// Notify PipedInputStream that there is no more data to be had.
destination.receive(-1);
}
public void connect (PipedInputStream dest) throws IOException
{
if (closed)
throw new IOException("pipe closed");
if (destination != null)
if (destination == dest)
return;
else
throw new IOException("pipe already connected");
destination = dest;
try
{
dest.connect(this);
}
catch (IOException ex)
{
destination = null;
throw ex;
}
}
public synchronized void flush () throws IOException
{
// There doesn't seem to be anything to do here.
// TBD: Should this maybe do a notifyAll as a way for the user
// to wake up the input stream to check for bytes to read? Shouldn't
// be necessary but if there aren't any bytes, other threads will just
// go blocak again anyway so it wouldn't hurt.
}
public PipedOutputStream ()
{
closed = false;
}
public PipedOutputStream (PipedInputStream dest) throws IOException
{
closed = false;
connect (dest);
}
public void write (int oneByte) throws IOException
{
if (closed)
throw new IOException ();
destination.receive(oneByte);
}
// This is mentioned in the JCL book, but we don't really need it.
// If there were a corresponding receive() method on
// PipedInputStream then we could get better performance using
// this.
// public void write (byte[] buffer, int offset, int count)
// throws IOException;
// Instance variables.
private PipedInputStream destination;
private boolean closed;
}

View file

@ -0,0 +1,210 @@
// PipedReader.java - Piped character stream.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 25, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to 1.1.
*/
public class PipedReader extends Reader
{
public void close () throws IOException
{
closed = true;
}
public void connect (PipedWriter src) throws IOException
{
if (closed)
throw new IOException ("already closed");
if (writer != null)
{
if (writer == src)
return;
throw new IOException ("already connected");
}
try
{
writer = src;
writer.connect(this);
}
catch (IOException e)
{
writer = null;
throw e;
}
}
public PipedReader ()
{
super ();
writer = null;
closed = false;
in = -1;
out = 0;
pipeBuffer = new char[1024];
}
public PipedReader (PipedWriter src) throws IOException
{
super ();
closed = false;
in = -1;
out = 0;
pipeBuffer = new char[1024];
connect (src);
}
public int read (char buf[], int offset, int count) throws IOException
{
if (closed)
throw new IOException ("closed");
if (count < 0)
throw new ArrayIndexOutOfBoundsException ();
int toCopy = count;
synchronized (lock)
{
while (toCopy > 0)
{
// Wait for data in the pipe. If the writer is closed and
// no data has been copied into the output buffer, return
// the magic EOF number.
while (in == -1)
{
if (writer.isClosed())
{
if (toCopy < count)
return count - toCopy;
return -1;
}
// Note that JCL doesn't say this is the right thing
// to do. Still, it feels right, and we must deal
// with an interrupt somehow.
try
{
lock.wait();
}
catch (InterruptedException e)
{
InterruptedIOException io
= new InterruptedIOException (e.getMessage());
io.bytesTransferred = count - toCopy;
throw io;
}
}
// Now copy some data from pipe into user buffer.
int len;
if (in < out)
len = pipeBuffer.length - out;
else
len = in - out;
len = len > toCopy ? toCopy : len;
System.arraycopy(pipeBuffer, out, buf, offset, len);
out += len;
if (out == pipeBuffer.length)
out = 0;
toCopy -= len;
offset += len;
// If we've read all the data, then reset so that we know
// there is nothing left to be read.
if (in == out)
in = -1;
// Tell anybody waiting for space in the buffer.
lock.notifyAll();
}
}
return count;
}
void receive (char buf[], int offset, int count) throws IOException
{
if (count < 0)
throw new ArrayIndexOutOfBoundsException ();
int original = count;
synchronized (lock)
{
while (count > 0)
{
// Wait until there is some space in the buffer.
while (in == out)
{
try
{
lock.wait();
}
catch (InterruptedException e)
{
// Turn interrupts into IO interrupts.
InterruptedIOException io
= new InterruptedIOException (e.getMessage());
io.bytesTransferred = original - count;
throw io;
}
}
// Compute destination in the pipe.
int base, len;
if (in == -1)
{
base = 0;
len = pipeBuffer.length;
}
else if (in < out)
{
base = in;
len = out - in;
}
else
{
base = in;
len = pipeBuffer.length - in;
}
int copyLen = len > count ? count : len;
// Copy data and update local state.
System.arraycopy(buf, offset, pipeBuffer, base, copyLen);
in = base + copyLen;
if (in == pipeBuffer.length)
in = 0;
count -= copyLen;
offset += copyLen;
// Tell anybody waiting for data.
lock.notifyAll();
}
}
}
boolean isClosed ()
{
return closed;
}
// The associated writer.
private PipedWriter writer;
// True if this reader has been closed.
boolean closed;
// Index of next character to overwrite when receive() is called.
// If -1, then that means the buffer is empty.
private int in;
// Index of next character to return from read().
private int out;
// The pipe buffer itself.
private char[] pipeBuffer;
}

View file

@ -0,0 +1,88 @@
// PipedWriter.java - Piped character stream.
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 25, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to 1.1.
*/
public class PipedWriter extends Writer
{
public void close () throws IOException
{
closed = true;
}
public void connect (PipedReader sink) throws IOException
{
if (closed)
throw new IOException ("already closed");
if (reader != null)
{
if (reader == sink)
return;
throw new IOException ("already connected");
}
try
{
reader = sink;
reader.connect(this);
}
catch (IOException e)
{
reader = null;
throw e;
}
}
public void flush () throws IOException
{
// We'll throw an exception if we're closed, but there's nothing
// else to do here.
if (closed)
throw new IOException ("closed");
}
public PipedWriter ()
{
super ();
closed = false;
}
public PipedWriter (PipedReader sink) throws IOException
{
super ();
closed = false;
connect (sink);
}
public void write (char buffer[], int offset, int count) throws IOException
{
if (closed)
throw new IOException ("closed");
reader.receive(buffer, offset, count);
}
boolean isClosed ()
{
return closed;
}
// The associated reader.
private PipedReader reader;
private boolean closed;
}

View file

@ -0,0 +1,236 @@
// PrintStream.java - Print string representations
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Not finished.
*/
public class PrintStream extends FilterOutputStream
{
public boolean checkError ()
{
return error;
}
public void close ()
{
try
{
out.close();
}
catch (IOException e)
{
setError ();
}
}
public void flush ()
{
try
{
out.flush();
}
catch (IOException e)
{
setError ();
}
}
private final void print (String str, boolean check_term)
{
try
{
write(str.getBytes());
if (check_term
&& auto_flush
&& str.indexOf(line_separator) != -1)
flush ();
}
catch (IOException e)
{
setError ();
}
}
public void print (boolean bool)
{
print (String.valueOf(bool), false);
}
public void print (int inum)
{
print (String.valueOf(inum), false);
}
public void print (long lnum)
{
print (String.valueOf(lnum), false);
}
public void print (float fnum)
{
print (String.valueOf(fnum), false);
}
public void print (double dnum)
{
print (String.valueOf(dnum), false);
}
public void print (Object obj)
{
print (String.valueOf(obj), false);
}
public void print (String str)
{
print (str, true);
}
public void print (char ch)
{
print (String.valueOf(ch), true);
}
public void print (char[] charArray)
{
print (String.valueOf(charArray), true);
}
public void println ()
{
print (line_separator, false);
if (auto_flush)
flush ();
}
public void println (boolean bool)
{
print (String.valueOf(bool), false);
println ();
}
public void println (int inum)
{
print (String.valueOf(inum), false);
println ();
}
public void println (long lnum)
{
print (String.valueOf(lnum), false);
println ();
}
public void println (float fnum)
{
print (String.valueOf(fnum), false);
println ();
}
public void println (double dnum)
{
print (String.valueOf(dnum), false);
println ();
}
public void println (Object obj)
{
print (String.valueOf(obj), false);
println ();
}
public void println (String str)
{
print (str, false);
println ();
}
public void println (char ch)
{
print (String.valueOf(ch), false);
println ();
}
public void println (char[] charArray)
{
print (String.valueOf(charArray), false);
println ();
}
public PrintStream (OutputStream out)
{
super (out);
error = false;
auto_flush = false;
}
public PrintStream (OutputStream out, boolean af)
{
super (out);
error = false;
auto_flush = af;
}
protected void setError ()
{
error = true;
}
public void write (int oneByte)
{
try
{
out.write(oneByte);
// JCL says to do this. I think it is wrong. FIXME.
if (auto_flush && oneByte == '\n')
out.flush();
}
catch (IOException e)
{
setError ();
}
}
public void write (byte[] buffer, int offset, int count)
{
try
{
out.write(buffer, offset, count);
// FIXME: JCL says to flush. But elsewhere the JCL says to
// use write to write the stringified form of an object, and
// only to flush if that string contains the line separator.
// How to resolve the contradiction?
if (auto_flush)
out.flush();
}
catch (IOException e)
{
setError ();
}
}
// True if error occurred.
private boolean error;
// True if auto-flush.
private boolean auto_flush;
// Line separator string.
private static final String line_separator
= System.getProperty("line.separator");
}

View file

@ -0,0 +1,286 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date April 17, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
* However, should use native methods for conversion.
*/
public class PrintWriter extends Writer
{
private boolean autoflush;
private boolean error;
Writer out;
public PrintWriter(Writer wr)
{
super(wr);
this.out = wr;
}
public PrintWriter(Writer wr, boolean autoflush)
{
super(wr);
this.out = wr;
this.autoflush = autoflush;
}
public PrintWriter(OutputStream out)
{
super();
this.out = new OutputStreamWriter(out);
this.lock = this.out;
}
public PrintWriter(OutputStream out, boolean autoflush)
{
this(out);
this.autoflush = autoflush;
}
protected void setError() { error = true; }
public boolean checkError()
{
flush();
return error;
}
public void flush()
{
try
{
out.flush();
}
catch (IOException ex)
{
error = true;
}
}
public void close()
{
try
{
out.close();
}
catch (IOException ex)
{
error = true;
}
}
public void print(String str)
{
try
{
out.write(str == null ? "null" : str);
}
catch (IOException ex)
{
error = true;
}
}
public void print(char ch)
{
write((int) ch);
}
public void print(char[] charArray)
{
write(charArray, 0, charArray.length);
}
public void print(boolean bool)
{
print(bool ? "true" : "false");
}
public void print(int inum)
{
print(Integer.toString(inum));
}
public void print(long lnum)
{
print(Long.toString(lnum));
}
public void print(float fnum)
{
print(Float.toString(fnum));
}
public void print(double dnum)
{
print(Double.toString(dnum));
}
public void print(Object obj)
{
print(obj == null ? "null" : obj.toString());
}
private static final char[] line_separator
= System.getProperty("line.separator").toCharArray();
public void println()
{
synchronized (lock)
{
printlnUnsynchronized();
}
}
private void printlnUnsynchronized()
{
try
{
write(line_separator, 0, line_separator.length);
if (autoflush)
out.flush();
}
catch (IOException ex)
{
error = true;
}
}
public void println(boolean bool)
{
synchronized (lock)
{
print(bool);
printlnUnsynchronized();
}
}
public void println(int inum)
{
synchronized (lock)
{
print(inum);
printlnUnsynchronized();
}
}
public void println(long lnum)
{
synchronized (lock)
{
print(lnum);
printlnUnsynchronized();
}
}
public void println(float fnum)
{
synchronized (lock)
{
print(fnum);
printlnUnsynchronized();
}
}
public void println(double dnum)
{
synchronized (lock)
{
print(dnum);
printlnUnsynchronized();
}
}
public void println(Object obj)
{
synchronized (lock)
{
print(obj);
printlnUnsynchronized();
}
}
public void println(String str)
{
synchronized (lock)
{
print(str);
printlnUnsynchronized();
}
}
public void println(char ch)
{
synchronized (lock)
{
print(ch);
printlnUnsynchronized();
}
}
public void println(char[] charArray)
{
synchronized (lock)
{
print(charArray);
printlnUnsynchronized();
}
}
public void write(int ch)
{
try
{
out.write(ch);
}
catch (IOException ex)
{
error = true;
}
}
public void write(char[] charArray, int offset, int count)
{
try
{
out.write(charArray, offset, count);
}
catch (IOException ex)
{
error = true;
}
}
public void write(String str, int offset, int count)
{
try
{
out.write(str, offset, count);
}
catch (IOException ex)
{
error = true;
}
}
public void write(char[] charArray)
{
write(charArray, 0, charArray.length);
}
public void write(String str)
{
write(str, 0, str.length());
}
}

View file

@ -0,0 +1,124 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 15, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class PushbackInputStream extends FilterInputStream
{
/* Internal buffer array for data. */
protected byte[] buf;
/* The current position in the buffer. */
protected int pos;
public PushbackInputStream(InputStream in)
{
this(in, 1);
}
public PushbackInputStream(InputStream in, int size)
{
super(in);
if (size < 0)
throw new IllegalArgumentException();
buf = new byte[size];
pos = buf.length;
}
public int available() throws IOException
{
return pos + super.available();
}
public void close() throws IOException
{
buf = null;
super.close();
}
public boolean markSupported()
{
return false;
}
public int read() throws IOException
{
if (pos < buf.length)
return ((int) buf[pos++]) & 0xFF;
return super.read();
}
public int read(byte[] b, int off, int len) throws IOException
{
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
int numBytes = Math.min(buf.length - pos, len);
for (int i = 0; i < numBytes; i++)
b[off++] = buf[pos++];
// `off' was just incremented to include `numBytes', so we can
// just pass ithere.
return numBytes + super.read(b, off, len - numBytes);
}
public void unread(int b) throws IOException
{
if (pos <= 0)
throw new IOException();
buf[--pos] = (byte) b;
}
public void unread(byte[] b) throws IOException
{
unread(b, 0, b.length);
}
public void unread(byte[] b, int off, int len) throws IOException
{
if (pos < len)
throw new IOException();
// Note the order that these bytes are being added is the opposite
// of what would be done if they were added to the buffer one at a time.
// See the Java Class Libraries book p. 1390.
System.arraycopy(b, off, buf, pos - len, len);
// Don't put this into the arraycopy above, an exception might be thrown
// and in that case we don't want to modify pos.
pos -= len;
}
// JDK1.2
public long skip(long n) throws IOException
{
final long origN = n;
if (n > 0L)
{
int numread = (int) Math.min((long) (buf.length - pos), n);
pos += numread;
n -= numread;
n -= super.skip(n);
}
return origN - n;
}
}

View file

@ -0,0 +1,136 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date October 16, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class PushbackReader extends FilterReader
{
/* Internal buffer array for data. */
private char[] buf;
/* The current position in the buffer. */
private int pos;
public PushbackReader(Reader in)
{
this(in, 1);
}
public PushbackReader(Reader in, int size)
{
super(in);
if (size < 0)
throw new IllegalArgumentException();
buf = new char[size];
pos = buf.length;
}
public void close() throws IOException
{
synchronized (lock)
{
buf = null;
super.close();
}
}
public boolean markSupported()
{
return false;
}
public int read() throws IOException
{
synchronized (lock)
{
if (buf == null)
throw new IOException();
if (pos < buf.length)
return ((int) buf[pos++]) & 0xFFFF;
return super.read();
}
}
public int read(char[] b, int off, int len) throws IOException
{
synchronized (lock)
{
if (buf == null)
throw new IOException();
if (off < 0 || len < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
int numBytes = Math.min(buf.length - pos, len);
for (int i = 0; i < numBytes; i++)
b[off++] = buf[pos++];
return numBytes + super.read(b, off, len - numBytes);
}
}
public boolean ready() throws IOException
{
synchronized (lock)
{
if (buf == null)
throw new IOException();
if (buf.length - pos > 0)
return true;
return super.ready();
}
}
public void unread(int b) throws IOException
{
synchronized (lock)
{
if (buf == null || pos <= 0)
throw new IOException();
buf[--pos] = (char) b;
}
}
public void unread(char[] b) throws IOException
{
unread(b, 0, b.length);
}
public void unread(char[] b, int off, int len) throws IOException
{
synchronized (lock)
{
if (buf == null || pos < len)
throw new IOException();
// Note the order that these chars are being added is the opposite
// of what would be done if they were added to the buffer one at a time.
// See the Java Class Libraries book p. 1397.
System.arraycopy(b, off, buf, pos - len, len);
// Don't put this into the arraycopy above, an exception might be thrown
// and in that case we don't want to modify pos.
pos -= len;
}
}
}

View file

@ -0,0 +1,249 @@
// RandomAccessFile.java
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 25, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: not finished
*/
public class RandomAccessFile implements DataOutput, DataInput
{
public void close () throws IOException
{
fd.close();
}
public final FileDescriptor getFD () throws IOException
{
if (! fd.valid())
throw new IOException ();
return fd;
}
public long getFilePointer () throws IOException
{
return fd.getFilePointer();
}
public long length () throws IOException
{
return fd.length();
}
public RandomAccessFile (String fileName, String mode) throws IOException
{
int fdmode;
if (mode.compareTo ("r") == 0)
fdmode = FileDescriptor.READ;
else if (mode.compareTo ("rw") == 0)
fdmode = FileDescriptor.READ | FileDescriptor.WRITE;
else
throw new IllegalArgumentException ("invalid mode: " + mode);
SecurityManager s = System.getSecurityManager();
if (s != null)
{
s.checkRead(fileName);
if ((fdmode & FileDescriptor.WRITE) != 0)
s.checkWrite(fileName);
}
fd = new FileDescriptor (fileName, fdmode);
// FIXME: read-only mode.
out = new DataOutputStream (new FileOutputStream (fd));
in = new DataInputStream (new FileInputStream (fd));
}
public RandomAccessFile (File file, String mode) throws IOException
{
this (file.getPath(), mode);
}
public int read () throws IOException
{
return in.read();
}
public int read (byte[] buffer) throws IOException
{
return in.read(buffer);
}
public int read (byte[] buffer, int offset, int count) throws IOException
{
return in.read(buffer, offset, count);
}
public final boolean readBoolean () throws IOException
{
return in.readBoolean();
}
public final byte readByte () throws IOException
{
return in.readByte();
}
public final char readChar () throws IOException
{
return in.readChar();
}
public final double readDouble () throws IOException
{
return in.readDouble();
}
public final float readFloat () throws IOException
{
return in.readFloat();
}
public final void readFully (byte[] buffer) throws IOException
{
// FIXME.
}
public final void readFully (byte[] buffer, int offset, int count)
throws IOException
{
// FIXME.
}
public final int readInt () throws IOException
{
return in.readInt();
}
public final String readLine () throws IOException
{
// FIXME?
return in.readLine();
}
public final long readLong () throws IOException
{
return in.readLong();
}
public final short readShort () throws IOException
{
return in.readShort();
}
public final int readUnsignedByte () throws IOException
{
return in.readUnsignedByte();
}
public final int readUnsignedShort () throws IOException
{
return in.readUnsignedShort();
}
public final String readUTF () throws IOException
{
return in.readUTF();
}
public void seek (long pos) throws IOException
{
fd.seek(pos, FileDescriptor.SET);
}
public int skipBytes (int count) throws IOException
{
return fd.seek(count, FileDescriptor.CUR);
}
public void write (int oneByte) throws IOException
{
out.write(oneByte);
}
public void write (byte[] buffer) throws IOException
{
out.write(buffer);
}
public void write (byte[] buffer, int offset, int count) throws IOException
{
out.write(buffer, offset, count);
}
public final void writeBoolean (boolean val) throws IOException
{
out.writeBoolean(val);
}
public final void writeByte (int v) throws IOException
{
out.writeByte(v);
}
public final void writeShort (int v) throws IOException
{
out.writeShort(v);
}
public final void writeChar (int v) throws IOException
{
out.writeChar(v);
}
public final void writeInt (int v) throws IOException
{
out.writeInt(v);
}
public final void writeLong (long v) throws IOException
{
out.writeLong(v);
}
public final void writeFloat (float v) throws IOException
{
out.writeFloat(v);
}
public final void writeDouble (double v) throws IOException
{
out.writeDouble(v);
}
public final void writeBytes (String s) throws IOException
{
out.writeBytes(s);
}
public final void writeChars (String s) throws IOException
{
out.writeChars(s);
}
public final void writeUTF (String s) throws IOException
{
out.writeUTF(s);
}
// The underlying file.
private FileDescriptor fd;
// The corresponding input and output streams.
private DataOutputStream out;
private DataInputStream in;
}

View file

@ -0,0 +1,87 @@
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date April 21, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public abstract class Reader
{
protected Object lock;
protected Reader()
{
this.lock = this;
}
protected Reader(Object lock)
{
this.lock = lock;
}
abstract public int read(char buf[], int offset, int count)
throws IOException;
public int read(char buf[]) throws IOException
{
return read(buf, 0, buf.length);
}
public int read() throws IOException
{
char[] buf = new char[1];
int count = read(buf, 0, 1);
return count > 0 ? buf[0] : -1;
}
abstract public void close() throws IOException;
public boolean markSupported()
{
return false;
}
public void mark(int readLimit) throws IOException
{
throw new IOException("mark not supported");
}
public void reset() throws IOException
{
throw new IOException("reset not supported");
}
public boolean ready() throws IOException
{
return false;
}
public long skip(long count) throws IOException
{
if (count <= 0)
return 0;
int bsize = count > 1024 ? 1024 : (int) count;
char[] buffer = new char[bsize];
long todo = count;
while (todo > 0)
{
int skipped = read(buffer, 0, bsize > todo ? (int) todo : bsize);
if (skipped <= 0)
break;
todo -= skipped;
}
return count - todo;
}
}

Some files were not shown because too many files have changed in this diff Show more