summaryrefslogtreecommitdiff
path: root/libjava/java
diff options
context:
space:
mode:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>1999-04-07 14:42:40 +0000
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>1999-04-07 14:42:40 +0000
commit2c60951ba0efef23e2b765964b5dc0f1f49438a9 (patch)
treed96801a16fdf03a5682ef98730fe333a46eef944 /libjava/java
parent1135eed2207f8f82c589e42ce113a1c2f0310778 (diff)
downloadgcc-2c60951ba0efef23e2b765964b5dc0f1f49438a9.tar.gz
Initial revision
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@26263 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/java')
-rw-r--r--libjava/java/io/BufferedInputStream.java168
-rw-r--r--libjava/java/io/BufferedOutputStream.java76
-rw-r--r--libjava/java/io/BufferedReader.java373
-rw-r--r--libjava/java/io/BufferedWriter.java129
-rw-r--r--libjava/java/io/ByteArrayInputStream.java113
-rw-r--r--libjava/java/io/ByteArrayOutputStream.java108
-rw-r--r--libjava/java/io/CharArrayReader.java152
-rw-r--r--libjava/java/io/CharArrayWriter.java122
-rw-r--r--libjava/java/io/CharConversionException.java34
-rw-r--r--libjava/java/io/DataInput.java41
-rw-r--r--libjava/java/io/DataInputStream.java249
-rw-r--r--libjava/java/io/DataOutput.java44
-rw-r--r--libjava/java/io/DataOutputStream.java165
-rw-r--r--libjava/java/io/EOFException.java34
-rw-r--r--libjava/java/io/File.java288
-rw-r--r--libjava/java/io/FileDescriptor.java87
-rw-r--r--libjava/java/io/FileInputStream.java96
-rw-r--r--libjava/java/io/FileNotFoundException.java34
-rw-r--r--libjava/java/io/FileOutputStream.java93
-rw-r--r--libjava/java/io/FileReader.java35
-rw-r--r--libjava/java/io/FileWriter.java44
-rw-r--r--libjava/java/io/FilenameFilter.java26
-rw-r--r--libjava/java/io/FilterInputStream.java75
-rw-r--r--libjava/java/io/FilterOutputStream.java61
-rw-r--r--libjava/java/io/FilterReader.java72
-rw-r--r--libjava/java/io/FilterWriter.java59
-rw-r--r--libjava/java/io/IOException.java34
-rw-r--r--libjava/java/io/InputStream.java104
-rw-r--r--libjava/java/io/InputStreamReader.java151
-rw-r--r--libjava/java/io/InterruptedIOException.java36
-rw-r--r--libjava/java/io/LineNumberInputStream.java143
-rw-r--r--libjava/java/io/LineNumberReader.java245
-rw-r--r--libjava/java/io/OutputStream.java48
-rw-r--r--libjava/java/io/OutputStreamWriter.java155
-rw-r--r--libjava/java/io/PipedInputStream.java242
-rw-r--r--libjava/java/io/PipedOutputStream.java94
-rw-r--r--libjava/java/io/PipedReader.java210
-rw-r--r--libjava/java/io/PipedWriter.java88
-rw-r--r--libjava/java/io/PrintStream.java236
-rw-r--r--libjava/java/io/PrintWriter.java286
-rw-r--r--libjava/java/io/PushbackInputStream.java124
-rw-r--r--libjava/java/io/PushbackReader.java136
-rw-r--r--libjava/java/io/RandomAccessFile.java249
-rw-r--r--libjava/java/io/Reader.java87
-rw-r--r--libjava/java/io/SequenceInputStream.java112
-rw-r--r--libjava/java/io/Serializable.java21
-rw-r--r--libjava/java/io/StreamTokenizer.java433
-rw-r--r--libjava/java/io/StringBufferInputStream.java83
-rw-r--r--libjava/java/io/StringReader.java139
-rw-r--r--libjava/java/io/StringWriter.java80
-rw-r--r--libjava/java/io/SyncFailedException.java34
-rw-r--r--libjava/java/io/UTFDataFormatException.java34
-rw-r--r--libjava/java/io/UnsupportedEncodingException.java32
-rw-r--r--libjava/java/io/Writer.java67
-rw-r--r--libjava/java/io/natFile.cc273
-rw-r--r--libjava/java/io/natFileDescriptorEcos.cc132
-rw-r--r--libjava/java/io/natFileDescriptorPosix.cc264
-rw-r--r--libjava/java/lang/AbstractMethodError.java34
-rw-r--r--libjava/java/lang/ArithmeticException.java32
-rw-r--r--libjava/java/lang/ArrayIndexOutOfBoundsException.java37
-rw-r--r--libjava/java/lang/ArrayStoreException.java32
-rw-r--r--libjava/java/lang/Boolean.java95
-rw-r--r--libjava/java/lang/Byte.java144
-rw-r--r--libjava/java/lang/Character.java286
-rw-r--r--libjava/java/lang/Class.h214
-rw-r--r--libjava/java/lang/Class.java155
-rw-r--r--libjava/java/lang/ClassCastException.java32
-rw-r--r--libjava/java/lang/ClassCircularityError.java34
-rw-r--r--libjava/java/lang/ClassFormatError.java34
-rw-r--r--libjava/java/lang/ClassLoader.java94
-rw-r--r--libjava/java/lang/ClassNotFoundException.java57
-rw-r--r--libjava/java/lang/CloneNotSupportedException.java32
-rw-r--r--libjava/java/lang/Cloneable.java23
-rw-r--r--libjava/java/lang/Comparable.java22
-rw-r--r--libjava/java/lang/Compiler.java53
-rw-r--r--libjava/java/lang/Double.java149
-rw-r--r--libjava/java/lang/Error.java34
-rw-r--r--libjava/java/lang/Exception.java32
-rw-r--r--libjava/java/lang/ExceptionInInitializerError.java50
-rw-r--r--libjava/java/lang/FirstThread.java40
-rw-r--r--libjava/java/lang/Float.java149
-rw-r--r--libjava/java/lang/IllegalAccessError.java34
-rw-r--r--libjava/java/lang/IllegalAccessException.java32
-rw-r--r--libjava/java/lang/IllegalArgumentException.java32
-rw-r--r--libjava/java/lang/IllegalMonitorStateException.java32
-rw-r--r--libjava/java/lang/IllegalStateException.java32
-rw-r--r--libjava/java/lang/IllegalThreadStateException.java32
-rw-r--r--libjava/java/lang/IncompatibleClassChangeError.java34
-rw-r--r--libjava/java/lang/IndexOutOfBoundsException.java32
-rw-r--r--libjava/java/lang/InstantiationError.java34
-rw-r--r--libjava/java/lang/InstantiationException.java32
-rw-r--r--libjava/java/lang/Integer.java355
-rw-r--r--libjava/java/lang/InternalError.java34
-rw-r--r--libjava/java/lang/InterruptedException.java32
-rw-r--r--libjava/java/lang/LinkageError.java34
-rw-r--r--libjava/java/lang/Long.java366
-rw-r--r--libjava/java/lang/Math.java118
-rw-r--r--libjava/java/lang/NegativeArraySizeException.java32
-rw-r--r--libjava/java/lang/NoClassDefFoundError.java34
-rw-r--r--libjava/java/lang/NoSuchFieldError.java34
-rw-r--r--libjava/java/lang/NoSuchFieldException.java32
-rw-r--r--libjava/java/lang/NoSuchMethodError.java34
-rw-r--r--libjava/java/lang/NoSuchMethodException.java32
-rw-r--r--libjava/java/lang/NullPointerException.java32
-rw-r--r--libjava/java/lang/Number.java39
-rw-r--r--libjava/java/lang/NumberFormatException.java32
-rw-r--r--libjava/java/lang/Object.h79
-rw-r--r--libjava/java/lang/Object.java86
-rw-r--r--libjava/java/lang/OutOfMemoryError.java34
-rw-r--r--libjava/java/lang/Process.java30
-rw-r--r--libjava/java/lang/Runnable.java27
-rw-r--r--libjava/java/lang/Runtime.java136
-rw-r--r--libjava/java/lang/RuntimeException.java32
-rw-r--r--libjava/java/lang/SecurityException.java31
-rw-r--r--libjava/java/lang/SecurityManager.java263
-rw-r--r--libjava/java/lang/Short.java145
-rw-r--r--libjava/java/lang/StackOverflowError.java34
-rw-r--r--libjava/java/lang/String.java286
-rw-r--r--libjava/java/lang/StringBuffer.java270
-rw-r--r--libjava/java/lang/StringIndexOutOfBoundsException.java37
-rw-r--r--libjava/java/lang/System.java166
-rw-r--r--libjava/java/lang/Thread.java297
-rw-r--r--libjava/java/lang/ThreadDeath.java35
-rw-r--r--libjava/java/lang/ThreadGroup.java406
-rw-r--r--libjava/java/lang/Throwable.java80
-rw-r--r--libjava/java/lang/UnknownError.java34
-rw-r--r--libjava/java/lang/UnsatisfiedLinkError.java34
-rw-r--r--libjava/java/lang/UnsupportedOperationException.java32
-rw-r--r--libjava/java/lang/VerifyError.java34
-rw-r--r--libjava/java/lang/VirtualMachineError.java34
-rw-r--r--libjava/java/lang/Void.java30
-rw-r--r--libjava/java/lang/dtoa.c906
-rw-r--r--libjava/java/lang/e_acos.c111
-rw-r--r--libjava/java/lang/e_asin.c120
-rw-r--r--libjava/java/lang/e_atan2.c131
-rw-r--r--libjava/java/lang/e_exp.c167
-rw-r--r--libjava/java/lang/e_fmod.c140
-rw-r--r--libjava/java/lang/e_log.c152
-rw-r--r--libjava/java/lang/e_pow.c312
-rw-r--r--libjava/java/lang/e_rem_pio2.c185
-rw-r--r--libjava/java/lang/e_remainder.c80
-rw-r--r--libjava/java/lang/e_scalb.c55
-rw-r--r--libjava/java/lang/e_sqrt.c452
-rw-r--r--libjava/java/lang/fdlibm.h343
-rw-r--r--libjava/java/lang/ieeefp.h103
-rw-r--r--libjava/java/lang/k_cos.c96
-rw-r--r--libjava/java/lang/k_rem_pio2.c320
-rw-r--r--libjava/java/lang/k_sin.c79
-rw-r--r--libjava/java/lang/k_tan.c132
-rw-r--r--libjava/java/lang/mprec.c958
-rw-r--r--libjava/java/lang/mprec.h374
-rw-r--r--libjava/java/lang/natCharacter.cc269
-rw-r--r--libjava/java/lang/natClass.cc785
-rw-r--r--libjava/java/lang/natDouble.cc180
-rw-r--r--libjava/java/lang/natFirstThread.cc56
-rw-r--r--libjava/java/lang/natFloat.cc37
-rw-r--r--libjava/java/lang/natMath.cc263
-rw-r--r--libjava/java/lang/natObject.cc241
-rw-r--r--libjava/java/lang/natRuntime.cc68
-rw-r--r--libjava/java/lang/natString.cc800
-rw-r--r--libjava/java/lang/natSystem.cc259
-rw-r--r--libjava/java/lang/natThread.cc295
-rw-r--r--libjava/java/lang/reflect/AccessibleObject.java53
-rw-r--r--libjava/java/lang/reflect/Array.java78
-rw-r--r--libjava/java/lang/reflect/Constructor.java106
-rw-r--r--libjava/java/lang/reflect/Field.java264
-rw-r--r--libjava/java/lang/reflect/InvocationTargetException.java73
-rw-r--r--libjava/java/lang/reflect/Member.java26
-rw-r--r--libjava/java/lang/reflect/Method.java123
-rw-r--r--libjava/java/lang/reflect/Modifier.java130
-rw-r--r--libjava/java/lang/reflect/natArray.cc339
-rw-r--r--libjava/java/lang/reflect/natField.cc435
-rw-r--r--libjava/java/lang/reflect/natMethod.cc386
-rw-r--r--libjava/java/lang/s_atan.c181
-rw-r--r--libjava/java/lang/s_ceil.c80
-rw-r--r--libjava/java/lang/s_copysign.c82
-rw-r--r--libjava/java/lang/s_cos.c82
-rw-r--r--libjava/java/lang/s_fabs.c73
-rw-r--r--libjava/java/lang/s_floor.c134
-rw-r--r--libjava/java/lang/s_rint.c87
-rw-r--r--libjava/java/lang/s_scalbn.c104
-rw-r--r--libjava/java/lang/s_sin.c132
-rw-r--r--libjava/java/lang/s_tan.c114
-rw-r--r--libjava/java/lang/sf_rint.c80
-rw-r--r--libjava/java/lang/strtod.c720
-rw-r--r--libjava/java/lang/w_acos.c118
-rw-r--r--libjava/java/lang/w_asin.c121
-rw-r--r--libjava/java/lang/w_atan2.c117
-rw-r--r--libjava/java/lang/w_exp.c136
-rw-r--r--libjava/java/lang/w_fmod.c107
-rw-r--r--libjava/java/lang/w_log.c115
-rw-r--r--libjava/java/lang/w_pow.c231
-rw-r--r--libjava/java/lang/w_remainder.c119
-rw-r--r--libjava/java/lang/w_sqrt.c93
-rw-r--r--libjava/java/net/BindException.java35
-rw-r--r--libjava/java/net/ConnectException.java35
-rw-r--r--libjava/java/net/ContentHandler.java29
-rw-r--r--libjava/java/net/ContentHandlerFactory.java27
-rw-r--r--libjava/java/net/FileNameMap.java27
-rw-r--r--libjava/java/net/HttpURLConnection.java174
-rw-r--r--libjava/java/net/InetAddress.java255
-rw-r--r--libjava/java/net/MalformedURLException.java35
-rw-r--r--libjava/java/net/NoRouteToHostException.java35
-rw-r--r--libjava/java/net/PlainSocketImpl.java64
-rw-r--r--libjava/java/net/ProtocolException.java35
-rw-r--r--libjava/java/net/ServerSocket.java105
-rw-r--r--libjava/java/net/Socket.java209
-rw-r--r--libjava/java/net/SocketException.java33
-rw-r--r--libjava/java/net/SocketImpl.java70
-rw-r--r--libjava/java/net/SocketImplFactory.java25
-rw-r--r--libjava/java/net/URL.java341
-rw-r--r--libjava/java/net/URLConnection.java423
-rw-r--r--libjava/java/net/URLStreamHandler.java107
-rw-r--r--libjava/java/net/URLStreamHandlerFactory.java27
-rw-r--r--libjava/java/net/UnknownHostException.java34
-rw-r--r--libjava/java/net/UnknownServiceException.java35
-rw-r--r--libjava/java/net/natInetAddress.cc270
-rw-r--r--libjava/java/net/natPlainSocketImpl.cc177
-rw-r--r--libjava/java/text/BreakIterator.java160
-rw-r--r--libjava/java/text/CharacterIterator.java36
-rw-r--r--libjava/java/text/ChoiceFormat.java310
-rw-r--r--libjava/java/text/DateFormat.java301
-rw-r--r--libjava/java/text/DateFormatSymbols.java265
-rw-r--r--libjava/java/text/DecimalFormat.java983
-rw-r--r--libjava/java/text/DecimalFormatSymbols.java293
-rw-r--r--libjava/java/text/FieldPosition.java65
-rw-r--r--libjava/java/text/Format.java51
-rw-r--r--libjava/java/text/MessageFormat.java543
-rw-r--r--libjava/java/text/NumberFormat.java236
-rw-r--r--libjava/java/text/ParseException.java34
-rw-r--r--libjava/java/text/ParsePosition.java59
-rw-r--r--libjava/java/text/SimpleDateFormat.java522
-rw-r--r--libjava/java/text/StringCharacterIterator.java142
-rw-r--r--libjava/java/util/BitSet.java183
-rw-r--r--libjava/java/util/Calendar.java258
-rw-r--r--libjava/java/util/ConcurrentModificationException.java33
-rw-r--r--libjava/java/util/Date.java460
-rw-r--r--libjava/java/util/Dictionary.java34
-rw-r--r--libjava/java/util/EmptyStackException.java27
-rw-r--r--libjava/java/util/Enumeration.java24
-rw-r--r--libjava/java/util/EventListener.java24
-rw-r--r--libjava/java/util/EventObject.java42
-rw-r--r--libjava/java/util/GregorianCalendar.java257
-rw-r--r--libjava/java/util/Hashtable.java398
-rw-r--r--libjava/java/util/ListResourceBundle.java52
-rw-r--r--libjava/java/util/Locale.java125
-rw-r--r--libjava/java/util/MissingResourceException.java43
-rw-r--r--libjava/java/util/NoSuchElementException.java32
-rw-r--r--libjava/java/util/Observable.java98
-rw-r--r--libjava/java/util/Observer.java24
-rw-r--r--libjava/java/util/Properties.java376
-rw-r--r--libjava/java/util/Random.java148
-rw-r--r--libjava/java/util/ResourceBundle.java188
-rw-r--r--libjava/java/util/SimpleTimeZone.java182
-rw-r--r--libjava/java/util/Stack.java74
-rw-r--r--libjava/java/util/StringTokenizer.java185
-rw-r--r--libjava/java/util/TimeZone.java120
-rw-r--r--libjava/java/util/TooManyListenersException.java32
-rw-r--r--libjava/java/util/Vector.java450
-rw-r--r--libjava/java/util/natDate.cc45
-rw-r--r--libjava/java/util/natGregorianCalendar.cc124
-rw-r--r--libjava/java/util/zip/Adler32.java101
-rw-r--r--libjava/java/util/zip/CRC32.java70
-rw-r--r--libjava/java/util/zip/Checksum.java31
-rw-r--r--libjava/java/util/zip/Deflater.java13
-rw-r--r--libjava/java/util/zip/DeflaterOutputStream.java46
-rw-r--r--libjava/java/util/zip/ZipConstants.java13
-rw-r--r--libjava/java/util/zip/ZipEntry.java84
-rw-r--r--libjava/java/util/zip/ZipException.java33
-rw-r--r--libjava/java/util/zip/ZipFile.java81
-rw-r--r--libjava/java/util/zip/ZipOutputStream.java26
271 files changed, 37903 insertions, 0 deletions
diff --git a/libjava/java/io/BufferedInputStream.java b/libjava/java/io/BufferedInputStream.java
new file mode 100644
index 00000000000..698abf608af
--- /dev/null
+++ b/libjava/java/io/BufferedInputStream.java
@@ -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;
+ }
+}
diff --git a/libjava/java/io/BufferedOutputStream.java b/libjava/java/io/BufferedOutputStream.java
new file mode 100644
index 00000000000..d37ed5d2cb0
--- /dev/null
+++ b/libjava/java/io/BufferedOutputStream.java
@@ -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;
+}
diff --git a/libjava/java/io/BufferedReader.java b/libjava/java/io/BufferedReader.java
new file mode 100644
index 00000000000..19e371a24e3
--- /dev/null
+++ b/libjava/java/io/BufferedReader.java
@@ -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;
+ }
+ }
+}
diff --git a/libjava/java/io/BufferedWriter.java b/libjava/java/io/BufferedWriter.java
new file mode 100644
index 00000000000..85aceed68bd
--- /dev/null
+++ b/libjava/java/io/BufferedWriter.java
@@ -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;
+}
diff --git a/libjava/java/io/ByteArrayInputStream.java b/libjava/java/io/ByteArrayInputStream.java
new file mode 100644
index 00000000000..9b9bf964baa
--- /dev/null
+++ b/libjava/java/io/ByteArrayInputStream.java
@@ -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;
+ }
+}
diff --git a/libjava/java/io/ByteArrayOutputStream.java b/libjava/java/io/ByteArrayOutputStream.java
new file mode 100644
index 00000000000..4d5f224e376
--- /dev/null
+++ b/libjava/java/io/ByteArrayOutputStream.java
@@ -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;
+}
diff --git a/libjava/java/io/CharArrayReader.java b/libjava/java/io/CharArrayReader.java
new file mode 100644
index 00000000000..a43e8da62e9
--- /dev/null
+++ b/libjava/java/io/CharArrayReader.java
@@ -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;
+ }
+ }
+}
diff --git a/libjava/java/io/CharArrayWriter.java b/libjava/java/io/CharArrayWriter.java
new file mode 100644
index 00000000000..3e1e4a4f78e
--- /dev/null
+++ b/libjava/java/io/CharArrayWriter.java
@@ -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;
+}
diff --git a/libjava/java/io/CharConversionException.java b/libjava/java/io/CharConversionException.java
new file mode 100644
index 00000000000..039578e4c52
--- /dev/null
+++ b/libjava/java/io/CharConversionException.java
@@ -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);
+ }
+}
diff --git a/libjava/java/io/DataInput.java b/libjava/java/io/DataInput.java
new file mode 100644
index 00000000000..2c6f988cc79
--- /dev/null
+++ b/libjava/java/io/DataInput.java
@@ -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;
+}
diff --git a/libjava/java/io/DataInputStream.java b/libjava/java/io/DataInputStream.java
new file mode 100644
index 00000000000..7c90008c6e0
--- /dev/null
+++ b/libjava/java/io/DataInputStream.java
@@ -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;
+ }
+}
diff --git a/libjava/java/io/DataOutput.java b/libjava/java/io/DataOutput.java
new file mode 100644
index 00000000000..c3fd366c561
--- /dev/null
+++ b/libjava/java/io/DataOutput.java
@@ -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;
+}
diff --git a/libjava/java/io/DataOutputStream.java b/libjava/java/io/DataOutputStream.java
new file mode 100644
index 00000000000..2ef4cf08885
--- /dev/null
+++ b/libjava/java/io/DataOutputStream.java
@@ -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;
+}
diff --git a/libjava/java/io/EOFException.java b/libjava/java/io/EOFException.java
new file mode 100644
index 00000000000..d890a0f79a7
--- /dev/null
+++ b/libjava/java/io/EOFException.java
@@ -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);
+ }
+}
diff --git a/libjava/java/io/File.java b/libjava/java/io/File.java
new file mode 100644
index 00000000000..30d98878f9c
--- /dev/null
+++ b/libjava/java/io/File.java
@@ -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);
+}
diff --git a/libjava/java/io/FileDescriptor.java b/libjava/java/io/FileDescriptor.java
new file mode 100644
index 00000000000..0782b0c8e95
--- /dev/null
+++ b/libjava/java/io/FileDescriptor.java
@@ -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;
+}
diff --git a/libjava/java/io/FileInputStream.java b/libjava/java/io/FileInputStream.java
new file mode 100644
index 00000000000..4f44dae03b7
--- /dev/null
+++ b/libjava/java/io/FileInputStream.java
@@ -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);
+ }
+}
diff --git a/libjava/java/io/FileNotFoundException.java b/libjava/java/io/FileNotFoundException.java
new file mode 100644
index 00000000000..07ff9bf1d9b
--- /dev/null
+++ b/libjava/java/io/FileNotFoundException.java
@@ -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);
+ }
+}
diff --git a/libjava/java/io/FileOutputStream.java b/libjava/java/io/FileOutputStream.java
new file mode 100644
index 00000000000..3e6e9724aec
--- /dev/null
+++ b/libjava/java/io/FileOutputStream.java
@@ -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;
+}
diff --git a/libjava/java/io/FileReader.java b/libjava/java/io/FileReader.java
new file mode 100644
index 00000000000..259526cceff
--- /dev/null
+++ b/libjava/java/io/FileReader.java
@@ -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));
+ }
+}
diff --git a/libjava/java/io/FileWriter.java b/libjava/java/io/FileWriter.java
new file mode 100644
index 00000000000..8c3f9a9d303
--- /dev/null
+++ b/libjava/java/io/FileWriter.java
@@ -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));
+ }
+}
diff --git a/libjava/java/io/FilenameFilter.java b/libjava/java/io/FilenameFilter.java
new file mode 100644
index 00000000000..682efed6d8a
--- /dev/null
+++ b/libjava/java/io/FilenameFilter.java
@@ -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);
+}
diff --git a/libjava/java/io/FilterInputStream.java b/libjava/java/io/FilterInputStream.java
new file mode 100644
index 00000000000..918948b2edd
--- /dev/null
+++ b/libjava/java/io/FilterInputStream.java
@@ -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);
+ }
+}
diff --git a/libjava/java/io/FilterOutputStream.java b/libjava/java/io/FilterOutputStream.java
new file mode 100644
index 00000000000..45d6fd024ad
--- /dev/null
+++ b/libjava/java/io/FilterOutputStream.java
@@ -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;
+}
diff --git a/libjava/java/io/FilterReader.java b/libjava/java/io/FilterReader.java
new file mode 100644
index 00000000000..1fe201472b4
--- /dev/null
+++ b/libjava/java/io/FilterReader.java
@@ -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);
+ }
+}
diff --git a/libjava/java/io/FilterWriter.java b/libjava/java/io/FilterWriter.java
new file mode 100644
index 00000000000..385cc7eee30
--- /dev/null
+++ b/libjava/java/io/FilterWriter.java
@@ -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;
+}
diff --git a/libjava/java/io/IOException.java b/libjava/java/io/IOException.java
new file mode 100644
index 00000000000..15a14ff15fa
--- /dev/null
+++ b/libjava/java/io/IOException.java
@@ -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);
+ }
+}
diff --git a/libjava/java/io/InputStream.java b/libjava/java/io/InputStream.java
new file mode 100644
index 00000000000..cc86efd49d6
--- /dev/null
+++ b/libjava/java/io/InputStream.java
@@ -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;
+ }
+}
diff --git a/libjava/java/io/InputStreamReader.java b/libjava/java/io/InputStreamReader.java
new file mode 100644
index 00000000000..ee44f918122
--- /dev/null
+++ b/libjava/java/io/InputStreamReader.java
@@ -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++];
+ }
+ }
+}
diff --git a/libjava/java/io/InterruptedIOException.java b/libjava/java/io/InterruptedIOException.java
new file mode 100644
index 00000000000..11d922b765e
--- /dev/null
+++ b/libjava/java/io/InterruptedIOException.java
@@ -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;
+}
diff --git a/libjava/java/io/LineNumberInputStream.java b/libjava/java/io/LineNumberInputStream.java
new file mode 100644
index 00000000000..1b96da9c846
--- /dev/null
+++ b/libjava/java/io/LineNumberInputStream.java
@@ -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;
+ }
+}
diff --git a/libjava/java/io/LineNumberReader.java b/libjava/java/io/LineNumberReader.java
new file mode 100644
index 00000000000..c709a7a0079
--- /dev/null
+++ b/libjava/java/io/LineNumberReader.java
@@ -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;
+ }
+}
diff --git a/libjava/java/io/OutputStream.java b/libjava/java/io/OutputStream.java
new file mode 100644
index 00000000000..5aae3611621
--- /dev/null
+++ b/libjava/java/io/OutputStream.java
@@ -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
+ {
+ }
+}
diff --git a/libjava/java/io/OutputStreamWriter.java b/libjava/java/io/OutputStreamWriter.java
new file mode 100644
index 00000000000..e529474875c
--- /dev/null
+++ b/libjava/java/io/OutputStreamWriter.java
@@ -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;
+ }
+ }
+}
diff --git a/libjava/java/io/PipedInputStream.java b/libjava/java/io/PipedInputStream.java
new file mode 100644
index 00000000000..d8a836c289f
--- /dev/null
+++ b/libjava/java/io/PipedInputStream.java
@@ -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();
+ }
+}
diff --git a/libjava/java/io/PipedOutputStream.java b/libjava/java/io/PipedOutputStream.java
new file mode 100644
index 00000000000..9b069944926
--- /dev/null
+++ b/libjava/java/io/PipedOutputStream.java
@@ -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;
+}
diff --git a/libjava/java/io/PipedReader.java b/libjava/java/io/PipedReader.java
new file mode 100644
index 00000000000..f54c4f8031f
--- /dev/null
+++ b/libjava/java/io/PipedReader.java
@@ -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;
+}
diff --git a/libjava/java/io/PipedWriter.java b/libjava/java/io/PipedWriter.java
new file mode 100644
index 00000000000..c914cac9f9c
--- /dev/null
+++ b/libjava/java/io/PipedWriter.java
@@ -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;
+}
diff --git a/libjava/java/io/PrintStream.java b/libjava/java/io/PrintStream.java
new file mode 100644
index 00000000000..499e5eb7059
--- /dev/null
+++ b/libjava/java/io/PrintStream.java
@@ -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");
+}
diff --git a/libjava/java/io/PrintWriter.java b/libjava/java/io/PrintWriter.java
new file mode 100644
index 00000000000..2a6cb01b95b
--- /dev/null
+++ b/libjava/java/io/PrintWriter.java
@@ -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());
+ }
+}
diff --git a/libjava/java/io/PushbackInputStream.java b/libjava/java/io/PushbackInputStream.java
new file mode 100644
index 00000000000..58c8fe6c4ec
--- /dev/null
+++ b/libjava/java/io/PushbackInputStream.java
@@ -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;
+ }
+}
diff --git a/libjava/java/io/PushbackReader.java b/libjava/java/io/PushbackReader.java
new file mode 100644
index 00000000000..0cfd63cdb2b
--- /dev/null
+++ b/libjava/java/io/PushbackReader.java
@@ -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;
+ }
+ }
+}
diff --git a/libjava/java/io/RandomAccessFile.java b/libjava/java/io/RandomAccessFile.java
new file mode 100644
index 00000000000..d240e0df439
--- /dev/null
+++ b/libjava/java/io/RandomAccessFile.java
@@ -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;
+}
diff --git a/libjava/java/io/Reader.java b/libjava/java/io/Reader.java
new file mode 100644
index 00000000000..b54735836c2
--- /dev/null
+++ b/libjava/java/io/Reader.java
@@ -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;
+ }
+}
diff --git a/libjava/java/io/SequenceInputStream.java b/libjava/java/io/SequenceInputStream.java
new file mode 100644
index 00000000000..771351784ab
--- /dev/null
+++ b/libjava/java/io/SequenceInputStream.java
@@ -0,0 +1,112 @@
+/* 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 java.util.Enumeration;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date November 3, 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 SequenceInputStream extends InputStream
+{
+ /* The handle for the current input stream. */
+ private InputStream in;
+
+ /* Secondary input stream; not used if constructed w/ enumeration. */
+ private InputStream in2;
+
+ /* The enum handle; not used if constructed w/ 2 explicit input streams. */
+ private Enumeration enum;
+
+ public SequenceInputStream(Enumeration e)
+ {
+ // FIXME: Assumes that enum contains only InputStreams.
+ enum = e;
+ in = (InputStream) enum.nextElement();
+ in2 = null;
+ }
+
+ public SequenceInputStream(InputStream s1, InputStream s2)
+ {
+ in = s1;
+ in2 = s2;
+ }
+
+ public int available() throws IOException
+ {
+ if (in == null)
+ return 0;
+
+ return in.available();
+ }
+
+ public void close() throws IOException
+ {
+ while (in != null)
+ {
+ in.close();
+ in = getNextStream ();
+ }
+ }
+
+ public int read() throws IOException
+ {
+ int ch = -1;
+
+ while (in != null && (ch = in.read()) < 0)
+ {
+ in.close();
+ in = getNextStream();
+ }
+
+ return ch;
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ int ch = -1;
+
+ // The validity of the parameters will be checked by in.read so
+ // don't bother doing it here.
+ while (in != null && (ch = in.read(b, off, len)) < 0)
+ {
+ in.close();
+ in = getNextStream();
+ }
+
+ return ch;
+ }
+
+ private InputStream getNextStream()
+ {
+ InputStream nextIn = null;
+
+ // FIXME: Assumes that enum contains only InputStreams.
+ if (enum != null)
+ {
+ if (enum.hasMoreElements())
+ nextIn = (InputStream) enum.nextElement();
+ }
+ else
+ if (in2 != null)
+ {
+ nextIn = in2;
+ in2 = null;
+ }
+
+ return nextIn;
+ }
+}
diff --git a/libjava/java/io/Serializable.java b/libjava/java/io/Serializable.java
new file mode 100644
index 00000000000..d4a31dbbad1
--- /dev/null
+++ b/libjava/java/io/Serializable.java
@@ -0,0 +1,21 @@
+/* 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 August 18, 1998.
+ */
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * Status: Believed complete
+ */
+
+public interface Serializable
+{
+}
diff --git a/libjava/java/io/StreamTokenizer.java b/libjava/java/io/StreamTokenizer.java
new file mode 100644
index 00000000000..d518f83b98d
--- /dev/null
+++ b/libjava/java/io/StreamTokenizer.java
@@ -0,0 +1,433 @@
+/* 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 25, 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 StreamTokenizer
+{
+ /* A constant indicating that the end of the stream has been read. */
+ public static final int TT_EOF = -1;
+
+ /* A constant indicating that the end of the line has been read. */
+ public static final int TT_EOL = '\n';
+
+ /* A constant indicating that a number token has been read. */
+ public static final int TT_NUMBER = -2;
+
+ /* A constant indicating that a word token has been read. */
+ public static final int TT_WORD = -3;
+
+ /* Contains the type of the token read resulting from a call to nextToken. */
+ public int ttype;
+
+ /* The String associated with word and string tokens. */
+ public String sval;
+
+ /* The numeric value associated with number tokens. */
+ public double nval;
+
+ /* Indicates whether end-of-line is recognized as a token. */
+ private boolean eolSignificant = false;
+
+ /* Indicates whether word tokens are automatically made lower case. */
+ private boolean lowerCase = false;
+
+ /* Indicates whether C++ style comments are recognized and skipped. */
+ private boolean slashSlash = false;
+
+ /* Indicates whether C style comments are recognized and skipped. */
+ private boolean slashStar = false;
+
+ /* Attribute tables of each byte from 0x00 to 0xFF. */
+ private boolean[] whitespace;
+ private boolean[] alphabetic;
+ private boolean[] numeric;
+ private boolean[] quote;
+ private boolean[] comment;
+
+ /* The Reader associated with this class. */
+ private PushbackReader in;
+
+ /* Indicates if a token has been pushed back. */
+ private boolean pushedBack = false;
+
+ /* Contains the current line number of the reader. */
+ private int lineNumber = 1;
+
+ // Deprecated in JDK 1.1.
+ public StreamTokenizer(InputStream is)
+ {
+ this(new InputStreamReader(is));
+ }
+
+ public StreamTokenizer(Reader r)
+ {
+ in = new PushbackReader(r);
+
+ whitespace = new boolean[256];
+ alphabetic = new boolean[256];
+ numeric = new boolean[256];
+ quote = new boolean[256];
+ comment = new boolean[256];
+ for (int i = 0; i < 256; i++)
+ resetChar(i);
+
+ whitespaceChars(0x00, 0x20);
+ wordChars('A', 'Z');
+ wordChars('a', 'z');
+ wordChars(0xA0, 0xFF);
+ commentChar('/');
+ quoteChar('\'');
+ quoteChar('"');
+ parseNumbers();
+ }
+
+ public void commentChar(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ comment[ch] = true;
+ }
+
+ public void eolIsSignificant(boolean flag)
+ {
+ eolSignificant = flag;
+ }
+
+ public int lineno()
+ {
+ return lineNumber;
+ }
+
+ public void lowerCaseMode(boolean flag)
+ {
+ lowerCase = flag;
+ }
+
+ private boolean isWhitespace(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ return whitespace[ch];
+
+ return false;
+ }
+
+ private boolean isAlphabetic(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ return alphabetic[ch];
+ else if (ch > 255)
+ return true;
+
+ return false;
+ }
+
+ private boolean isNumeric(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ return numeric[ch];
+
+ return false;
+ }
+
+ private boolean isQuote(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ return quote[ch];
+
+ return false;
+ }
+
+ private boolean isComment(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ return comment[ch];
+
+ return false;
+ }
+
+ public int nextToken() throws IOException
+ {
+ if (pushedBack)
+ {
+ pushedBack = false;
+ return ttype;
+ }
+
+ sval = null;
+ int ch;
+
+ // Skip whitespace. Deal with EOL along the way.
+ while (isWhitespace(ch = in.read()))
+ if (ch == '\n' || ch == '\r')
+ {
+ lineNumber++;
+
+ // Throw away \n if in combination with \r.
+ if (ch == '\r' && (ch = in.read()) != '\n')
+ in.unread(ch);
+ if (eolSignificant)
+ return (ttype = TT_EOL);
+ }
+
+ if (ch == TT_EOF)
+ ttype = TT_EOF;
+ else if (isNumeric(ch))
+ {
+ if (ch == '-')
+ {
+ // Read ahead to see if this is an ordinary '-' rather than numeric.
+ ch = in.read();
+ in.unread(ch);
+ if (isNumeric(ch) && ch != '-')
+ ch = '-';
+ else
+ return (ttype = '-');
+ }
+
+ StringBuffer tokbuf = new StringBuffer();
+ tokbuf.append((char) ch);
+
+ int decCount = 0;
+ while (isNumeric(ch = in.read()) && ch != '-')
+ if (ch == '.' && decCount++ > 0)
+ break;
+ else
+ tokbuf.append((char) ch);
+
+ in.unread(ch);
+ ttype = TT_NUMBER;
+ nval = Double.valueOf(tokbuf.toString()).doubleValue();
+ }
+ else if (isAlphabetic(ch))
+ {
+ StringBuffer tokbuf = new StringBuffer();
+ tokbuf.append((char) ch);
+ while (isAlphabetic(ch = in.read()) || isNumeric(ch))
+ tokbuf.append((char) ch);
+ in.unread(ch);
+ ttype = TT_WORD;
+ sval = tokbuf.toString();
+ if (lowerCase)
+ sval.toLowerCase();
+ }
+ else if (isComment(ch))
+ {
+ while ((ch = in.read()) != '\n' && ch != '\r' && ch != TT_EOF)
+ ;
+ in.unread(ch);
+ return nextToken(); // Recursive, but not too deep in normal cases.
+ }
+ else if (isQuote(ch))
+ {
+ ttype = ch;
+ StringBuffer tokbuf = new StringBuffer();
+ while ((ch = in.read()) != ttype && ch != '\n' && ch != '\r' &&
+ ch != TT_EOF)
+ {
+ if (ch == '\\')
+ switch (ch = in.read())
+ {
+ case 'a': ch = 0x7;
+ break;
+ case 'b': ch = '\b';
+ break;
+ case 'f': ch = 0xC;
+ break;
+ case 'n': ch = '\n';
+ break;
+ case 'r': ch = '\r';
+ break;
+ case 't': ch = '\t';
+ break;
+ case 'v': ch = 0xB;
+ break;
+ case '\"':
+ case '\'':
+ case '\\':
+ break;
+ default:
+ int ch1, nextch;
+ if ((nextch = ch1 = ch) >= '0' && ch <= '7')
+ {
+ ch -= '0';
+ if ((nextch = in.read()) >= '0' && nextch <= '7')
+ {
+ ch = ch * 8 + nextch - '0';
+ if ((nextch = in.read()) >= '0' && nextch <= '7' &&
+ ch1 >= '0' && ch1 <= '3')
+ {
+ ch = ch * 8 + nextch - '0';
+ nextch = in.read();
+ }
+ }
+ }
+
+ in.unread(nextch);
+ }
+
+ tokbuf.append((char) ch);
+ }
+
+ // Throw away matching quote char.
+ if (ch != ttype)
+ in.unread(ch);
+
+ sval = tokbuf.toString();
+ }
+ else
+ {
+ if (ch == '/')
+ if ((ch = in.read()) == '/' && slashSlash)
+ {
+ while ((ch = in.read()) != '\n' && ch != '\r' && ch != TT_EOF)
+ ;
+ in.unread(ch);
+ return nextToken(); // Recursive, but not too deep in normal cases
+ }
+ else if (ch == '*' && slashStar)
+ {
+ while (true)
+ {
+ ch = in.read();
+ if (ch == '*')
+ if ((ch = in.read()) == '/')
+ break;
+ else
+ in.unread(ch);
+ else if (ch == '\n' || ch == '\r')
+ {
+ lineNumber++;
+ if (ch == '\r' && (ch = in.read()) != '\n')
+ in.unread(ch);
+ }
+ else if (ch == TT_EOF)
+ {
+ in.unread(ch);
+ break;
+ }
+ }
+ return nextToken(); // Recursive, but not too deep in normal cases
+ }
+ else
+ {
+ in.unread(ch);
+ ch = '/';
+ }
+
+ ttype = ch;
+ }
+
+ return ttype;
+ }
+
+ private void resetChar(int ch)
+ {
+ whitespace[ch] = alphabetic[ch] = numeric[ch] = quote[ch] = comment[ch] =
+ false;
+ }
+
+ public void ordinaryChar(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ resetChar(ch);
+ }
+
+ public void ordinaryChars(int low, int hi)
+ {
+ if (low < 0)
+ low = 0;
+ if (hi > 255)
+ hi = 255;
+ for (int i = low; i <= hi; i++)
+ resetChar(i);
+ }
+
+ public void parseNumbers()
+ {
+ for (int i = 0; i <= 9; i++)
+ numeric['0' + i] = true;
+
+ numeric['.'] = true;
+ numeric['-'] = true;
+ }
+
+ public void pushBack()
+ {
+ // pushBack may cause the lineno method to return an incorrect value
+ // if lineno is called before the next call to nextToken.
+ pushedBack = true;
+ }
+
+ public void quoteChar(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ quote[ch] = true;
+ }
+
+ public void resetSyntax()
+ {
+ ordinaryChars(0x00, 0xFF);
+ }
+
+ public void slashSlashComments(boolean flag)
+ {
+ slashSlash = flag;
+ }
+
+ public void slashStarComments(boolean flag)
+ {
+ slashStar = flag;
+ }
+
+ public String toString()
+ {
+ String tempstr;
+ if (ttype == TT_EOF)
+ tempstr = "EOF";
+ else if (ttype == TT_EOL)
+ tempstr = "EOL";
+ else if (ttype == TT_WORD)
+ tempstr = sval;
+ else if (ttype == TT_NUMBER)
+ tempstr = "n=" + Double.toString(nval);
+ else // must be an ordinary char.
+ tempstr = "\'" + (new Character((char) ttype)).toString() + "\'";
+
+ return "Token[" + tempstr + "], line " + Integer.toString(lineno());
+ }
+
+ public void whitespaceChars(int low, int hi)
+ {
+ if (low < 0)
+ low = 0;
+ if (hi > 255)
+ hi = 255;
+ for (int i = low; i <= hi; i++)
+ whitespace[i] = true;
+ }
+
+ public void wordChars(int low, int hi)
+ {
+ if (low < 0)
+ low = 0;
+ if (hi > 255)
+ hi = 255;
+ for (int i = low; i <= hi; i++)
+ alphabetic[i] = true;
+ }
+}
diff --git a/libjava/java/io/StringBufferInputStream.java b/libjava/java/io/StringBufferInputStream.java
new file mode 100644
index 00000000000..19e89db592c
--- /dev/null
+++ b/libjava/java/io/StringBufferInputStream.java
@@ -0,0 +1,83 @@
+/* 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 StringBufferInputStream extends InputStream
+{
+ /* The String which is the input to this stream. */
+ protected String buffer;
+
+ /* Position of the next byte in buffer to be read. */
+ protected int pos = 0;
+
+ /* The length of the String buffer. */
+ protected int count;
+
+ public StringBufferInputStream(String s)
+ {
+ buffer = s;
+ count = s.length();
+ }
+
+ public int available()
+ {
+ return count - pos;
+ }
+
+ public int read()
+ {
+ if (pos >= count)
+ return -1; // EOF
+
+ return ((int) buffer.charAt(pos++)) & 0xFF;
+ }
+
+ public int read(byte[] b, int off, int len)
+ {
+ if (off < 0 || len < 0 || off + len > b.length)
+ throw new ArrayIndexOutOfBoundsException();
+
+ if (pos >= count)
+ return -1; // EOF
+
+ int numRead = Math.min(len, count - pos);
+ if (numRead < 0)
+ return 0;
+
+ buffer.getBytes(pos, pos + numRead, b, off);
+ pos += numRead;
+ return numRead;
+ }
+
+ public void reset()
+ {
+ pos = 0;
+ }
+
+ public long skip(long n)
+ {
+ if (n < 0)
+ return 0L;
+
+ long actualSkip = Math.min(n, count - pos);
+ pos += actualSkip;
+ return actualSkip;
+ }
+}
diff --git a/libjava/java/io/StringReader.java b/libjava/java/io/StringReader.java
new file mode 100644
index 00000000000..08e8d0c4f15
--- /dev/null
+++ b/libjava/java/io/StringReader.java
@@ -0,0 +1,139 @@
+/* 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 19, 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 StringReader extends Reader
+{
+ /* A String provided by the creator of the stream. */
+ private String buf;
+
+ /* Position of the next char in buf to be read. */
+ private int pos;
+
+ /* The currently marked position in the stream. */
+ private int markedPos;
+
+ /* The index in buf one greater than the last valid character. */
+ private int count;
+
+ public StringReader(String buffer)
+ {
+ super();
+ buf = buffer;
+
+ count = buffer.length();
+ markedPos = pos = 0;
+ }
+
+ public void close()
+ {
+ synchronized (lock)
+ {
+ buf = null;
+ }
+ }
+
+ public void mark(int readAheadLimit) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException();
+
+ // readAheadLimit is ignored per Java Class Lib. book, p. 1692.
+ markedPos = pos;
+ }
+ }
+
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+ public int read() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException();
+
+ if (pos < count)
+ return ((int) buf.charAt(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 lastChar = Math.min(count, pos + len);
+ buf.getChars(pos, lastChar, b, off);
+ int numChars = lastChar - pos;
+ pos = lastChar;
+ return numChars;
+ }
+ }
+
+ public boolean ready() // TODO12: throws IOException
+ {
+ // TODO12: The JCL specifically says this returns true even if the
+ // reader has been closed, whereas the online 1.2 doc specifically
+ // says to throw an IOException if closed.
+ 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;
+ }
+ }
+}
diff --git a/libjava/java/io/StringWriter.java b/libjava/java/io/StringWriter.java
new file mode 100644
index 00000000000..90ad9a9b688
--- /dev/null
+++ b/libjava/java/io/StringWriter.java
@@ -0,0 +1,80 @@
+// StringWriter.java - StringBuffer 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 StringWriter extends Writer
+{
+ 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 StringBuffer getBuffer ()
+ {
+ return buffer;
+ }
+
+ public StringWriter ()
+ {
+ this (16);
+ }
+
+ protected StringWriter (int size)
+ {
+ super ();
+ buffer = new StringBuffer (size);
+ lock = buffer;
+ }
+
+ public String toString ()
+ {
+ return buffer.toString();
+ }
+
+ public void write (int oneChar)
+ {
+ buffer.append((char) oneChar);
+ }
+
+ public void write (char[] chars, int offset, int len)
+ {
+ buffer.append(chars, offset, len);
+ }
+
+ public void write (String str)
+ {
+ buffer.append(str);
+ }
+
+ public void write (String str, int offset, int len)
+ {
+ buffer.append(str.substring(offset, offset + len));
+ }
+
+ // The string buffer.
+ private StringBuffer buffer;
+}
diff --git a/libjava/java/io/SyncFailedException.java b/libjava/java/io/SyncFailedException.java
new file mode 100644
index 00000000000..b920198edf6
--- /dev/null
+++ b/libjava/java/io/SyncFailedException.java
@@ -0,0 +1,34 @@
+// SyncFailedException.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 SyncFailedException extends IOException
+{
+ public SyncFailedException ()
+ {
+ super ();
+ }
+
+ public SyncFailedException (String s)
+ {
+ super (s);
+ }
+}
diff --git a/libjava/java/io/UTFDataFormatException.java b/libjava/java/io/UTFDataFormatException.java
new file mode 100644
index 00000000000..aea35401772
--- /dev/null
+++ b/libjava/java/io/UTFDataFormatException.java
@@ -0,0 +1,34 @@
+// UTFDataFormatException.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 UTFDataFormatException extends IOException
+{
+ public UTFDataFormatException ()
+ {
+ super ();
+ }
+
+ public UTFDataFormatException (String s)
+ {
+ super (s);
+ }
+}
diff --git a/libjava/java/io/UnsupportedEncodingException.java b/libjava/java/io/UnsupportedEncodingException.java
new file mode 100644
index 00000000000..f3c26f9b316
--- /dev/null
+++ b/libjava/java/io/UnsupportedEncodingException.java
@@ -0,0 +1,32 @@
+/* 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.
+ */
+
+public class UnsupportedEncodingException extends IOException
+{
+ public UnsupportedEncodingException ()
+ {
+ super();
+ }
+
+ public UnsupportedEncodingException (String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/io/Writer.java b/libjava/java/io/Writer.java
new file mode 100644
index 00000000000..48cedb63114
--- /dev/null
+++ b/libjava/java/io/Writer.java
@@ -0,0 +1,67 @@
+/* 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, write(String, int, int) should be made a native method.
+ */
+
+public abstract class Writer
+{
+ protected Object lock;
+
+ protected Writer ()
+ {
+ lock = this;
+ }
+
+ protected Writer (Object lock)
+ {
+ this.lock = lock;
+ }
+
+ abstract public void close() throws IOException;
+
+ abstract public void flush() throws IOException;
+
+ abstract public void write(char[] buf, int offset, int count)
+ throws IOException;
+
+ public void write(char[] buf) throws IOException
+ {
+ write(buf, 0, buf.length);
+ }
+
+ public void write(int ch) throws IOException
+ {
+ char[] buf = new char[1];
+ buf[0] = (char) ch;
+ write(buf, 0, 1);
+ }
+
+ // FIXME - re-write using native code to not require copied buffer.
+ public void write (String str, int offset, int count) throws IOException
+ {
+ char[] buf = new char[count];
+ str.getChars(offset, offset + count, buf, 0);
+ write(buf, 0, count);
+ }
+
+ public void write (String str) throws IOException
+ {
+ write(str, 0, str.length());
+ }
+
+}
diff --git a/libjava/java/io/natFile.cc b/libjava/java/io/natFile.cc
new file mode 100644
index 00000000000..40f227719e5
--- /dev/null
+++ b/libjava/java/io/natFile.cc
@@ -0,0 +1,273 @@
+// natFile.cc - Native part of File class.
+
+/* 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 <errno.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#ifdef HAVE_DIRENT_H
+#define _POSIX_PTHREAD_SEMANTICS
+#ifndef _REENTRANT
+# define _REENTRANT
+#endif
+#include <dirent.h>
+#endif
+#include <string.h>
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/io/File.h>
+#include <java/io/IOException.h>
+#include <java/util/Vector.h>
+#include <java/lang/String.h>
+#include <java/io/FilenameFilter.h>
+#include <java/lang/System.h>
+
+jboolean
+java::io::File::access (jstring canon, jint query)
+{
+ if (! canon)
+ return false;
+ char buf[MAXPATHLEN];
+ jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf);
+ // FIXME?
+ buf[total] = '\0';
+ JvAssert (query == READ || query == WRITE || query == EXISTS);
+#ifdef HAVE_ACCESS
+ int mode;
+ if (query == READ)
+ mode = R_OK;
+ else if (query == WRITE)
+ mode = W_OK;
+ else
+ mode = F_OK;
+ return ::access (buf, mode) == 0;
+#else
+ return false;
+#endif
+}
+
+jboolean
+java::io::File::stat (jstring canon, jint query)
+{
+ if (! canon)
+ return false;
+ char buf[MAXPATHLEN];
+ jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf);
+ // FIXME?
+ buf[total] = '\0';
+
+#ifdef HAVE_STAT
+ struct stat sb;
+ if (::stat (buf, &sb))
+ return false;
+
+ JvAssert (query == DIRECTORY || query == ISFILE);
+ jboolean r = S_ISDIR (sb.st_mode);
+ return query == DIRECTORY ? r : ! r;
+#else
+ return false;
+#endif
+}
+
+jlong
+java::io::File::attr (jstring canon, jint query)
+{
+ if (! canon)
+ return false;
+
+ char buf[MAXPATHLEN];
+ jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf);
+ // FIXME?
+ buf[total] = '\0';
+
+#ifdef HAVE_STAT
+ struct stat sb;
+ // FIXME: not sure about return value here.
+ if (::stat (buf, &sb))
+ return 0;
+
+ JvAssert (query == MODIFIED || query == LENGTH);
+ // FIXME: time computation is very POSIX-specific -- POSIX and Java
+ // have the same Epoch.
+ return query == MODIFIED ? sb.st_mtime * 1000 : sb.st_size;
+#else
+ // There's no good choice here.
+ return 23;
+#endif
+}
+
+jstring
+java::io::File::getCanonicalPath (void)
+{
+ char buf[MAXPATHLEN], buf2[MAXPATHLEN];
+ jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
+ // FIXME?
+ buf[total] = '\0';
+
+#ifdef HAVE_REALPATH
+ if (realpath (buf, buf2) == NULL)
+ _Jv_Throw (new IOException (JvNewStringLatin1 (strerror (errno))));
+
+ // FIXME: what encoding to assume for file names? This affects many
+ // calls.
+ return JvNewStringUTF (buf2);
+#else
+ return JvNewStringUTF (buf);
+#endif
+}
+
+jboolean
+java::io::File::isAbsolute (void)
+{
+ // FIXME: cpp define name.
+ // FIXME: cygwin.
+#ifdef WIN32
+ if (path->charAt(0) == '/' || path->charAt(0) == '\\')
+ return true;
+ if (path->length() < 3)
+ return false;
+ // Hard-code A-Za-z because Windows (I think) can't use non-ASCII
+ // letters as drive names.
+ if ((path->charAt(0) < 'a' || path->charAt(0) > 'z')
+ && (path->charAt(0) < 'A' || path->charAt(0) > 'Z'))
+ return false;
+ return (path->charAt(1) == ':'
+ && (path->charAt(2) == '/' || path->charAt(2) == '\\'));
+#else
+ return path->charAt(0) == '/';
+#endif
+}
+
+#ifdef HAVE_DIRENT_H
+#if defined(__JV_POSIX_THREADS__) && defined(HAVE_READDIR_R)
+
+static struct dirent *
+get_entry (DIR *dir, struct dirent *e)
+{
+ struct dirent *r;
+ if (readdir_r (dir, e, &r) || r == NULL)
+ return NULL;
+ return e;
+}
+
+#else /* defined(__JV_POSIX_THREADS__) && defined(HAVE_READDIR_R) */
+
+static struct dirent *
+get_entry (DIR *dir, struct dirent *)
+{
+ return readdir (dir);
+}
+
+#endif /* defined(__JV_POSIX_THREADS__) && defined(HAVE_READDIR_R) */
+#endif /* HAVE_DIRENT_H */
+
+jstringArray
+java::io::File::performList (jstring canon, FilenameFilter *filter)
+{
+ if (! canon)
+ return NULL;
+
+#ifdef HAVE_DIRENT_H
+ char buf[MAXPATHLEN];
+ jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf);
+ // FIXME?
+ buf[total] = '\0';
+
+ DIR *dir = opendir (buf);
+ if (! dir)
+ return NULL;
+
+ java::util::Vector *vec = new java::util::Vector ();
+ struct dirent *d, d2;
+ while ((d = get_entry (dir, &d2)) != NULL)
+ {
+ if (! strcmp (d->d_name, ".") || ! strcmp (d->d_name, ".."))
+ continue;
+
+ jstring name = JvNewStringUTF (d->d_name);
+ if (filter && ! filter->accept(this, name))
+ continue;
+
+ vec->addElement(name);
+ }
+
+ closedir (dir);
+
+ jobjectArray ret = JvNewObjectArray (vec->size(), canon->getClass(),
+ NULL);
+ vec->copyInto(ret);
+ return reinterpret_cast<jstringArray> (ret);
+#else /* HAVE_DIRENT_H */
+ return NULL;
+#endif /* HAVE_DIRENT_H */
+}
+
+jboolean
+java::io::File::performMkdir (void)
+{
+ char buf[MAXPATHLEN];
+ jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
+ // FIXME?
+ buf[total] = '\0';
+
+#ifdef HAVE_MKDIR
+ // FIXME: mode.
+ return ::mkdir (buf, 0755) == 0;
+#else
+ return false;
+#endif
+}
+
+jboolean
+java::io::File::performRenameTo (File *dest)
+{
+ char buf[MAXPATHLEN];
+ jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
+ // FIXME?
+ buf[total] = '\0';
+ char buf2[MAXPATHLEN];
+ total = JvGetStringUTFRegion (dest->path, 0, dest->path->length(), buf2);
+ // FIXME?
+ buf2[total] = '\0';
+
+#ifdef HAVE_RENAME
+ return ::rename (buf, buf2) == 0;
+#else
+ return false;
+#endif
+}
+
+jboolean
+java::io::File::performDelete (jstring canon)
+{
+ char buf[MAXPATHLEN];
+ jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf);
+ // FIXME?
+ buf[total] = '\0';
+
+#ifdef HAVE_UNLINK
+#ifdef HAVE_RMDIR
+ if (! ::rmdir (buf))
+ return true;
+#endif // HAVE_RMDIR
+ if (errno == ENOTDIR)
+ return ::unlink (buf) == 0;
+#endif // HAVE_UNLINK
+ return false;
+}
diff --git a/libjava/java/io/natFileDescriptorEcos.cc b/libjava/java/io/natFileDescriptorEcos.cc
new file mode 100644
index 00000000000..f2c3fb0db79
--- /dev/null
+++ b/libjava/java/io/natFileDescriptorEcos.cc
@@ -0,0 +1,132 @@
+// natFileDescriptor.cc - Native part of FileDescriptor class.
+
+/* 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 <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/io/FileDescriptor.h>
+#include <java/io/SyncFailedException.h>
+#include <java/io/IOException.h>
+#include <java/io/EOFException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/String.h>
+#include <java/io/FileNotFoundException.h>
+
+extern "C" void diag_write_char (char c);
+
+static void
+diag_write (char *data, int len)
+{
+ while (len > 0)
+ {
+ diag_write_char (*data++);
+ len--;
+ }
+}
+
+#define NO_FSYNC_MESSAGE "sync unsupported"
+
+jboolean
+java::io::FileDescriptor::valid (void)
+{
+ return true;
+}
+
+void
+java::io::FileDescriptor::sync (void)
+{
+ // Some files don't support fsync. We don't bother reporting these
+ // as errors.
+#ifdef HAVE_FSYNC
+#else
+ JvThrow (new SyncFailedException (JvNewStringLatin1 (NO_FSYNC_MESSAGE)));
+#endif
+}
+
+jint
+java::io::FileDescriptor::open (jstring path, jint jflags)
+{
+ return fd;
+}
+
+void
+java::io::FileDescriptor::write (jint b)
+{
+ char d = (char) b;
+ ::diag_write (&d, 1);
+}
+
+void
+java::io::FileDescriptor::write (jbyteArray b, jint offset, jint len)
+{
+ if (! b)
+ JvThrow (new java::lang::NullPointerException);
+ if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
+ JvThrow (new java::lang::ArrayIndexOutOfBoundsException);
+ char *bytes = (char *)elements (b) + offset;
+ ::diag_write (bytes, len);
+}
+
+void
+java::io::FileDescriptor::close (void)
+{
+}
+
+jint
+java::io::FileDescriptor::seek (jlong pos, jint whence)
+{
+ JvAssert (whence == SET || whence == CUR);
+
+ jlong len = length ();
+ jlong here = getFilePointer ();
+
+ if ((whence == SET && pos > len) || (whence == CUR && here + pos > len))
+ JvThrow (new EOFException);
+
+ return 0;
+}
+
+jlong
+java::io::FileDescriptor::length (void)
+{
+ return 0;
+}
+
+jlong
+java::io::FileDescriptor::getFilePointer (void)
+{
+ return 0;
+}
+
+jint
+java::io::FileDescriptor::read (void)
+{
+ return 0;
+}
+
+jint
+java::io::FileDescriptor::read (jbyteArray buffer, jint offset, jint count)
+{
+ return 0;
+}
+
+jint
+java::io::FileDescriptor::available (void)
+{
+ return 0;
+}
diff --git a/libjava/java/io/natFileDescriptorPosix.cc b/libjava/java/io/natFileDescriptorPosix.cc
new file mode 100644
index 00000000000..3efd8e4791b
--- /dev/null
+++ b/libjava/java/io/natFileDescriptorPosix.cc
@@ -0,0 +1,264 @@
+// natFileDescriptor.cc - Native part of FileDescriptor class.
+
+/* 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>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_IOCTL_H
+#define BSD_COMP /* Get FIONREAD on Solaris2. */
+#include <sys/ioctl.h>
+#endif
+
+// Pick up FIONREAD on Solaris 2.5.
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/io/FileDescriptor.h>
+#include <java/io/SyncFailedException.h>
+#include <java/io/IOException.h>
+#include <java/io/InterruptedIOException.h>
+#include <java/io/EOFException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/String.h>
+#include <java/lang/Thread.h>
+#include <java/io/FileNotFoundException.h>
+
+#define NO_FSYNC_MESSAGE "sync unsupported"
+
+jboolean
+java::io::FileDescriptor::valid (void)
+{
+ struct stat sb;
+ return ::fstat (fd, &sb) == 0;
+}
+
+void
+java::io::FileDescriptor::sync (void)
+{
+ // Some files don't support fsync. We don't bother reporting these
+ // as errors.
+#ifdef HAVE_FSYNC
+ if (::fsync (fd) && errno != EROFS && errno != EINVAL)
+ JvThrow (new SyncFailedException (JvNewStringLatin1 (strerror (errno))));
+#else
+ JvThrow (new SyncFailedException (JvNewStringLatin1 (NO_FSYNC_MESSAGE)));
+#endif
+}
+
+jint
+java::io::FileDescriptor::open (jstring path, jint jflags)
+{
+ // FIXME: eww.
+ char buf[MAXPATHLEN];
+ jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
+ // FIXME?
+ buf[total] = '\0';
+ int flags = 0;
+#ifdef O_BINARY
+ flags |= O_BINARY;
+#endif
+
+ JvAssert ((jflags & READ) || (jflags & WRITE));
+ if ((jflags & READ) && (jflags & WRITE))
+ flags |= O_RDWR;
+ else if ((jflags & READ))
+ flags |= O_RDONLY;
+ else
+ {
+ flags |= O_WRONLY | O_CREAT;
+ if ((jflags & APPEND))
+ flags |= O_APPEND;
+ else
+ flags |= O_TRUNC;
+ }
+
+ // FIXME: mode?
+ int fd = ::open (buf, flags, 0755);
+ if (fd == -1)
+ {
+ char msg[MAXPATHLEN + 200];
+ sprintf (msg, "%s: %s", buf, strerror (errno));
+ JvThrow (new FileNotFoundException (JvNewStringLatin1 (msg)));
+ }
+ return fd;
+}
+
+void
+java::io::FileDescriptor::write (jint b)
+{
+ jbyte d = (jbyte) b;
+ int r = ::write (fd, &d, 1);
+ if (java::lang::Thread::interrupted())
+ {
+ InterruptedIOException *iioe
+ = new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
+ iioe->bytesTransferred = r == -1 ? 0 : r;
+ JvThrow (iioe);
+ }
+ else if (r == -1)
+ JvThrow (new IOException (JvNewStringLatin1 (strerror (errno))));
+ // FIXME: loop if r != 1.
+}
+
+void
+java::io::FileDescriptor::write (jbyteArray b, jint offset, jint len)
+{
+ if (! b)
+ JvThrow (new java::lang::NullPointerException);
+ if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
+ JvThrow (new java::lang::ArrayIndexOutOfBoundsException);
+ jbyte *bytes = elements (b) + offset;
+ int r = ::write (fd, bytes, len);
+ if (java::lang::Thread::interrupted())
+ {
+ InterruptedIOException *iioe
+ = new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
+ iioe->bytesTransferred = r == -1 ? 0 : r;
+ JvThrow (iioe);
+ }
+ else if (r == -1)
+ JvThrow (new IOException (JvNewStringLatin1 (strerror (errno))));
+ // FIXME: loop if r != len.
+}
+
+void
+java::io::FileDescriptor::close (void)
+{
+ jint save = fd;
+ fd = -1;
+ if (::close (save))
+ JvThrow (new IOException (JvNewStringLatin1 (strerror (errno))));
+}
+
+jint
+java::io::FileDescriptor::seek (jlong pos, jint whence)
+{
+ JvAssert (whence == SET || whence == CUR);
+
+ jlong len = length ();
+ jlong here = getFilePointer ();
+
+ if ((whence == SET && pos > len) || (whence == CUR && here + pos > len))
+ JvThrow (new EOFException);
+
+ off_t r = ::lseek (fd, (off_t) pos, whence == SET ? SEEK_SET : SEEK_CUR);
+ if (r == -1)
+ JvThrow (new IOException (JvNewStringLatin1 (strerror (errno))));
+ return r;
+}
+
+jlong
+java::io::FileDescriptor::length (void)
+{
+ struct stat sb;
+ if (::fstat (fd, &sb))
+ JvThrow (new IOException (JvNewStringLatin1 (strerror (errno))));
+ return sb.st_size;
+}
+
+jlong
+java::io::FileDescriptor::getFilePointer (void)
+{
+ off_t r = ::lseek (fd, 0, SEEK_CUR);
+ if (r == -1)
+ JvThrow (new IOException (JvNewStringLatin1 (strerror (errno))));
+ return r;
+}
+
+jint
+java::io::FileDescriptor::read (void)
+{
+ jbyte b;
+ int r = ::read (fd, &b, 1);
+ if (r == 0)
+ return -1;
+ if (java::lang::Thread::interrupted())
+ {
+ InterruptedIOException *iioe
+ = new InterruptedIOException (JvNewStringLatin1 ("read interrupted"));
+ iioe->bytesTransferred = r == -1 ? 0 : r;
+ JvThrow (iioe);
+ }
+ else if (r == -1)
+ JvThrow (new IOException (JvNewStringLatin1 (strerror (errno))));
+ return b & 0xFF;
+}
+
+jint
+java::io::FileDescriptor::read (jbyteArray buffer, jint offset, jint count)
+{
+ if (! buffer)
+ JvThrow (new java::lang::NullPointerException);
+ jsize bsize = JvGetArrayLength (buffer);
+ if (offset < 0 || count < 0 || offset + count > bsize)
+ JvThrow (new java::lang::ArrayIndexOutOfBoundsException);
+ jbyte *bytes = elements (buffer) + offset;
+ int r = ::read (fd, bytes, count);
+ if (r == 0)
+ return -1;
+ if (java::lang::Thread::interrupted())
+ {
+ InterruptedIOException *iioe
+ = new InterruptedIOException (JvNewStringLatin1 ("read interrupted"));
+ iioe->bytesTransferred = r == -1 ? 0 : r;
+ JvThrow (iioe);
+ }
+ else if (r == -1)
+ JvThrow (new IOException (JvNewStringLatin1 (strerror (errno))));
+ return r;
+}
+
+jint
+java::io::FileDescriptor::available (void)
+{
+#if defined (FIONREAD)
+ long num;
+ int r = ::ioctl (fd, FIONREAD, &num);
+ if (r == -1)
+ JvThrow (new IOException (JvNewStringLatin1 (strerror (errno))));
+ return (jint) num;
+#elif defined (HAVE_SELECT)
+ int r = -1;
+ if (fd < 0)
+ errno = EBADF;
+ else
+ {
+ fd_set rd;
+ FD_ZERO (&rd);
+ FD_SET (fd, &rd);
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ r = ::select (fd + 1, &rd, NULL, NULL, &tv);
+ }
+ if (r == -1)
+ JvThrow (new IOException (JvNewStringLatin1 (strerror (errno))));
+ return r == 0 ? 0 : 1;
+#else
+ JvThrow (new IOException (JvNewStringLatin1 ("unimplemented")));
+#endif
+}
diff --git a/libjava/java/lang/AbstractMethodError.java b/libjava/java/lang/AbstractMethodError.java
new file mode 100644
index 00000000000..b1751e2e0f1
--- /dev/null
+++ b/libjava/java/lang/AbstractMethodError.java
@@ -0,0 +1,34 @@
+// AbstractMethodError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 AbstractMethodError extends IncompatibleClassChangeError
+{
+ public AbstractMethodError ()
+ {
+ super ();
+ }
+
+ public AbstractMethodError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/ArithmeticException.java b/libjava/java/lang/ArithmeticException.java
new file mode 100644
index 00000000000..def8c82be77
--- /dev/null
+++ b/libjava/java/lang/ArithmeticException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 ArithmeticException extends RuntimeException
+{
+ public ArithmeticException()
+ {
+ super();
+ }
+
+ public ArithmeticException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/ArrayIndexOutOfBoundsException.java b/libjava/java/lang/ArrayIndexOutOfBoundsException.java
new file mode 100644
index 00000000000..e66b6d7189b
--- /dev/null
+++ b/libjava/java/lang/ArrayIndexOutOfBoundsException.java
@@ -0,0 +1,37 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException
+{
+ public ArrayIndexOutOfBoundsException()
+ {
+ super();
+ }
+
+ public ArrayIndexOutOfBoundsException(int index)
+ {
+ this("Array index out of range: " + index);
+ }
+
+ public ArrayIndexOutOfBoundsException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/ArrayStoreException.java b/libjava/java/lang/ArrayStoreException.java
new file mode 100644
index 00000000000..7b9ede6ff25
--- /dev/null
+++ b/libjava/java/lang/ArrayStoreException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 ArrayStoreException extends RuntimeException
+{
+ public ArrayStoreException()
+ {
+ super();
+ }
+
+ public ArrayStoreException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/Boolean.java b/libjava/java/lang/Boolean.java
new file mode 100644
index 00000000000..78ab77ff81a
--- /dev/null
+++ b/libjava/java/lang/Boolean.java
@@ -0,0 +1,95 @@
+/* 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.lang;
+
+import java.io.Serializable;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 3, 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 final class Boolean extends Object implements Serializable
+{
+ public static final Boolean FALSE = new Boolean(false);
+ public static final Boolean TRUE = new Boolean(true);
+
+ // This initialization is seemingly circular, but it is accepted
+ // by javac, and is handled specially by gcc.
+ public static final Class TYPE = boolean.class;
+
+ /* The boolean value of the instance. */
+ private boolean value;
+
+ public Boolean(boolean boolVal)
+ {
+ value = boolVal;
+ }
+
+ public Boolean(String strVal)
+ {
+ value = strVal.equalsIgnoreCase("true");
+ }
+
+ public boolean booleanValue()
+ {
+ return value;
+ }
+
+ public boolean equals(Object obj)
+ {
+ /* Don't need to compare obj to null as instanceof will do this. */
+ if (obj instanceof Boolean)
+ return value == ((Boolean) obj).value;
+ return false;
+ }
+
+ public static boolean getBoolean(String property)
+ {
+ /* TBD: If a security manager exists and it doesn't permit accessing
+ * the property, it will throw an exception. Should we catch it?
+ */
+ try
+ {
+ String val = System.getProperty(property);
+ return val == null ? false : val.equalsIgnoreCase("true");
+ }
+ catch (SecurityException e)
+ {
+ return false;
+ }
+ }
+
+ public int hashCode()
+ {
+ /* These values are from the Java Lang. Spec. (Sec 20.4.7).
+ * TBD: They could be made private static final fields but they're only
+ * used here (and shouldn't be used anywhere else), though it might be
+ * useful to grep on something like JAVA_HASH_* values for us as
+ * developers.
+ */
+ return value ? 1231 : 1237;
+ }
+
+ public String toString()
+ {
+ return value ? "true" : "false";
+ }
+
+ public static Boolean valueOf(String str)
+ {
+ /* This returns a Boolean (big B), not a boolean (little b). */
+ return str.equalsIgnoreCase("true") ? TRUE : FALSE;
+ }
+}
diff --git a/libjava/java/lang/Byte.java b/libjava/java/lang/Byte.java
new file mode 100644
index 00000000000..f3ec4020671
--- /dev/null
+++ b/libjava/java/lang/Byte.java
@@ -0,0 +1,144 @@
+/* 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.lang;
+
+/**
+ * @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.
+ * Includes JDK 1.2 methods.
+ */
+
+public final class Byte extends Number implements Comparable
+{
+ byte value;
+
+ public final static byte MIN_VALUE = -128;
+ public final static byte MAX_VALUE = 127;
+
+ // This initialization is seemingly circular, but it is accepted
+ // by javac, and is handled specially by gcc.
+ public static final Class TYPE = byte.class;
+
+ public Byte(byte value)
+ {
+ this.value = value;
+ }
+
+ public Byte(String str)
+ throws NumberFormatException
+ {
+ this.value = parseByte(str, 10);
+ }
+
+ public byte byteValue()
+ {
+ return value;
+ }
+
+ public short shortValue()
+ {
+ return value;
+ }
+
+ public int intValue()
+ {
+ return value;
+ }
+
+ public long longValue ()
+ {
+ return value;
+ }
+
+ public float floatValue ()
+ {
+ return (float) value;
+ }
+
+ public double doubleValue ()
+ {
+ return (double) value;
+ }
+
+ public static Byte decode(String str)
+ throws NumberFormatException
+ {
+ int i = (Integer.decode(str)).intValue();
+ if (i < MIN_VALUE || i > MAX_VALUE)
+ throw new NumberFormatException();
+ return new Byte((byte) i);
+ }
+
+ public static byte parseByte(String str, int radix)
+ throws NumberFormatException
+ {
+ int i = Integer.parseInt(str, radix);
+ if (i < MIN_VALUE || i > MAX_VALUE)
+ throw new NumberFormatException();
+ return (byte) i;
+ }
+
+ public static byte parseByte(String str)
+ throws NumberFormatException
+ {
+ return parseByte(str, 10);
+ }
+
+ public static Byte valueOf(String str, int radix)
+ throws NumberFormatException
+ {
+ return new Byte(parseByte(str, radix));
+ }
+
+ public static Byte valueOf(String str)
+ throws NumberFormatException
+ {
+ return valueOf(str, 10);
+ }
+
+ // Added in JDK 1.2
+ public int compareTo(Byte anotherByte)
+ {
+ return this.value - anotherByte.value;
+ }
+
+ // Added in JDK 1.2
+ public int compareTo(Object o) throws ClassCastException
+ {
+ if (o instanceof Byte)
+ return this.value - ((Byte) o).value;
+ else
+ throw new ClassCastException();
+ }
+
+ public boolean equals(Object obj)
+ {
+ return obj != null && (obj instanceof Byte) && ((Byte)obj).value == value;
+ }
+
+ // Verified that hashCode is returns plain value (see Boolean_1 test).
+ public int hashCode()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ return Integer.toString((int) value);
+ }
+
+ public static String toString(byte value)
+ {
+ return Integer.toString((int) value);
+ }
+}
diff --git a/libjava/java/lang/Character.java b/libjava/java/lang/Character.java
new file mode 100644
index 00000000000..c7dd052e0c0
--- /dev/null
+++ b/libjava/java/lang/Character.java
@@ -0,0 +1,286 @@
+// Character.java - Character class.
+
+/* 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.lang;
+
+import java.io.Serializable;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date September 10, 1998
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1,
+ * online API docs for JDK 1.2 beta from http://www.javasoft.com,
+ * and The Unicode Standard Version 2.0.
+ * Status: Believed complete and correct for JDK 1.1; 1.2 methods
+ * unimplemented.
+ */
+
+public final class Character implements Serializable, Comparable
+{
+ public static final char MIN_VALUE = '\u0000';
+ public static final char MAX_VALUE = '\uffff';
+
+ public static final int MIN_RADIX = 2;
+ public static final int MAX_RADIX = 36;
+
+ // This initialization is seemingly circular, but it is accepted
+ // by javac, and is handled specially by gcc.
+ public static final Class TYPE = char.class;
+
+ // Space.
+ public static final byte SPACE_SEPARATOR = 12;
+ public static final byte LINE_SEPARATOR = 13;
+ public static final byte PARAGRAPH_SEPARATOR = 14;
+
+ // Letters.
+ public static final byte UPPERCASE_LETTER = 1;
+ public static final byte LOWERCASE_LETTER = 2;
+ public static final byte TITLECASE_LETTER = 3;
+ public static final byte MODIFIER_LETTER = 4;
+ public static final byte OTHER_LETTER = 5;
+
+ // Numbers.
+ public static final byte DECIMAL_DIGIT_NUMBER = 9;
+ public static final byte LETTER_NUMBER = 10;
+ public static final byte OTHER_NUMBER = 11;
+
+ // Marks.
+ public static final byte NON_SPACING_MARK = 6;
+ public static final byte ENCLOSING_MARK = 7;
+ public static final byte COMBINING_SPACING_MARK = 8;
+
+ // Punctuation.
+ public static final byte DASH_PUNCTUATION = 20;
+ public static final byte START_PUNCTUATION = 21;
+ public static final byte END_PUNCTUATION = 22;
+ public static final byte CONNECTOR_PUNCTUATION = 23;
+ public static final byte OTHER_PUNCTUATION = 24;
+
+ // Symbols.
+ public static final byte MATH_SYMBOL = 25;
+ public static final byte CURRENCY_SYMBOL = 26;
+ public static final byte MODIFIER_SYMBOL = 27;
+ public static final byte OTHER_SYMBOL = 28;
+
+ // Format controls.
+ public static final byte CONTROL = 15;
+ // Note: The JCL book says that both FORMAT and PRIVATE_USE are 18.
+ // However, FORMAT is actually 16.
+ public static final byte FORMAT = 16;
+
+ // Others.
+ public static final byte UNASSIGNED = 0;
+ public static final byte PRIVATE_USE = 18;
+ public static final byte SURROGATE = 19;
+
+
+ public Character (char ch)
+ {
+ value = ch;
+ }
+
+ public char charValue ()
+ {
+ return value;
+ }
+
+ // See if a character is a digit. If so, return the corresponding
+ // value. Otherwise return -1.
+ private static native int digit_value (char ch);
+
+ public static int digit (char ch, int radix)
+ {
+ if (radix < MIN_RADIX || radix > MAX_RADIX)
+ return -1;
+
+ int d = digit_value (ch);
+ if (d == -1)
+ {
+ if (ch >= 'A' && ch <= 'Z')
+ d = ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'z')
+ d = ch - 'a' + 10;
+ else
+ return -1;
+ }
+ return d >= radix ? -1 : d;
+ }
+
+ public boolean equals (Object obj)
+ {
+ // Don't need to compare OBJ to null as instanceof will do this.
+ if (obj instanceof Character)
+ return value == ((Character) obj).value;
+ return false;
+ }
+
+ public static char forDigit (int d, int rdx)
+ {
+ if (d < 0 || d >= rdx || rdx < MIN_RADIX || rdx > MAX_RADIX)
+ return '\u0000';
+ if (d < 10)
+ return (char) ('0' + d);
+ // The Java Language Spec says to use lowercase, while the JCL
+ // says to use uppercase. We go with the former.
+ return (char) ('a' + d - 10);
+ }
+
+ public static native int getNumericValue (char ch);
+ public static native int getType (char ch);
+
+ public int hashCode ()
+ {
+ return value;
+ }
+
+ public static boolean isDefined (char ch)
+ {
+ return getType (ch) != UNASSIGNED;
+ }
+
+ public static boolean isDigit (char ch)
+ {
+ return digit_value (ch) != -1;
+ }
+
+ // The JCL book says that the argument here is a Character. That is
+ // wrong.
+ public static boolean isIdentifierIgnorable (char ch)
+ {
+ // This information comes from the Unicode Standard. It isn't
+ // auto-generated as it doesn't appear in the unidata table.
+ return ((ch >= '\u0000' && ch <= '\u0008')
+ || (ch >= '\u000e' && ch <= '\u001b')
+ // JDK 1.2 docs say that these are ignorable. The Unicode
+ // Standard is somewhat ambiguous on this issue.
+ || (ch >= '\u007f' && ch <= '\u009f')
+ || (ch >= '\u200c' && ch <= '\u200f')
+ // JCl says 200a through 200e, but that is a typo. The
+ // Unicode standard says the bidi controls are 202a
+ // through 202e.
+ || (ch >= '\u202a' && ch <= '\u202e')
+ || (ch >= '\u206a' && ch <= '\u206f')
+ || ch == '\ufeff');
+ }
+
+ public static boolean isISOControl (char c)
+ {
+ return ((c >= '\u0000' && c <= '\u001f')
+ || (c >= '\u007f' && c <= '\u009f'));
+ }
+
+ public static boolean isJavaIdentifierPart (char ch)
+ {
+ if (isIdentifierIgnorable (ch) || isDigit (ch))
+ return true;
+ int type = getType (ch);
+ return (type == COMBINING_SPACING_MARK || type == NON_SPACING_MARK
+ || type == CURRENCY_SYMBOL || type == CONNECTOR_PUNCTUATION
+ || type == UPPERCASE_LETTER || type == LOWERCASE_LETTER
+ || type == TITLECASE_LETTER || type == MODIFIER_LETTER
+ || type == OTHER_LETTER || type == LETTER_NUMBER);
+ }
+
+ public static boolean isJavaIdentifierStart (char ch)
+ {
+ int type = getType (ch);
+ return (type == CURRENCY_SYMBOL || type == CONNECTOR_PUNCTUATION
+ || type == UPPERCASE_LETTER || type == LOWERCASE_LETTER
+ || type == TITLECASE_LETTER || type == MODIFIER_LETTER
+ || type == OTHER_LETTER);
+ }
+
+ // Deprecated in 1.2.
+ public static boolean isJavaLetter (char ch)
+ {
+ return ch == '$' || ch == '_' || isLetter (ch);
+ }
+
+ // Deprecated in 1.2.
+ public static boolean isJavaLetterOrDigit (char ch)
+ {
+ return ch == '$' || ch == '_' || isLetterOrDigit (ch);
+ }
+
+ public static boolean isLetter (char ch)
+ {
+ int type = getType (ch);
+ return (type == UPPERCASE_LETTER || type == LOWERCASE_LETTER
+ || type == TITLECASE_LETTER || type == MODIFIER_LETTER
+ || type == OTHER_LETTER);
+ }
+
+ public static boolean isLetterOrDigit (char ch)
+ {
+ return isDigit (ch) || isLetter (ch);
+ }
+
+ public static native boolean isLowerCase (char ch);
+
+ // Deprecated in JCL.
+ public static boolean isSpace (char ch)
+ {
+ return ch == '\n' || ch == '\t' || ch == '\f' || ch == '\r' || ch == ' ';
+ }
+
+ public static native boolean isSpaceChar (char ch);
+ public static native boolean isTitleCase (char ch);
+
+ public static boolean isUnicodeIdentifierPart (char ch)
+ {
+ if (isIdentifierIgnorable (ch) || isDigit (ch))
+ return true;
+ int type = getType (ch);
+ return (type == CONNECTOR_PUNCTUATION || type == LETTER_NUMBER
+ || type == COMBINING_SPACING_MARK || type == NON_SPACING_MARK
+ || type == UPPERCASE_LETTER || type == LOWERCASE_LETTER
+ || type == TITLECASE_LETTER || type == MODIFIER_LETTER
+ || type == OTHER_LETTER);
+ }
+
+ public static boolean isUnicodeIdentifierStart (char ch)
+ {
+ return isLetter (ch);
+ }
+
+ public static native boolean isUpperCase (char ch);
+
+ public static boolean isWhitespace (char ch)
+ {
+ return ((ch >= '\u0009' && ch <= '\r')
+ || (ch >= '\u001c' && ch <= '\u001f')
+ || (ch != '\u00a0' && ch != '\ufeff' && isSpaceChar (ch)));
+ }
+
+ public static native char toLowerCase (char ch);
+ public static native char toTitleCase (char ch);
+ public static native char toUpperCase (char ch);
+
+ public String toString ()
+ {
+ return String.valueOf(value);
+ }
+
+ public int compareTo (Character anotherCharacter)
+ {
+ return value - anotherCharacter.value;
+ }
+
+ public int compareTo (Object o)
+ {
+ return compareTo ((Character) o);
+ }
+
+ // Private data.
+ private char value;
+}
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
new file mode 100644
index 00000000000..eb0a2f95533
--- /dev/null
+++ b/libjava/java/lang/Class.h
@@ -0,0 +1,214 @@
+// Class.h - Header file for java.lang.Class. -*- 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. */
+
+// Written primary using compiler source and Class.java as guides.
+#ifndef __JAVA_LANG_CLASS_H__
+#define __JAVA_LANG_CLASS_H__
+
+#pragma interface
+
+#include <java/lang/Object.h>
+#include <java/lang/String.h>
+
+// We declare these here to avoid including cni.h.
+extern "C" void _Jv_InitClass (jclass klass);
+extern "C" void _Jv_RegisterClasses (jclass *classes);
+
+struct _Jv_Field;
+struct _Jv_VTable;
+
+#define CONSTANT_Class 7
+#define CONSTANT_Fieldref 9
+#define CONSTANT_Methodref 10
+#define CONSTANT_InterfaceMethodref 11
+#define CONSTANT_String 8
+#define CONSTANT_Integer 3
+#define CONSTANT_Float 4
+#define CONSTANT_Long 5
+#define CONSTANT_Double 6
+#define CONSTANT_NameAndType 12
+#define CONSTANT_Utf8 1
+#define CONSTANT_Unicode 2
+#define CONSTANT_ResolvedFlag 16
+#define CONSTANT_ResolvedString (CONSTANT_String+CONSTANT_ResolvedFlag)
+#define CONSTANT_ResolvedClass (CONSTANT_Class+CONSTANT_ResolvedFlag)
+
+struct _Jv_Constants
+{
+ jint size;
+ jbyte *tags;
+ void **data;
+};
+
+struct _Jv_Method
+{
+ _Jv_Utf8Const *name;
+ _Jv_Utf8Const *signature;
+ unsigned short accflags;
+ void *ncode;
+};
+
+#define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
+
+class java::lang::Class : public java::lang::Object
+{
+public:
+ static jclass forName (jstring className);
+ JArray<jclass> *getClasses (void);
+
+ java::lang::ClassLoader *getClassLoader (void)
+ {
+ return loader;
+ }
+
+ jclass getComponentType (void)
+ {
+ return isArray () ? (* (jclass *) &methods) : 0;
+ }
+
+ java::lang::reflect::Constructor *getConstructor (JArray<jclass> *);
+ JArray<java::lang::reflect::Constructor *> *getConstructors (void);
+ java::lang::reflect::Constructor *getDeclaredConstructor (JArray<jclass> *);
+ JArray<java::lang::reflect::Constructor *> *getDeclaredConstructors (void);
+ java::lang::reflect::Field *getDeclaredField (jstring);
+ JArray<java::lang::reflect::Field *> *getDeclaredFields (void);
+ java::lang::reflect::Method *getDeclaredMethod (jstring, JArray<jclass> *);
+ JArray<java::lang::reflect::Method *> *getDeclaredMethods (void);
+
+ JArray<jclass> *getDeclaredClasses (void);
+ jclass getDeclaringClass (void);
+
+ java::lang::reflect::Field *getField (jstring);
+private:
+ java::lang::reflect::Field *getField (jstring, jint);
+public:
+ JArray<java::lang::reflect::Field *> *getFields (void);
+
+ JArray<jclass> *getInterfaces (void);
+
+ java::lang::reflect::Method *getMethod (jstring, JArray<jclass> *);
+ JArray<java::lang::reflect::Method *> *getMethods (void);
+
+ jint getModifiers (void)
+ {
+ return accflags;
+ }
+
+ jstring getName (void);
+
+ java::io::InputStream *getResourceAsStream (jstring resourceName);
+ JArray<jobject> *getSigners (void);
+
+ jclass getSuperclass (void)
+ {
+ return superclass;
+ }
+
+ jboolean isArray (void)
+ {
+ return name->data[0] == '[';
+ }
+
+ jboolean isAssignableFrom (jclass cls);
+ jboolean isInstance (jobject obj);
+ jboolean isInterface (void);
+
+ jboolean isPrimitive (void)
+ {
+ return vtable == JV_PRIMITIVE_VTABLE;
+ }
+
+ jobject newInstance (void);
+ jstring toString (void);
+
+ // FIXME: this probably shouldn't be public.
+ jint size (void)
+ {
+ return size_in_bytes;
+ }
+
+private:
+ void checkMemberAccess (jint flags);
+ void resolveConstants (void);
+
+ // Various functions to handle class initialization.
+ java::lang::Throwable *hackTrampoline (jint, java::lang::Throwable *);
+ void hackRunInitializers (void);
+ void initializeClass (void);
+
+ // Friend functions implemented in natClass.cc.
+ friend _Jv_Method *_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
+ _Jv_Utf8Const *signature);
+ friend void _Jv_InitClass (jclass klass);
+ friend void _Jv_RegisterClasses (jclass *classes);
+ friend jclass _Jv_FindClassInCache (_Jv_Utf8Const *name,
+ java::lang::ClassLoader *loader);
+ friend jclass _Jv_FindArrayClass (jclass element);
+ friend jclass _Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
+ java::lang::ClassLoader *loader);
+
+ friend jfieldID JvGetFirstInstanceField (jclass);
+ friend jint JvNumInstanceFields (jclass);
+ friend jobject _Jv_AllocObject (jclass, jint);
+ friend jobjectArray _Jv_NewObjectArray (jsize, jclass, jobject);
+ friend jobject _Jv_NewPrimArray (jclass, jint);
+ friend jobject _Jv_JNI_ToReflectedField (_Jv_JNIEnv *, jclass, jfieldID);
+ friend jfieldID _Jv_FromReflectedField (java::lang::reflect::Field *);
+ friend jmethodID _Jv_FromReflectedMethod (java::lang::reflect::Method *);
+
+ friend class _Jv_PrimClass;
+
+#ifdef JV_MARKOBJ_DECL
+ friend JV_MARKOBJ_DECL;
+#endif
+
+ // Chain for class pool.
+ jclass next;
+ // Name of class.
+ _Jv_Utf8Const *name;
+ // Access flags for class.
+ unsigned short accflags;
+ // The superclass, or null for Object.
+ jclass superclass;
+ // Class constants.
+ _Jv_Constants constants;
+ // Methods. If this is an array class, then this field holds a
+ // pointer to the element type. If this is a primitive class, this
+ // is used to cache a pointer to the appropriate array type.
+ _Jv_Method *methods;
+ // Number of methods. If this class is primitive, this holds the
+ // character used to represent this type in a signature.
+ short method_count;
+ // Number of methods in the vtable.
+ short vtable_method_count;
+ // The fields.
+ _Jv_Field *fields;
+ // Size of instance fields, in bytes.
+ int size_in_bytes;
+ // Total number of fields (instance and static).
+ short field_count;
+ // Number of static fields.
+ short static_field_count;
+ // The vtbl for all objects of this class.
+ _Jv_VTable *vtable;
+ // Interfaces implemented by this class.
+ jclass *interfaces;
+ // The class loader for this class.
+ java::lang::ClassLoader *loader;
+ // Number of interfaces.
+ short interface_count;
+ // State of this class.
+ jbyte state;
+ // The thread which has locked this class. Used during class
+ // initialization.
+ java::lang::Thread *thread;
+};
+
+#endif /* __JAVA_LANG_CLASS_H__ */
diff --git a/libjava/java/lang/Class.java b/libjava/java/lang/Class.java
new file mode 100644
index 00000000000..4ffcceaf675
--- /dev/null
+++ b/libjava/java/lang/Class.java
@@ -0,0 +1,155 @@
+// Class.java - Representation of a Java class.
+
+/* 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.lang;
+import java.io.Serializable;
+import java.io.InputStream;
+import java.lang.reflect.*;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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.
+ * plus gcj compiler sources (to determine object layout)
+ * Status: Sufficient for our purposes, but some methods missing
+ * and some not implemented.
+ */
+
+public final class Class implements Serializable
+{
+ public static native Class forName (String className)
+ throws ClassNotFoundException;
+ public native Class[] getClasses ();
+ public native ClassLoader getClassLoader ();
+ public native Class getComponentType ();
+
+ public native Constructor getConstructor (Class[] parameterTypes)
+ throws NoSuchMethodException, SecurityException;
+ public native Constructor[] getConstructors () throws SecurityException;
+
+ public native Class[] getDeclaredClasses () throws SecurityException;
+
+ public native Constructor getDeclaredConstructor (Class[] parameterTypes)
+ throws NoSuchMethodException, SecurityException;
+ public native Constructor[] getDeclaredConstructors ()
+ throws SecurityException;
+ public native Field getDeclaredField (String fieldName)
+ throws NoSuchFieldException, SecurityException;
+ public native Field[] getDeclaredFields () throws SecurityException;
+ public native Method getDeclaredMethod (String methodName,
+ Class[] parameterTypes)
+ throws NoSuchMethodException, SecurityException;
+ public native Method[] getDeclaredMethods () throws SecurityException;
+
+ // This is marked as unimplemented in the JCL book.
+ public native Class getDeclaringClass ();
+
+ private native Field getField (String fieldName, int hash)
+ throws NoSuchFieldException, SecurityException;
+
+ public Field getField (String fieldName)
+ throws NoSuchFieldException, SecurityException
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkMemberAccess (this, java.lang.reflect.Member.DECLARED);
+ Field fld = getField(fieldName, fieldName.hashCode());
+ if (fld == null)
+ throw new NoSuchFieldException(fieldName);
+ return fld;
+ }
+ public native Field[] getFields () throws SecurityException;
+
+ public native Class[] getInterfaces ();
+
+ public native Method getMethod (String methodName, Class[] parameterTypes)
+ throws NoSuchMethodException, SecurityException;
+ public native Method[] getMethods () throws SecurityException;
+
+ public native int getModifiers ();
+ public native String getName ();
+
+ // FIXME: can't implement this until we have java.net.
+ // public URL getResource (String resourceName);
+
+ // FIXME: implement.
+ public InputStream getResourceAsStream (String resourceName)
+ {
+ return null;
+ }
+
+ // FIXME: implement. Requires java.security.
+ public Object[] getSigners ()
+ {
+ return null;
+ }
+
+ public native Class getSuperclass ();
+ public native boolean isArray ();
+ public native boolean isAssignableFrom (Class cls);
+ public native boolean isInstance (Object obj);
+ public native boolean isInterface ();
+ public native boolean isPrimitive ();
+ public native Object newInstance ()
+ throws InstantiationException, IllegalAccessException;
+
+ public String toString ()
+ {
+ if (isPrimitive ())
+ return getName ();
+ return (isInterface () ? "interface " : "class ") + getName ();
+ }
+
+ // Don't allow new classes to be made.
+ private Class ()
+ {
+ }
+
+ // Do a security check.
+ private void checkMemberAccess (int flags)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkMemberAccess(this, flags);
+ }
+
+ // FIXME: this method exists only because we cannot catch Java
+ // exceptions from C++ code. This is a helper for initializeClass.
+ private Throwable hackTrampoline (int what, Throwable old_exception)
+ {
+ Throwable new_val = null;
+ try
+ {
+ if (what == 0)
+ initializeClass ();
+ else if (what == 1)
+ hackRunInitializers ();
+ else if (what == 2)
+ new_val = new ExceptionInInitializerError (old_exception);
+ }
+ catch (Throwable t)
+ {
+ new_val = t;
+ }
+ return new_val;
+ }
+
+ // FIXME: this is a hack to let us run the class initializers. We
+ // could do it inline in initializeClass() if we could catch Java
+ // exceptions from C++.
+ private native void hackRunInitializers ();
+
+ // Initialize the class.
+ private native void initializeClass ();
+}
diff --git a/libjava/java/lang/ClassCastException.java b/libjava/java/lang/ClassCastException.java
new file mode 100644
index 00000000000..bd5a2a49b8e
--- /dev/null
+++ b/libjava/java/lang/ClassCastException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 ClassCastException extends RuntimeException
+{
+ public ClassCastException()
+ {
+ super();
+ }
+
+ public ClassCastException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/ClassCircularityError.java b/libjava/java/lang/ClassCircularityError.java
new file mode 100644
index 00000000000..a5e03831805
--- /dev/null
+++ b/libjava/java/lang/ClassCircularityError.java
@@ -0,0 +1,34 @@
+// ClassCircularityError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 ClassCircularityError extends LinkageError
+{
+ public ClassCircularityError ()
+ {
+ super ();
+ }
+
+ public ClassCircularityError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/ClassFormatError.java b/libjava/java/lang/ClassFormatError.java
new file mode 100644
index 00000000000..99b8425c9be
--- /dev/null
+++ b/libjava/java/lang/ClassFormatError.java
@@ -0,0 +1,34 @@
+// ClassFormatError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 ClassFormatError extends LinkageError
+{
+ public ClassFormatError ()
+ {
+ super ();
+ }
+
+ public ClassFormatError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/ClassLoader.java b/libjava/java/lang/ClassLoader.java
new file mode 100644
index 00000000000..048cea7d883
--- /dev/null
+++ b/libjava/java/lang/ClassLoader.java
@@ -0,0 +1,94 @@
+// ClassLoader.java - Define policies for loading Java classes.
+
+/* 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.lang;
+import java.io.InputStream;
+import java.util.Hashtable;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 28, 1998
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * Status: Just a stub; not useful at all.
+ */
+
+public abstract class ClassLoader
+{
+ protected ClassLoader ()
+ {
+ cache = new Hashtable ();
+ }
+
+ protected final Class defineClass (String className, byte[] bytecode,
+ int offset, int length)
+ {
+ throw new ClassFormatError ("defineClass unimplemented");
+ }
+
+ protected final Class defineClass (byte[] bytecodes,
+ int offset, int length)
+ {
+ return defineClass (null, bytecodes, offset, length);
+ }
+
+ protected final Class findLoadedClass (String className)
+ {
+ return (Class) cache.get(className);
+ }
+
+ protected final Class findSystemClass (String className)
+ throws ClassNotFoundException
+ {
+ Class c = system.findLoadedClass(className);
+ system.resolveClass(c);
+ return c;
+ }
+
+ // FIXME: Needs URL.
+ // public URL getResource (String resName);
+
+ public InputStream getResourceAsStream (String resName)
+ {
+ return null;
+ }
+
+ // FIXME: Needs URL.
+ // public static final URL getSystemResource (String resName);
+
+ public static final InputStream getSystemResourceAsStream (String resName)
+ {
+ return null;
+ }
+
+ protected abstract Class loadClass (String className, boolean resolve)
+ throws ClassNotFoundException;
+ public Class loadClass (String name) throws ClassNotFoundException
+ {
+ return loadClass (name, true);
+ }
+
+ protected final void resolveClass (Class c)
+ {
+ // Nothing for now.
+ }
+
+ protected final void setSigners (Class cl, Object[] signers)
+ {
+ // Nothing for now.
+ }
+
+ // Class cache.
+ private Hashtable cache;
+
+ // The system class loader. FIXME: should have an actual value
+ private static final ClassLoader system = null;
+}
diff --git a/libjava/java/lang/ClassNotFoundException.java b/libjava/java/lang/ClassNotFoundException.java
new file mode 100644
index 00000000000..e0ea15e22a2
--- /dev/null
+++ b/libjava/java/lang/ClassNotFoundException.java
@@ -0,0 +1,57 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 ClassNotFoundException extends Exception
+{
+ public ClassNotFoundException()
+ {
+ super();
+ }
+
+ // TODO12:
+ // public ClassNotFoundException(String msg, Throwable ex)
+ // {
+ // }
+
+ public ClassNotFoundException(String msg)
+ {
+ super(msg);
+ }
+
+ // TODO12:
+ // public Throwable getException()
+ // {
+ // }
+
+ // TBD: if this needs to be implemented
+ // public void printStackTrace()
+ // {
+ // }
+
+ // TBD: if this needs to be implemented
+ // public void printStackTrace(PrintStream ps)
+ // {
+ // }
+
+ // TBD: if this needs to be implemented
+ // public void printStackTrace(PrintWriter pw)
+ // {
+ // }
+}
diff --git a/libjava/java/lang/CloneNotSupportedException.java b/libjava/java/lang/CloneNotSupportedException.java
new file mode 100644
index 00000000000..155e80481a9
--- /dev/null
+++ b/libjava/java/lang/CloneNotSupportedException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 CloneNotSupportedException extends Exception
+{
+ public CloneNotSupportedException()
+ {
+ super();
+ }
+
+ public CloneNotSupportedException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/Cloneable.java b/libjava/java/lang/Cloneable.java
new file mode 100644
index 00000000000..730e5c91b5f
--- /dev/null
+++ b/libjava/java/lang/Cloneable.java
@@ -0,0 +1,23 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 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 Cloneable
+{
+}
diff --git a/libjava/java/lang/Comparable.java b/libjava/java/lang/Comparable.java
new file mode 100644
index 00000000000..e40e6e81ae8
--- /dev/null
+++ b/libjava/java/lang/Comparable.java
@@ -0,0 +1,22 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 8, 1998.
+ */
+/* Written using online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+public interface Comparable
+{
+ public int compareTo(Object o) throws ClassCastException;
+}
diff --git a/libjava/java/lang/Compiler.java b/libjava/java/lang/Compiler.java
new file mode 100644
index 00000000000..7feb9f86429
--- /dev/null
+++ b/libjava/java/lang/Compiler.java
@@ -0,0 +1,53 @@
+// Compiler.java - Control byte->machine code compiler.
+
+/* 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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 23, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ */
+
+public final class Compiler
+{
+ public static Object command (Object arg)
+ {
+ // Our implementation defines this to a no-op.
+ return null;
+ }
+
+ public static boolean compileClass (Class oneClass)
+ {
+ // Never succeed.
+ return false;
+ }
+
+ public static boolean compileClasses (String classNames)
+ {
+ // Note the incredibly lame interface. Always fail.
+ return false;
+ }
+
+ public static void disable ()
+ {
+ }
+
+ public static void enable ()
+ {
+ }
+
+ // Don't allow new `Compiler's to be made.
+ private Compiler ()
+ {
+ }
+}
diff --git a/libjava/java/lang/Double.java b/libjava/java/lang/Double.java
new file mode 100644
index 00000000000..850aa5ad979
--- /dev/null
+++ b/libjava/java/lang/Double.java
@@ -0,0 +1,149 @@
+/* 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.lang;
+
+/**
+ * @author Andrew Haley <aph@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
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+public final class Double extends Number
+{
+ public static final double MIN_VALUE = 5e-324;
+ public static final double MAX_VALUE = 1.7976931348623157e+308;
+ public static final double NEGATIVE_INFINITY = -1.0d/0.0d;
+ public static final double POSITIVE_INFINITY = 1.0d/0.0d;
+ public static final double NaN = 0.0d/0.0d;
+
+ // This initialization is seemingly circular, but it is accepted
+ // by javac, and is handled specially by gcc.
+ public static final Class TYPE = double.class;
+
+ private double value;
+
+ private native static double doubleValueOf (String s)
+ throws NumberFormatException;
+
+ public Double (double v)
+ {
+ value = v;
+ }
+
+ public Double (String s) throws NumberFormatException
+ {
+ value = valueOf (s).doubleValue ();
+ }
+
+ public String toString ()
+ {
+ return toString (value);
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (obj == null)
+ return false;
+
+ if (!(obj instanceof Double))
+ return false;
+
+ Double d = (Double) obj;
+
+ return doubleToLongBits (value) == doubleToLongBits (d.doubleValue ());
+ }
+
+ public int hashCode ()
+ {
+ long v = doubleToLongBits (value);
+ return (int) (v ^ (v >>> 32));
+ }
+
+ public int intValue ()
+ {
+ return (int) value;
+ }
+
+ public long longValue ()
+ {
+ return (long) value;
+ }
+
+ public float floatValue ()
+ {
+ return (float) value;
+ }
+
+ public double doubleValue ()
+ {
+ return value;
+ }
+
+ public byte byteValue ()
+ {
+ return (byte) value;
+ }
+
+ public short shortValue ()
+ {
+ return (short) value;
+ }
+
+ native static String toString (double v, boolean isFloat);
+
+ public static String toString (double v)
+ {
+ return toString (v, false);
+ }
+
+ public static Double valueOf (String s) throws NullPointerException,
+ NumberFormatException
+ {
+ if (s == null)
+ throw new NullPointerException ();
+
+ return new Double (doubleValueOf (s));
+ }
+
+ public boolean isNaN ()
+ {
+ return isNaN (value);
+ }
+
+ public static boolean isNaN (double v)
+ {
+ long bits = doubleToLongBits (v);
+ long e = bits & 0x7ff0000000000000L;
+ long f = bits & 0x000fffffffffffffL;
+
+ return e == 0x7ff0000000000000L && f != 0L;
+ }
+
+ public boolean isInfinite ()
+ {
+ return isInfinite (value);
+ }
+
+ public static boolean isInfinite (double v)
+ {
+ long bits = doubleToLongBits (v);
+ long f = bits & 0x7fffffffffffffffL;
+
+ return f == 0x7ff0000000000000L;
+ }
+
+ public static native long doubleToLongBits (double value);
+
+ public static native double longBitsToDouble (long bits);
+}
+
diff --git a/libjava/java/lang/Error.java b/libjava/java/lang/Error.java
new file mode 100644
index 00000000000..ef69f0ea413
--- /dev/null
+++ b/libjava/java/lang/Error.java
@@ -0,0 +1,34 @@
+// Error.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 Error extends Throwable
+{
+ public Error ()
+ {
+ super ();
+ }
+
+ public Error (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/Exception.java b/libjava/java/lang/Exception.java
new file mode 100644
index 00000000000..8eb5e44dc36
--- /dev/null
+++ b/libjava/java/lang/Exception.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 Exception extends Throwable
+{
+ public Exception()
+ {
+ super();
+ }
+
+ public Exception(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/ExceptionInInitializerError.java b/libjava/java/lang/ExceptionInInitializerError.java
new file mode 100644
index 00000000000..deb1213e3b2
--- /dev/null
+++ b/libjava/java/lang/ExceptionInInitializerError.java
@@ -0,0 +1,50 @@
+// ExceptionInInitializerError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 ExceptionInInitializerError extends LinkageError
+{
+ public ExceptionInInitializerError ()
+ {
+ super ();
+ exception = null;
+ }
+
+ public ExceptionInInitializerError (String msg)
+ {
+ super (msg);
+ exception = null;
+ }
+
+ public ExceptionInInitializerError (Throwable e)
+ {
+ super ();
+ exception = e;
+ }
+
+ public Throwable getException ()
+ {
+ return exception;
+ }
+
+ // The exception that caused this error.
+ private Throwable exception;
+}
diff --git a/libjava/java/lang/FirstThread.java b/libjava/java/lang/FirstThread.java
new file mode 100644
index 00000000000..ec0f1db33d5
--- /dev/null
+++ b/libjava/java/lang/FirstThread.java
@@ -0,0 +1,40 @@
+// FirstThread.java - Implementation of very first thread.
+
+/* 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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date August 24, 1998
+ */
+
+// This is entirely internal to our implementation.
+
+final class FirstThread extends Thread
+{
+ public native void run ();
+
+ public FirstThread (ThreadGroup g, Class k, Object o)
+ {
+ super (g, null, "main");
+ klass = k;
+ args = o;
+ }
+
+ private static void die (String s)
+ {
+ System.err.println(s);
+ System.exit(1);
+ }
+
+ // Private data.
+ private Class klass;
+ private Object args;
+}
diff --git a/libjava/java/lang/Float.java b/libjava/java/lang/Float.java
new file mode 100644
index 00000000000..99cc66bc8e7
--- /dev/null
+++ b/libjava/java/lang/Float.java
@@ -0,0 +1,149 @@
+/* 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.lang;
+
+/**
+ * @author Andrew Haley <aph@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
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+public final class Float extends Number
+{
+ public static final float MAX_VALUE = 3.4028235e+38f;
+ public static final float MIN_VALUE = 1.4e-45f;
+ public static final float NEGATIVE_INFINITY = -1.0f/0.0f;
+ public static final float POSITIVE_INFINITY = 1.0f/0.0f;
+ public static final float NaN = 0.0f/0.0f;
+
+ // This initialization is seemingly circular, but it is accepted
+ // by javac, and is handled specially by gcc.
+ public static final Class TYPE = float.class;
+
+ private float value;
+
+ public Float (float value)
+ {
+ this.value = value;
+ }
+
+ public Float (double value)
+ {
+ this.value = (float)value;
+ }
+
+ public Float (String s) throws NumberFormatException
+ {
+ this.value = valueOf (s).floatValue ();
+ }
+
+ public String toString ()
+ {
+ return toString (value);
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (obj == null)
+ return false;
+
+ if (!(obj instanceof Float))
+ return false;
+
+ Float f = (Float) obj;
+
+ return floatToIntBits (value) == floatToIntBits (f.floatValue ());
+ }
+
+ public int hashCode ()
+ {
+ return floatToIntBits (value);
+ }
+
+ public int intValue ()
+ {
+ return (int) value;
+ }
+
+ public long longValue ()
+ {
+ return (long) value;
+ }
+
+ public float floatValue ()
+ {
+ return (float) value;
+ }
+
+ public double doubleValue ()
+ {
+ return (double) value;
+ }
+
+ public byte byteValue ()
+ {
+ return (byte) value;
+ }
+
+ public short shortValue ()
+ {
+ return (short) value;
+ }
+
+ public static String toString (float v)
+ {
+ return Double.toString ((double) v, true);
+ }
+
+ public static Float valueOf (String s) throws NullPointerException,
+ NumberFormatException
+ {
+ if (s == null)
+ throw new NullPointerException ();
+
+ return new Float (Double.valueOf (s).floatValue ());
+ }
+
+ public boolean isNaN ()
+ {
+ return isNaN (value);
+ }
+
+ public static boolean isNaN (float v)
+ {
+ int bits = floatToIntBits (v);
+ int e = bits & 0x7f800000;
+ int f = bits & 0x007fffff;
+
+ return e == 0x7f800000 && f != 0;
+ }
+
+ public boolean isInfinite ()
+ {
+ return isInfinite (value);
+ }
+
+ public static boolean isInfinite (float v)
+ {
+ int bits = floatToIntBits (v);
+ int f = bits & 0x7fffffff;
+
+ return f == 0x7f800000;
+ }
+
+ public static native int floatToIntBits (float value);
+
+ public static native float intBitsToFloat (int bits);
+
+}
+
diff --git a/libjava/java/lang/IllegalAccessError.java b/libjava/java/lang/IllegalAccessError.java
new file mode 100644
index 00000000000..2d863416eb5
--- /dev/null
+++ b/libjava/java/lang/IllegalAccessError.java
@@ -0,0 +1,34 @@
+// IllegalAccessError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 IllegalAccessError extends IncompatibleClassChangeError
+{
+ public IllegalAccessError ()
+ {
+ super ();
+ }
+
+ public IllegalAccessError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/IllegalAccessException.java b/libjava/java/lang/IllegalAccessException.java
new file mode 100644
index 00000000000..c07a518779a
--- /dev/null
+++ b/libjava/java/lang/IllegalAccessException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 IllegalAccessException extends Exception
+{
+ public IllegalAccessException()
+ {
+ super();
+ }
+
+ public IllegalAccessException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/IllegalArgumentException.java b/libjava/java/lang/IllegalArgumentException.java
new file mode 100644
index 00000000000..6e8f0ed0300
--- /dev/null
+++ b/libjava/java/lang/IllegalArgumentException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 IllegalArgumentException extends RuntimeException
+{
+ public IllegalArgumentException()
+ {
+ super();
+ }
+
+ public IllegalArgumentException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/IllegalMonitorStateException.java b/libjava/java/lang/IllegalMonitorStateException.java
new file mode 100644
index 00000000000..f431749ca5f
--- /dev/null
+++ b/libjava/java/lang/IllegalMonitorStateException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 IllegalMonitorStateException extends RuntimeException
+{
+ public IllegalMonitorStateException()
+ {
+ super();
+ }
+
+ public IllegalMonitorStateException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/IllegalStateException.java b/libjava/java/lang/IllegalStateException.java
new file mode 100644
index 00000000000..2ea0d02b62b
--- /dev/null
+++ b/libjava/java/lang/IllegalStateException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 IllegalStateException extends RuntimeException
+{
+ public IllegalStateException()
+ {
+ super();
+ }
+
+ public IllegalStateException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/IllegalThreadStateException.java b/libjava/java/lang/IllegalThreadStateException.java
new file mode 100644
index 00000000000..72afa771ede
--- /dev/null
+++ b/libjava/java/lang/IllegalThreadStateException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 IllegalThreadStateException extends IllegalArgumentException
+{
+ public IllegalThreadStateException()
+ {
+ super();
+ }
+
+ public IllegalThreadStateException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/IncompatibleClassChangeError.java b/libjava/java/lang/IncompatibleClassChangeError.java
new file mode 100644
index 00000000000..31a22c46175
--- /dev/null
+++ b/libjava/java/lang/IncompatibleClassChangeError.java
@@ -0,0 +1,34 @@
+// IncompatibleClassChangeError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 IncompatibleClassChangeError extends LinkageError
+{
+ public IncompatibleClassChangeError ()
+ {
+ super ();
+ }
+
+ public IncompatibleClassChangeError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/IndexOutOfBoundsException.java b/libjava/java/lang/IndexOutOfBoundsException.java
new file mode 100644
index 00000000000..c8b5878b3d8
--- /dev/null
+++ b/libjava/java/lang/IndexOutOfBoundsException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 IndexOutOfBoundsException extends RuntimeException
+{
+ public IndexOutOfBoundsException()
+ {
+ super();
+ }
+
+ public IndexOutOfBoundsException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/InstantiationError.java b/libjava/java/lang/InstantiationError.java
new file mode 100644
index 00000000000..7982615e8f6
--- /dev/null
+++ b/libjava/java/lang/InstantiationError.java
@@ -0,0 +1,34 @@
+// InstantiationError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 InstantiationError extends IncompatibleClassChangeError
+{
+ public InstantiationError ()
+ {
+ super ();
+ }
+
+ public InstantiationError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/InstantiationException.java b/libjava/java/lang/InstantiationException.java
new file mode 100644
index 00000000000..d5ca893fe02
--- /dev/null
+++ b/libjava/java/lang/InstantiationException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 InstantiationException extends Exception
+{
+ public InstantiationException()
+ {
+ super();
+ }
+
+ public InstantiationException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/Integer.java b/libjava/java/lang/Integer.java
new file mode 100644
index 00000000000..54acc27ed6b
--- /dev/null
+++ b/libjava/java/lang/Integer.java
@@ -0,0 +1,355 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 11, 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 final class Integer extends Number implements Comparable
+{
+ public static final int MAX_VALUE = 0x7FFFFFFF;
+ public static final int MIN_VALUE = 0x80000000;
+
+ // This initialization is seemingly circular, but it is accepted
+ // by javac, and is handled specially by gcc.
+ public static final Class TYPE = int.class;
+
+ /* The int value of the instance. */
+ private int value;
+
+ public Integer(int val)
+ {
+ value = val;
+ }
+
+ public Integer(String str) throws NumberFormatException
+ {
+ value = parseInt(str, 10);
+ }
+
+ public byte byteValue()
+ {
+ return (byte) value;
+ }
+
+ public double doubleValue()
+ {
+ return (double) value;
+ }
+
+ public float floatValue()
+ {
+ return (float) value;
+ }
+
+ public int intValue()
+ {
+ return value;
+ }
+
+ public long longValue()
+ {
+ return value;
+ }
+
+ public short shortValue()
+ {
+ return (short) value;
+ }
+
+ // Added in JDK 1.2
+ public int compareTo(Integer anotherInteger)
+ {
+ if (this.value == anotherInteger.value)
+ return 0;
+
+ // Returns just -1 or 1 on inequality; doing math might overflow the int.
+ if (this.value > anotherInteger.value)
+ return 1;
+
+ return -1;
+ }
+
+ // Added in JDK 1.2
+ public int compareTo(Object o) throws ClassCastException
+ {
+ if (!(o instanceof Integer))
+ throw new ClassCastException();
+
+ return this.compareTo((Integer) o);
+ }
+
+ public static Integer decode(String str) throws NumberFormatException
+ {
+ boolean isNeg = false;
+ int index = 0;
+ int radix = 10;
+ final int len;
+
+ if (str == null || (len = str.length()) == 0)
+ throw new NumberFormatException();
+
+ // Negative numbers are always radix 10.
+ if (str.charAt(0) == '-')
+ {
+ radix = 10;
+ index++;
+ isNeg = true;
+ }
+ else if (str.charAt(index) == '#')
+ {
+ radix = 16;
+ index++;
+ }
+ else if (str.charAt(index) == '0')
+ {
+ // Check if str is just "0"
+ if (len == 1)
+ return new Integer(0);
+
+ index++;
+ if (str.charAt(index) == 'x')
+ {
+ radix = 16;
+ index++;
+ }
+ else
+ radix = 8;
+ }
+
+ if (index >= len)
+ throw new NumberFormatException();
+
+ return new Integer(parseInt(str, index, len, isNeg, radix));
+ }
+
+ public boolean equals(Object obj)
+ {
+ return (obj != null && (obj instanceof Integer)
+ && ((Integer) obj).value == value);
+ }
+
+ public static Integer getInteger(String prop)
+ {
+ return getInteger(prop, null);
+ }
+
+ public static Integer getInteger(String prop, int defval)
+ {
+ Integer val = getInteger(prop, null);
+ return val == null ? new Integer(defval) : val;
+ }
+
+ public static Integer getInteger(String prop, Integer defobj)
+ {
+ try
+ {
+ return decode(System.getProperty(prop));
+ }
+ catch (NumberFormatException ex)
+ {
+ return defobj;
+ }
+ }
+
+ public int hashCode()
+ {
+ return value;
+ }
+
+ public static int parseInt(String str) throws NumberFormatException
+ {
+ return parseInt(str, 10);
+ }
+
+ public static int parseInt(String str, int radix) throws NumberFormatException
+ {
+ final int len;
+
+ if (str == null || (len = str.length()) == 0 ||
+ radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
+ throw new NumberFormatException();
+
+ boolean isNeg = false;
+ int index = 0;
+ if (str.charAt(index) == '-')
+ if (len > 1)
+ {
+ isNeg = true;
+ index++;
+ }
+ else
+ throw new NumberFormatException();
+
+ return parseInt(str, index, len, isNeg, radix);
+ }
+
+ private static int parseInt(String str, int index, int len, boolean isNeg,
+ int radix) throws NumberFormatException
+ {
+ int val = 0;
+ int digval;
+
+ for ( ; index < len; index++)
+ {
+ // The the previous loop iteration left us with a negative
+ // value (which can only be the most negative value, but we
+ // don't check that), then having more digits is wrong.
+ if (val == MIN_VALUE)
+ throw new NumberFormatException();
+
+ if ((digval = Character.digit(str.charAt(index), radix)) < 0)
+ throw new NumberFormatException();
+
+ // Throw an exception for overflow if result is negative.
+ // However, we special-case the most negative value.
+ val *= radix;
+ if (val < 0 || val + digval < 0)
+ {
+ if (isNeg && val + digval == MIN_VALUE)
+ {
+ // Ok.
+ }
+ else
+ throw new NumberFormatException();
+ }
+ val += digval;
+ }
+
+ return isNeg ? -(val) : val;
+ }
+
+ public static String toBinaryString(int num)
+ {
+ return toUnsignedString(num, 1);
+ }
+
+ public static String toHexString(int num)
+ {
+ return toUnsignedString(num, 4);
+ }
+
+ public static String toOctalString(int num)
+ {
+ return toUnsignedString(num, 3);
+ }
+
+ private static String toUnsignedString(int num, int exp)
+ {
+ // Use an array large enough for a binary number.
+ int radix = 1 << exp;
+ int mask = radix - 1;
+ char[] buffer = new char[32];
+ int i = 32;
+ do
+ {
+ buffer[--i] = Character.forDigit(num & mask, radix);
+ num = num >>> exp;
+ }
+ while (num != 0);
+
+ return String.valueOf(buffer, i, 32-i);
+ }
+
+ public String toString()
+ {
+ return toString(this.value);
+ }
+
+ public static String toString(int num)
+ {
+ // Use an arrary large enough for "-2147483648"; i.e. 11 chars.
+ char[] buffer = new char[11];
+ int i = 11;
+ boolean isNeg;
+ if (num < 0)
+ {
+ isNeg = true;
+ num = -(num);
+ if (num < 0)
+ {
+ // Must be MIN_VALUE, so handle this special case.
+ buffer[--i] = '8';
+ num = 214748364;
+ }
+ }
+ else
+ isNeg = false;
+
+ do
+ {
+ buffer[--i] = (char) ((int) '0' + (num % 10));
+ num /= 10;
+ }
+ while (num > 0);
+
+ if (isNeg)
+ buffer[--i] = '-';
+
+ return String.valueOf(buffer, i, 11-i);
+ }
+
+ public static String toString(int num, int radix)
+ {
+ // Use optimized method for the typical case.
+ if (radix == 10 ||
+ radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
+ return toString(num);
+
+ // For negative numbers, print out the absolute value w/ a leading '-'.
+ // Use an array large enough for a binary number.
+ char[] buffer = new char[33];
+ int i = 33;
+ boolean isNeg;
+ if (num < 0)
+ {
+ isNeg = true;
+ num = -(num);
+
+ // When the value is MIN_VALUE, it overflows when made positive
+ if (num < 0)
+ {
+ buffer[--i] = Character.forDigit(-(num + radix) % radix, radix);
+ num = -(num / radix);
+ }
+ }
+ else
+ isNeg = false;
+
+ do
+ {
+ buffer[--i] = Character.forDigit(num % radix, radix);
+ num /= radix;
+ }
+ while (num > 0);
+
+ if (isNeg)
+ buffer[--i] = '-';
+
+ return String.valueOf(buffer, i, 33-i);
+ }
+
+ public static Integer valueOf(String str) throws NumberFormatException
+ {
+ return new Integer(parseInt(str, 10));
+ }
+
+ public static Integer valueOf(String str, int radix)
+ throws NumberFormatException
+ {
+ return new Integer(parseInt(str, radix));
+ }
+}
diff --git a/libjava/java/lang/InternalError.java b/libjava/java/lang/InternalError.java
new file mode 100644
index 00000000000..6e484cfa6d0
--- /dev/null
+++ b/libjava/java/lang/InternalError.java
@@ -0,0 +1,34 @@
+// InternalError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 InternalError extends VirtualMachineError
+{
+ public InternalError ()
+ {
+ super ();
+ }
+
+ public InternalError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/InterruptedException.java b/libjava/java/lang/InterruptedException.java
new file mode 100644
index 00000000000..ef2e9b3adaf
--- /dev/null
+++ b/libjava/java/lang/InterruptedException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 InterruptedException extends Exception
+{
+ public InterruptedException()
+ {
+ super();
+ }
+
+ public InterruptedException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/LinkageError.java b/libjava/java/lang/LinkageError.java
new file mode 100644
index 00000000000..c9386a7c3c1
--- /dev/null
+++ b/libjava/java/lang/LinkageError.java
@@ -0,0 +1,34 @@
+// LinkageError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 LinkageError extends Error
+{
+ public LinkageError ()
+ {
+ super ();
+ }
+
+ public LinkageError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/Long.java b/libjava/java/lang/Long.java
new file mode 100644
index 00000000000..1ee8bf36277
--- /dev/null
+++ b/libjava/java/lang/Long.java
@@ -0,0 +1,366 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 final class Long extends Number implements Comparable
+{
+ public static final long MAX_VALUE = 0x7FFFFFFFFFFFFFFFL;
+ public static final long MIN_VALUE = 0x8000000000000000L;
+
+ // This initialization is seemingly circular, but it is accepted
+ // by javac, and is handled specially by gcc.
+ public static final Class TYPE = long.class;
+
+ /* The long value of the instance. */
+ private long value;
+
+ public Long(long val)
+ {
+ value = val;
+ }
+
+ public Long(String str) throws NumberFormatException
+ {
+ value = parseLong(str, 10);
+ }
+
+ public byte byteValue()
+ {
+ return (byte) value;
+ }
+
+ public double doubleValue()
+ {
+ return (double) value;
+ }
+
+ public float floatValue()
+ {
+ return (float) value;
+ }
+
+ public int intValue()
+ {
+ return (int) value;
+ }
+
+ public long longValue()
+ {
+ return value;
+ }
+
+ public short shortValue()
+ {
+ return (short) value;
+ }
+
+ // Added in JDK 1.2
+ public int compareTo(Long anotherLong)
+ {
+ if (this.value == anotherLong.value)
+ return 0;
+
+ // Returns just -1 or 1 on inequality; doing math might overflow the long.
+ if (this.value > anotherLong.value)
+ return 1;
+
+ return -1;
+ }
+
+ // Added in JDK 1.2
+ public int compareTo(Object o) throws ClassCastException
+ {
+ if (!(o instanceof Long))
+ throw new ClassCastException();
+
+ return this.compareTo((Long) o);
+ }
+
+ // Added in JDK 1.2
+ public static Long decode(String str) throws NumberFormatException
+ {
+ boolean isNeg = false;
+ int index = 0;
+ int radix = 10;
+ final int len;
+
+ if (str == null || (len = str.length()) == 0)
+ throw new NumberFormatException();
+
+ // Negative numbers are always radix 10.
+ if (str.charAt(0) == '-')
+ {
+ radix = 10;
+ index++;
+ isNeg = true;
+ }
+ else if (str.charAt(index) == '#')
+ {
+ radix = 16;
+ index++;
+ }
+ else if (str.charAt(index) == '0')
+ {
+ // Check if str is just "0"
+ if (len == 1)
+ return new Long(0L);
+
+ index++;
+ if (str.charAt(index) == 'x')
+ {
+ radix = 16;
+ index++;
+ }
+ else
+ radix = 8;
+ }
+
+ if (index >= len)
+ throw new NumberFormatException();
+
+ return new Long(parseLong(str, index, len, isNeg, radix));
+ }
+
+ public boolean equals(Object obj)
+ {
+ return (obj != null && (obj instanceof Long)
+ && ((Long) obj).value == value);
+ }
+
+ public static Long getLong(String prop)
+ {
+ return getLong(prop, null);
+ }
+
+ public static Long getLong(String prop, long defval)
+ {
+ Long val = getLong(prop, null);
+ return val == null ? new Long(defval) : val;
+ }
+
+ public static Long getLong(String prop, Long defobj)
+ {
+ try
+ {
+ return decode(System.getProperty(prop));
+ }
+ catch (NumberFormatException ex)
+ {
+ return defobj;
+ }
+ }
+
+ public int hashCode()
+ {
+ return (int)(this.longValue()^(this.longValue()>>>32));
+ }
+
+ public static long parseLong(String str) throws NumberFormatException
+ {
+ return parseLong(str, 10);
+ }
+
+ public static long parseLong(String str, int radix)
+ throws NumberFormatException
+ {
+ final int len;
+
+ if (str == null || (len = str.length()) == 0 ||
+ radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
+ throw new NumberFormatException();
+
+ boolean isNeg = false;
+ int index = 0;
+ if (str.charAt(index) == '-')
+ if (len > 1)
+ {
+ isNeg = true;
+ index++;
+ }
+ else
+ throw new NumberFormatException();
+
+ return parseLong(str, index, len, isNeg, radix);
+ }
+
+ private static long parseLong(String str, int index, int len, boolean isNeg,
+ int radix) throws NumberFormatException
+ {
+ long val = 0;
+ int digval;
+
+ for ( ; index < len; index++)
+ {
+ // The the previous loop iteration left us with a negative
+ // value (which can only be the most negative value, but we
+ // don't check that), then having more digits is wrong.
+ if (val == MIN_VALUE)
+ throw new NumberFormatException();
+
+ if ((digval = Character.digit(str.charAt(index), radix)) < 0)
+ throw new NumberFormatException();
+
+ // Throw an exception for overflow if result is negative.
+ // However, we special-case the most negative value.
+ val *= radix;
+ if (val < 0 || val + digval < 0)
+ {
+ if (isNeg && val + digval == MIN_VALUE)
+ {
+ // Ok.
+ }
+ else
+ throw new NumberFormatException();
+ }
+ val += digval;
+ }
+
+ return isNeg ? -(val) : val;
+ }
+
+ public static String toBinaryString(long num)
+ {
+ return toUnsignedString(num, 1);
+ }
+
+ public static String toHexString(long num)
+ {
+ return toUnsignedString(num, 4);
+ }
+
+ public static String toOctalString(long num)
+ {
+ return toUnsignedString(num, 3);
+ }
+
+ private static String toUnsignedString(long num, int exp)
+ {
+ // Use an array large enough for a binary number.
+ int radix = 1 << exp;
+ long mask = radix - 1;
+ char[] buffer = new char[64];
+ int i = 64;
+ do
+ {
+ buffer[--i] = Character.forDigit((int) (num & mask), radix);
+ num = num >>> exp;
+ }
+ while (num != 0);
+
+ return String.valueOf(buffer, i, 64-i);
+ }
+
+ public String toString()
+ {
+ return toString(this.value);
+ }
+
+ public static String toString(long num)
+ {
+ // Use the Integer toString for efficiency if possible.
+ if (num <= Integer.MAX_VALUE && num >= Integer.MIN_VALUE)
+ return Integer.toString((int) num);
+
+ // Use an arrary large enough for "-9223372036854775808"; i.e. 11 chars.
+ char[] buffer = new char[20];
+ int i = 20;
+ boolean isNeg;
+ if (num < 0)
+ {
+ isNeg = true;
+ num = -(num);
+ if (num < 0)
+ {
+ // Must be MIN_VALUE, so handle this special case.
+ buffer[--i] = '8';
+ num = 922337203685477580L;
+ }
+ }
+ else
+ isNeg = false;
+
+ do
+ {
+ buffer[--i] = (char) ((int) '0' + (num % 10));
+ num /= 10;
+ }
+ while (num > 0);
+
+ if (isNeg)
+ buffer[--i] = '-';
+
+ return String.valueOf(buffer, i, 20-i);
+ }
+
+ public static String toString(long num, int radix)
+ {
+ // Use optimized method for the typical case.
+ if (radix == 10 ||
+ radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
+ return toString(num);
+
+ // Use the Integer toString for efficiency if possible.
+ if (num <= Integer.MAX_VALUE && num >= Integer.MIN_VALUE)
+ return Integer.toString((int) num, radix);
+
+ // For negative numbers, print out the absolute value w/ a leading '-'.
+ // Use an array large enough for a binary number.
+ char[] buffer = new char[65];
+ int i = 65;
+ boolean isNeg;
+ if (num < 0)
+ {
+ isNeg = true;
+ num = -(num);
+
+ // When the value is MIN_VALUE, it overflows when made positive
+ if (num < 0)
+ {
+ buffer[--i] = Character.forDigit((int) (-(num + radix) % radix),
+ radix);
+ num = -(num / radix);
+ }
+ }
+ else
+ isNeg = false;
+
+ do
+ {
+ buffer[--i] = Character.forDigit((int) (num % radix), radix);
+ num /= radix;
+ }
+ while (num > 0);
+
+ if (isNeg)
+ buffer[--i] = '-';
+
+ return String.valueOf(buffer, i, 65-i);
+ }
+
+ public static Long valueOf(String str) throws NumberFormatException
+ {
+ return new Long(parseLong(str, 10));
+ }
+
+ public static Long valueOf(String str, int radix)
+ throws NumberFormatException
+ {
+ return new Long(parseLong(str, radix));
+ }
+}
diff --git a/libjava/java/lang/Math.java b/libjava/java/lang/Math.java
new file mode 100644
index 00000000000..77c00bd2fd5
--- /dev/null
+++ b/libjava/java/lang/Math.java
@@ -0,0 +1,118 @@
+/* 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. */
+
+/**
+ * @author Andrew Haley <aph@cygnus.com>
+ * @date September 18, 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.
+ */
+
+package java.lang;
+
+import java.util.Random;
+
+public final class Math
+{
+ private static Random random_;
+
+ public static final double E = 2.7182818284590452354;
+ public static final double PI = 3.14159265358979323846;
+
+ public static native double sin (double x);
+
+ public static native double cos (double x);
+
+ public static native double tan (double x);
+
+ public static native double asin (double x);
+
+ public static native double acos (double x);
+
+ public static native double atan (double x);
+
+ public static native double atan2(double y, double x);
+
+ public static native double exp (double x);
+
+ public static native double log (double x);
+
+ public static native double sqrt (double x);
+
+ public static native double pow (double x, double y);
+
+ public static native double IEEEremainder (double x, double y);
+
+ public static native double ceil (double x);
+
+ public static native double floor (double x);
+
+ public static native double rint (double x);
+
+ public static native int round (float x);
+
+ public static native long round (double x);
+
+ public static synchronized double random ()
+ {
+ if (random_ == null)
+ random_ = new Random ();
+ return random_.nextDouble ();
+ }
+
+ public static int abs (int n)
+ {
+ return (n < 0 ? -n : n);
+ }
+
+ public static long abs (long n)
+ {
+ return (n < 0 ? -n : n);
+ }
+
+ public static native float abs (float x);
+
+ public static native double abs (double x);
+
+ public static int min (int a, int b)
+ {
+ return (a < b ? a : b);
+ }
+
+ public static long min (long a, long b)
+ {
+ return (a < b ? a : b);
+ }
+
+ public static native float min (float a, float b);
+
+ public static native double min (double a, double b);
+
+ public static int max (int a, int b)
+ {
+ return (a < b ? b : a);
+ }
+
+ public static long max (long a, long b)
+ {
+ return (a < b ? b : a);
+ }
+
+ public static native float max (float a, float b);
+
+ public static native double max (double a, double b);
+
+ // Don't allow objects to be made.
+ private Math ()
+ {
+ }
+}
+
diff --git a/libjava/java/lang/NegativeArraySizeException.java b/libjava/java/lang/NegativeArraySizeException.java
new file mode 100644
index 00000000000..838f408e49c
--- /dev/null
+++ b/libjava/java/lang/NegativeArraySizeException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 NegativeArraySizeException extends RuntimeException
+{
+ public NegativeArraySizeException()
+ {
+ super();
+ }
+
+ public NegativeArraySizeException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/NoClassDefFoundError.java b/libjava/java/lang/NoClassDefFoundError.java
new file mode 100644
index 00000000000..4368d35baa4
--- /dev/null
+++ b/libjava/java/lang/NoClassDefFoundError.java
@@ -0,0 +1,34 @@
+// NoClassDefFoundError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 NoClassDefFoundError extends LinkageError
+{
+ public NoClassDefFoundError ()
+ {
+ super ();
+ }
+
+ public NoClassDefFoundError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/NoSuchFieldError.java b/libjava/java/lang/NoSuchFieldError.java
new file mode 100644
index 00000000000..13165e89798
--- /dev/null
+++ b/libjava/java/lang/NoSuchFieldError.java
@@ -0,0 +1,34 @@
+// NoSuchFieldError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 NoSuchFieldError extends IncompatibleClassChangeError
+{
+ public NoSuchFieldError ()
+ {
+ super ();
+ }
+
+ public NoSuchFieldError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/NoSuchFieldException.java b/libjava/java/lang/NoSuchFieldException.java
new file mode 100644
index 00000000000..6e51cdad739
--- /dev/null
+++ b/libjava/java/lang/NoSuchFieldException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 NoSuchFieldException extends Exception
+{
+ public NoSuchFieldException()
+ {
+ super();
+ }
+
+ public NoSuchFieldException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/NoSuchMethodError.java b/libjava/java/lang/NoSuchMethodError.java
new file mode 100644
index 00000000000..2c4c1da9f05
--- /dev/null
+++ b/libjava/java/lang/NoSuchMethodError.java
@@ -0,0 +1,34 @@
+// NoSuchMethodError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 NoSuchMethodError extends IncompatibleClassChangeError
+{
+ public NoSuchMethodError ()
+ {
+ super ();
+ }
+
+ public NoSuchMethodError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/NoSuchMethodException.java b/libjava/java/lang/NoSuchMethodException.java
new file mode 100644
index 00000000000..9861777c77d
--- /dev/null
+++ b/libjava/java/lang/NoSuchMethodException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 NoSuchMethodException extends Exception
+{
+ public NoSuchMethodException()
+ {
+ super();
+ }
+
+ public NoSuchMethodException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/NullPointerException.java b/libjava/java/lang/NullPointerException.java
new file mode 100644
index 00000000000..1d1abdd148c
--- /dev/null
+++ b/libjava/java/lang/NullPointerException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 NullPointerException extends RuntimeException
+{
+ public NullPointerException()
+ {
+ super();
+ }
+
+ public NullPointerException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/Number.java b/libjava/java/lang/Number.java
new file mode 100644
index 00000000000..bf9306b45f3
--- /dev/null
+++ b/libjava/java/lang/Number.java
@@ -0,0 +1,39 @@
+/* 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.lang;
+
+import java.io.Serializable;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 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 Number implements Serializable
+{
+ public byte byteValue() // Became non-abstract in JDK 1.2
+ {
+ return (byte) intValue();
+ }
+
+ public abstract double doubleValue();
+ public abstract float floatValue();
+ public abstract int intValue();
+ public abstract long longValue();
+
+ public short shortValue() // Became non-abstract in JDK 1.2
+ {
+ return (short) intValue();
+ }
+}
diff --git a/libjava/java/lang/NumberFormatException.java b/libjava/java/lang/NumberFormatException.java
new file mode 100644
index 00000000000..c05a8f172d4
--- /dev/null
+++ b/libjava/java/lang/NumberFormatException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 NumberFormatException extends IllegalArgumentException
+{
+ public NumberFormatException()
+ {
+ super();
+ }
+
+ public NumberFormatException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/Object.h b/libjava/java/lang/Object.h
new file mode 100644
index 00000000000..c5d55f17833
--- /dev/null
+++ b/libjava/java/lang/Object.h
@@ -0,0 +1,79 @@
+// Object.h - Header file for java.lang.Object. -*- 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_LANG_OBJECT_H__
+#define __JAVA_LANG_OBJECT_H__
+
+#pragma interface
+
+#include <javaprims.h>
+#include <java-assert.h>
+#include <java-threads.h>
+#include <java-gc.h>
+
+// This class is mainly here as a kludge to get G++ to allocate
+// vtable pointer as the *first* word of each Object, instead of
+// the second word (following sync_info). Note that various pieces of
+// code know that finalize() is the first method. For instance,
+// Object.java knows this, as does _Jv_AllocObject.
+
+struct _JvObjectPrefix
+{
+protected:
+ // This is disguised as the C++ vtbl.
+ // _Jv_VTable* vtable;
+
+ virtual void finalize () = 0;
+};
+
+class java::lang::Object : public _JvObjectPrefix
+{
+public:
+ // Order must match order in Object.java.
+ jclass getClass (void);
+ virtual jint hashCode (void);
+ void notify (void);
+ void notifyAll (void);
+ void wait (jlong timeout, jint nanos);
+ virtual jboolean equals (jobject obj);
+ Object (void);
+ virtual jstring toString (void);
+ void wait (void);
+ void wait (jlong timeout);
+
+ friend jint _Jv_MonitorEnter (jobject obj);
+ friend jint _Jv_MonitorExit (jobject obj);
+ friend void _Jv_InitializeSyncMutex (void);
+ friend void _Jv_FinalizeObject (jobject obj);
+
+#ifdef JV_MARKOBJ_DECL
+ friend JV_MARKOBJ_DECL;
+#endif
+#ifdef JV_MARKARRAY_DECL
+ friend JV_MARKARRAY_DECL;
+#endif
+
+protected:
+ virtual jobject clone (void);
+ virtual void finalize (void);
+
+private:
+ // This does not actually refer to a Java object. Instead it is a
+ // placeholder for a piece of internal data (the synchronization
+ // information).
+ jobject sync_info;
+
+ // Initialize the sync_info field.
+ void sync_init (void);
+
+ static void hack12_6 (jobject f);
+};
+
+#endif /* __JAVA_LANG_OBJECT_H__ */
diff --git a/libjava/java/lang/Object.java b/libjava/java/lang/Object.java
new file mode 100644
index 00000000000..2adad290812
--- /dev/null
+++ b/libjava/java/lang/Object.java
@@ -0,0 +1,86 @@
+// Object.java - The root of all evil.
+
+/* 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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date September 30, 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.
+ * plus gcj compiler sources (to determine object layout)
+ * Status: Complete to version 1.1
+ */
+
+public class Object
+{
+ // This must come first. See _JvObjectPrefix in Object.h.
+ protected void finalize () throws Throwable
+ {
+ }
+
+ public final native Class getClass ();
+ public native int hashCode ();
+ public final native void notify ();
+ public final native void notifyAll ();
+ public final native void wait (long timeout, int nanos)
+ throws InterruptedException;
+
+ public boolean equals (Object obj)
+ {
+ return this == obj;
+ }
+
+ public Object ()
+ {
+ }
+
+ public String toString ()
+ {
+ return getClass().getName() + '@' + Integer.toHexString(hashCode());
+ }
+
+ public final void wait () throws InterruptedException
+ {
+ wait (0, 0);
+ }
+
+ public final void wait (long timeout) throws InterruptedException
+ {
+ wait (timeout, 0);
+ }
+
+ protected native Object clone () throws CloneNotSupportedException;
+
+ // This initializes the sync_info member. It is here for
+ // completeness (some day we'll be able to auto-generate Object.h).
+ private final native void sync_init ();
+
+ // This exists as a workaround for the fact that we can't catch a
+ // Java Exception from C++. This is from section 12.6 of the Java
+ // Language Spec. FIXME: remove this once exception processing
+ // works.
+ private static final void hack12_6 (Object f)
+ {
+ try
+ {
+ f.finalize();
+ }
+ catch (Throwable x)
+ {
+ }
+ }
+
+ // Note that we don't mention the sync_info field here. If we do,
+ // jc1 will not work correctly.
+}
diff --git a/libjava/java/lang/OutOfMemoryError.java b/libjava/java/lang/OutOfMemoryError.java
new file mode 100644
index 00000000000..418e13ccbce
--- /dev/null
+++ b/libjava/java/lang/OutOfMemoryError.java
@@ -0,0 +1,34 @@
+// OutOfMemoryError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 OutOfMemoryError extends VirtualMachineError
+{
+ public OutOfMemoryError ()
+ {
+ super ();
+ }
+
+ public OutOfMemoryError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/Process.java b/libjava/java/lang/Process.java
new file mode 100644
index 00000000000..765bc9bb8bd
--- /dev/null
+++ b/libjava/java/lang/Process.java
@@ -0,0 +1,30 @@
+// Process.java - Represent spawned system process.
+
+/* 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.lang;
+import java.io.*;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 23, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ */
+
+public abstract class Process
+{
+ abstract public void destroy ();
+ abstract public int exitValue ();
+ abstract public InputStream getErrorStream ();
+ abstract public InputStream getInputStream ();
+ abstract public OutputStream getOutputStream ();
+ abstract public int waitFor () throws InterruptedException;
+}
diff --git a/libjava/java/lang/Runnable.java b/libjava/java/lang/Runnable.java
new file mode 100644
index 00000000000..8e27d91856d
--- /dev/null
+++ b/libjava/java/lang/Runnable.java
@@ -0,0 +1,27 @@
+// Runnable.java - Runnable interface.
+
+/* 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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date August 25, 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: Complete.
+ */
+
+public interface Runnable
+{
+ public abstract void run ();
+}
diff --git a/libjava/java/lang/Runtime.java b/libjava/java/lang/Runtime.java
new file mode 100644
index 00000000000..baf1ae541b7
--- /dev/null
+++ b/libjava/java/lang/Runtime.java
@@ -0,0 +1,136 @@
+// Runtime.java - Runtime class.
+
+/* 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.lang;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date August 27, 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: All 1.1 methods exist. exec(), load(), and loadLibrary()
+ * are not fully implemented.
+ */
+
+public class Runtime
+{
+ public Process exec (String prog) throws IOException
+ {
+ String[] a = new String[1];
+ a[0] = prog;
+ return exec (a, null);
+ }
+
+ public Process exec (String prog, String[] envp) throws IOException
+ {
+ String[] a = new String[1];
+ a[0] = prog;
+ return exec (a, envp);
+ }
+
+ public Process exec (String[] progarray) throws IOException
+ {
+ return exec (progarray, null);
+ }
+
+ public Process exec (String[] progarray, String[] envp) throws IOException
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkExec(progarray[0]);
+ // FIXME.
+ return null;
+ }
+
+ private final static void checkExit (int status)
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkExit(status);
+ }
+
+ public native void exit (int status);
+
+ public native long freeMemory ();
+ public native void gc ();
+
+ // Deprecated in 1.1. We implement what the JCL book says.
+ public InputStream getLocalizedInputStream (InputStream in)
+ {
+ return in;
+ }
+
+ // Deprecated in 1.1. We implement what the JCL book says.
+ public OutputStream getLocalizedOutputStream (OutputStream out)
+ {
+ return out;
+ }
+
+ public static Runtime getRuntime ()
+ {
+ return self;
+ }
+
+ private final void checkLink (String lib)
+ {
+ if (lib == null)
+ throw new NullPointerException ();
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkLink(lib);
+ }
+
+ public synchronized void load (String pathname)
+ {
+ checkLink (pathname);
+ // FIXME.
+ throw new UnsatisfiedLinkError ("Runtime.load not implemented");
+ }
+ public synchronized void loadLibrary (String libname)
+ {
+ checkLink (libname);
+ // FIXME.
+ throw new UnsatisfiedLinkError ("Runtime.loadLibrary not implemented");
+ }
+
+ public native void runFinalization ();
+
+ // This method is static in JDK 1.1, but isn't listed as static in
+ // the books. It is marked as static in the 1.2 docs.
+ public static void runFinalizersOnExit (boolean run)
+ {
+ // The status we pass to the security check is unspecified.
+ checkExit (0);
+ self.finalize_on_exit = run;
+ }
+
+ public native long totalMemory ();
+ public native void traceInstructions (boolean on);
+ public native void traceMethodCalls (boolean on);
+
+ // The sole constructor.
+ private Runtime ()
+ {
+ finalize_on_exit = false;
+ }
+
+ // Private data.
+ private static Runtime self = new Runtime ();
+ // FIXME: for now this can't be static. If it is, our compiler will
+ // mark it as local, and it will be inaccessible to natRuntime.cc.
+ private boolean finalize_on_exit;
+}
diff --git a/libjava/java/lang/RuntimeException.java b/libjava/java/lang/RuntimeException.java
new file mode 100644
index 00000000000..e0d3f5397d3
--- /dev/null
+++ b/libjava/java/lang/RuntimeException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 RuntimeException extends Exception
+{
+ public RuntimeException()
+ {
+ super();
+ }
+
+ public RuntimeException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/SecurityException.java b/libjava/java/lang/SecurityException.java
new file mode 100644
index 00000000000..8a6a94f7f75
--- /dev/null
+++ b/libjava/java/lang/SecurityException.java
@@ -0,0 +1,31 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 SecurityException extends RuntimeException
+{
+ public SecurityException()
+ {
+ super();
+ }
+
+ public SecurityException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/SecurityManager.java b/libjava/java/lang/SecurityManager.java
new file mode 100644
index 00000000000..50091f1044e
--- /dev/null
+++ b/libjava/java/lang/SecurityManager.java
@@ -0,0 +1,263 @@
+/* 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. */
+
+// SecurityManager
+
+package java.lang;
+
+/**
+ * @author Anthony Green <green@cygnus.com>
+ * @date October 5, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ */
+
+import java.io.*;
+import java.net.*;
+
+public abstract class SecurityManager
+{
+ protected boolean inCheck = false;
+
+ public void checkAccept (String host, int port)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkAccess (Thread thrd)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkAccess (ThreadGroup thrdGroup)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkAwtEventQueueAccess ()
+ {
+ throw new SecurityException();
+ }
+
+ public void checkConnect (String host, int prt)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkConnect (String host, int prt, Object ctx)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkCreateClassLoader ()
+ {
+ throw new SecurityException();
+ }
+
+ public void checkDelete (String fileName)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkExec (String prog)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkExit (int stat)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkLink (String lib)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkListen (int lport)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkMemberAccess (Class cl, int mtype)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkMulticast (InetAddress maddr)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkMulticast (InetAddress maddr, byte ttl)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkPackageAccess (String pkg)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkPackageDefinition (String pkg)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkPrintJobAccess ()
+ {
+ throw new SecurityException();
+ }
+
+ public void checkPropertiesAccess ()
+ {
+ throw new SecurityException();
+ }
+
+ public void checkPropertyAccess (String prop)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkPropertyAccess (String prop, String defval)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkRead (FileDescriptor fd)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkRead (String fileName)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkRead (String fileName, Object ctx)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkSecurityAccess (String action)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkSetFactory ()
+ {
+ throw new SecurityException();
+ }
+
+ public void checkSystemClipboardAccess ()
+ {
+ throw new SecurityException();
+ }
+
+ public boolean checkTopLevelWindow (Object window)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkWrite (FileDescriptor fd)
+ {
+ throw new SecurityException();
+ }
+
+ public void checkWrite (String fileName)
+ {
+ throw new SecurityException();
+ }
+
+ // Note: this method is deprecated in JDK 1.2
+ protected /* native */ int classDepth (String className)
+ {
+ Class[] classStack = getClassContext ();
+ for (int i = 0; i < classStack.length; i++)
+ if (classStack[i].getName().compareTo(className) == 0)
+ return i;
+
+ return -1;
+ }
+
+ // Note: this method is deprecated in JDK 1.2
+ protected /* native */ int classLoaderDepth ()
+ {
+ Class[] classStack = getClassContext ();
+ for (int i = 0; i < classStack.length; i++)
+ if (classStack[i].getClassLoader() != null)
+ return i;
+
+ return -1;
+ }
+
+ protected /* native */ ClassLoader currentClassLoader ()
+ {
+ Class[] classStack = getClassContext ();
+ for (int i = 0; i < classStack.length; i++)
+ {
+ ClassLoader loader = classStack[i].getClassLoader();
+ if (loader != null)
+ return loader;
+ }
+
+ return null;
+ }
+
+ protected /* native */ Class currentLoadedClass ()
+ {
+ Class[] classStack = getClassContext ();
+ for (int i = 0; i < classStack.length; i++)
+ {
+ ClassLoader loader = classStack[i].getClassLoader();
+ if (loader != null)
+ return classStack[i];
+ }
+
+ return null;
+ }
+
+ protected /* native */ Class[] getClassContext ()
+ {
+ return new Class[0];
+ }
+
+ // Note: this method is deprecated in JDK 1.2
+ public boolean getInCheck ()
+ {
+ return inCheck;
+ }
+
+ public Object getSecurityContext ()
+ {
+ // FIXME: This has yet to be implemented.
+ return new String("");
+ }
+
+ public ThreadGroup getThreadGroup ()
+ {
+ return Thread.currentThread().getThreadGroup();
+ }
+
+ protected boolean inClass (String className)
+ {
+ return (classDepth (className) != -1);
+ }
+
+ protected boolean inClassLoader ()
+ {
+ return (classLoaderDepth () != -1);
+ }
+
+ protected SecurityManager ()
+ {
+ if (System.getSecurityManager () != null)
+ throw new SecurityException ();
+ }
+}
diff --git a/libjava/java/lang/Short.java b/libjava/java/lang/Short.java
new file mode 100644
index 00000000000..4a17f2d6ea7
--- /dev/null
+++ b/libjava/java/lang/Short.java
@@ -0,0 +1,145 @@
+/* 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.lang;
+
+/**
+ * @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.
+ * Includes JDK 1.2 methods.
+ */
+
+public final class Short extends Number implements Comparable
+{
+ short value;
+
+ public final static short MIN_VALUE = -32768;
+ public final static short MAX_VALUE = 32767;
+
+ // This initialization is seemingly circular, but it is accepted
+ // by javac, and is handled specially by gcc.
+ public static final Class TYPE = short.class;
+
+ public Short(short value)
+ {
+ this.value = value;
+ }
+
+ public Short(String str)
+ throws NumberFormatException
+ {
+ this.value = parseShort(str, 10);
+ }
+
+ public byte byteValue()
+ {
+ return (byte) value;
+ }
+
+ public short shortValue()
+ {
+ return value;
+ }
+
+ public int intValue()
+ {
+ return value;
+ }
+
+ public long longValue ()
+ {
+ return value;
+ }
+
+ public float floatValue ()
+ {
+ return (float) value;
+ }
+
+ public double doubleValue ()
+ {
+ return (double) value;
+ }
+
+ public static Short decode(String str)
+ throws NumberFormatException
+ {
+ int i = (Integer.decode(str)).intValue();
+ if (i < MIN_VALUE || i > MAX_VALUE)
+ throw new NumberFormatException();
+ return new Short((short) i);
+ }
+
+ public static short parseShort(String str, int radix)
+ throws NumberFormatException
+ {
+ int i = Integer.parseInt(str, radix);
+ if (i < MIN_VALUE || i > MAX_VALUE)
+ throw new NumberFormatException();
+ return (short) i;
+ }
+
+ public static short parseShort(String str)
+ throws NumberFormatException
+ {
+ return parseShort(str, 10);
+ }
+
+ public static Short valueOf(String str, int radix)
+ throws NumberFormatException
+ {
+ return new Short(parseShort(str, radix));
+ }
+
+ public static Short valueOf(String str)
+ throws NumberFormatException
+ {
+ return valueOf(str, 10);
+ }
+
+ // Added in JDK 1.2
+ public int compareTo(Short anotherShort)
+ {
+ return this.value - anotherShort.value;
+ }
+
+ // Added in JDK 1.2
+ public int compareTo(Object o) throws ClassCastException
+ {
+ if (o instanceof Short)
+ return this.value - ((Short) o).value;
+ else
+ throw new ClassCastException();
+ }
+
+ public boolean equals(Object obj)
+ {
+ return (obj != null && (obj instanceof Short)
+ && ((Short) obj).value == value);
+ }
+
+ // Verified that hashCode is returns plain value (see Short_1 test).
+ public int hashCode()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ return Integer.toString((int) value);
+ }
+
+ public static String toString(short value)
+ {
+ return Integer.toString((int) value);
+ }
+}
diff --git a/libjava/java/lang/StackOverflowError.java b/libjava/java/lang/StackOverflowError.java
new file mode 100644
index 00000000000..ace8b25c1a0
--- /dev/null
+++ b/libjava/java/lang/StackOverflowError.java
@@ -0,0 +1,34 @@
+// StackOverflowError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 StackOverflowError extends VirtualMachineError
+{
+ public StackOverflowError ()
+ {
+ super ();
+ }
+
+ public StackOverflowError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/String.java b/libjava/java/lang/String.java
new file mode 100644
index 00000000000..1321676d0e5
--- /dev/null
+++ b/libjava/java/lang/String.java
@@ -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.lang;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date September 4, 1998.
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Complete to 1.1, but see FIXMEs. Also see testsuite results.
+ */
+
+public final class String
+{
+ private Object data;
+ private int boffset; // Note this is a byte offset - don't use in Java code!
+ private int count;
+
+ public String ()
+ {
+ init();
+ }
+
+ public String (String value)
+ {
+ data = value.data;
+ boffset = value.boffset;
+ count = value.count;
+ }
+
+ public String (StringBuffer buffer)
+ {
+ init (buffer.value, 0, buffer.count, true);
+ }
+
+ public String (char[] data)
+ {
+ init(data, 0, data.length, false);
+ }
+
+ public String (char[] data, int offset, int count)
+ {
+ init(data, offset, count, false);
+ }
+
+ public String (byte[] byteArray)
+ {
+ this (byteArray, 0, byteArray.length);
+ }
+
+ public String (byte[] byteArray, int offset, int count)
+ {
+ try
+ {
+ init (byteArray, offset, count,
+ System.getProperty("file.encoding", "8859_1"));
+ }
+ catch (UnsupportedEncodingException x1)
+ {
+ // Maybe the default encoding is bad.
+ try
+ {
+ init (byteArray, offset, count, "8859_1");
+ }
+ catch (UnsupportedEncodingException x2)
+ {
+ // We know this can't happen.
+ }
+ }
+ }
+
+ public String (byte[] byteArray, String enc)
+ throws UnsupportedEncodingException
+ {
+ this (byteArray, 0, byteArray.length, enc);
+ }
+
+ public String (byte[] byteArray, int offset, int count, String enc)
+ throws UnsupportedEncodingException
+ {
+ init (byteArray, offset, count, enc);
+ }
+
+ public static String copyValueOf(char[] data)
+ {
+ return copyValueOf (data, 0, data.length);
+ }
+
+ public static String copyValueOf(char[] data, int offset, int count)
+ {
+ String r = new String ();
+ r.init(data, offset, count, false);
+ return r;
+ }
+
+ /** @deprecated */
+ public String (byte[] ascii, int hibyte)
+ {
+ init(ascii, hibyte, 0, ascii.length);
+ }
+
+ /** @deprecated */
+ public String (byte[] ascii, int hibyte, int offset, int count)
+ {
+ init(ascii, hibyte, offset, count);
+ }
+
+ public String toString ()
+ {
+ return this;
+ }
+
+ public native boolean equals (Object anObject);
+
+ public native int hashCode ();
+
+ public int length ()
+ {
+ return count;
+ }
+
+ public native char charAt (int index);
+
+ public native void getChars (int srcBegin, int srcEnd,
+ char[] dst, int dstBegin);
+
+ public byte[] getBytes () throws UnsupportedEncodingException
+ {
+ return getBytes (System.getProperty("file.encoding", "8859_1"));
+ }
+
+ public native byte[] getBytes (String enc)
+ throws UnsupportedEncodingException;
+
+ /** @deprecated */
+ public native void getBytes (int srcBegin, int srcEnd,
+ byte[] dst, int dstBegin);
+
+ public native char[] toCharArray ();
+
+ public native boolean equalsIgnoreCase (String anotherString);
+
+ public native int compareTo (String anotherString);
+
+ public native boolean regionMatches (int toffset,
+ String other, int ooffset, int len);
+
+ public native boolean regionMatches (boolean ignoreCase, int toffset,
+ String other, int ooffset, int len);
+
+ public boolean startsWith (String prefix)
+ {
+ return startsWith (prefix, 0);
+ }
+
+ public native boolean startsWith (String prefix, int toffset);
+
+ public boolean endsWith (String suffix)
+ {
+ return regionMatches (this.count - suffix.count, suffix, 0, suffix.count);
+ }
+
+ // No such method specified in the doc, including JDK 1.2.
+ // public boolean endsWith (String suffix, int toffset)
+ // {
+ // return regionMatches (toffset, suffix, 0, suffix.count);
+ // }
+
+ // The Language Specification, and the JDK 1.2 API docs say that
+ // index and lastIndex take an int, while the Class Libraries
+ // say they take a char. The former wins ...
+
+ public int indexOf (int ch)
+ {
+ return indexOf (ch, 0);
+ }
+
+ public native int indexOf (int ch, int fromIndex);
+
+ public int indexOf (String str)
+ {
+ return indexOf (str, 0);
+ }
+
+ public native int indexOf (String str, int fromIndex);
+
+ public int lastIndexOf (int ch)
+ {
+ return lastIndexOf (ch, count - 1);
+ }
+
+ public native int lastIndexOf (int ch, int fromIndex);
+
+ public int lastIndexOf (String str)
+ {
+ return lastIndexOf (str, count - str.count);
+ }
+
+ public int lastIndexOf (String str, int fromIndex)
+ {
+ if (fromIndex >= count)
+ fromIndex = count - str.count;
+ for (;; --fromIndex)
+ {
+ if (fromIndex < 0)
+ return -1;
+ if (startsWith(str, fromIndex))
+ return fromIndex;
+ }
+ }
+
+ public String substring (int beginIndex)
+ {
+ return substring (beginIndex, count);
+ }
+
+ public native String substring (int beginIndex, int endIndex);
+
+ public native String concat (String str);
+
+ public native String replace (char oldChar, char newChar);
+
+ public native String toLowerCase ();
+
+ public native String toUpperCase ();
+
+ public native String trim ();
+
+ public static String valueOf (Object obj)
+ {
+ return obj == null ? "null" : obj.toString();
+ }
+
+ public static String valueOf (char[] data)
+ {
+ return valueOf (data, 0, data.length);
+ }
+
+ public static native String valueOf (char[] data, int offset, int count);
+
+ public static String valueOf (boolean b)
+ {
+ return b ? "true" : "false";
+ }
+
+ public static native String valueOf (char c);
+
+ public static String valueOf (int i)
+ {
+ return Integer.toString(i);
+ }
+
+ public static String valueOf (long l)
+ {
+ return Long.toString(l);
+ }
+
+ public static String valueOf (float f)
+ {
+ return Float.toString(f);
+ }
+
+ public static String valueOf (double d)
+ {
+ return Double.toString(d);
+ }
+
+ public native String intern ();
+
+ private native void init ();
+ private native void init (char[] chars, int offset, int count,
+ boolean dont_copy);
+ private native void init (byte[] chars, int hibyte, int offset, int count);
+ private native void init (byte[] chars, int offset, int count, String enc)
+ throws UnsupportedEncodingException;
+ private native void unintern ();
+ private static native void rehash ();
+}
diff --git a/libjava/java/lang/StringBuffer.java b/libjava/java/lang/StringBuffer.java
new file mode 100644
index 00000000000..4127d54787f
--- /dev/null
+++ b/libjava/java/lang/StringBuffer.java
@@ -0,0 +1,270 @@
+// StringBuffer.java - Growable strings.
+
+/* 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.lang;
+import java.io.Serializable;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 23, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ */
+
+public final class StringBuffer implements Serializable
+{
+ public StringBuffer append (boolean bool)
+ {
+ return append (String.valueOf(bool));
+ }
+
+ public synchronized StringBuffer append (char ch)
+ {
+ ensureCapacity (count + 1);
+ value[count++] = ch;
+ return this;
+ }
+
+ public StringBuffer append (int inum)
+ {
+ return append (String.valueOf(inum));
+ }
+
+ public StringBuffer append (long lnum)
+ {
+ return append (String.valueOf(lnum));
+ }
+
+ public StringBuffer append (float fnum)
+ {
+ return append (String.valueOf(fnum));
+ }
+
+ public StringBuffer append (double dnum)
+ {
+ return append (String.valueOf(dnum));
+ }
+
+ public StringBuffer append (Object obj)
+ {
+ return append (String.valueOf(obj));
+ }
+
+ public synchronized StringBuffer append (String str)
+ {
+ if (str == null)
+ str = "null";
+ int len = str.length();
+ ensureCapacity (count + len);
+ str.getChars(0, len, value, count);
+ count += len;
+ return this;
+ }
+
+ public StringBuffer append (char[] data)
+ {
+ return append (data, 0, data.length);
+ }
+
+ public synchronized StringBuffer append (char[] data, int offset, int count)
+ {
+ ensureCapacity (this.count + count);
+ System.arraycopy(data, offset, value, this.count, count);
+ this.count += count;
+ return this;
+ }
+
+ public int capacity ()
+ {
+ return value.length;
+ }
+
+ public synchronized char charAt (int index)
+ {
+ if (index >= count)
+ throw new StringIndexOutOfBoundsException (index);
+ return value[index];
+ }
+
+ public synchronized void ensureCapacity (int minimumCapacity)
+ {
+ if (shared || minimumCapacity > value.length)
+ {
+ minimumCapacity = Math.max(minimumCapacity, value.length*2+2);
+ char[] nb = new char[minimumCapacity];
+ System.arraycopy(value, 0, nb, 0, count);
+ value = nb;
+ shared = false;
+ }
+ }
+
+ public synchronized void getChars (int srcOffset, int srcEnd,
+ char[] dst, int dstOffset)
+ {
+ if (srcOffset < 0 || srcOffset > srcEnd)
+ throw new StringIndexOutOfBoundsException (srcOffset);
+ int todo = srcEnd - srcOffset;
+ if (srcEnd > count || dstOffset + todo > count)
+ throw new StringIndexOutOfBoundsException (srcEnd);
+ System.arraycopy(value, srcOffset, dst, dstOffset, todo);
+ }
+
+ public StringBuffer insert (int offset, boolean bool)
+ {
+ return insert (offset, bool ? "true" : "false");
+ }
+
+ public synchronized StringBuffer insert (int offset, char ch)
+ {
+ if (offset < 0 || offset > count)
+ throw new StringIndexOutOfBoundsException (offset);
+ ensureCapacity (count+1);
+ System.arraycopy(value, offset, value, offset+1, count-offset);
+ value[offset] = ch;
+ count++;
+ return this;
+ }
+
+ public StringBuffer insert (int offset, int inum)
+ {
+ return insert (offset, String.valueOf(inum));
+ }
+
+ public StringBuffer insert (int offset, long lnum)
+ {
+ return insert (offset, String.valueOf(lnum));
+ }
+
+ public StringBuffer insert (int offset, float fnum)
+ {
+ return insert (offset, String.valueOf(fnum));
+ }
+
+ public StringBuffer insert (int offset, double dnum)
+ {
+ return insert (offset, String.valueOf(dnum));
+ }
+
+ public StringBuffer insert (int offset, Object obj)
+ {
+ return insert (offset, String.valueOf(obj));
+ }
+
+ public synchronized StringBuffer insert (int offset, String str)
+ {
+ if (offset < 0 || offset > count)
+ throw new StringIndexOutOfBoundsException (offset);
+ // Note that using `null' is from JDK 1.2.
+ if (str == null)
+ str = "null";
+ int len = str.length();
+ ensureCapacity(count+len);
+ System.arraycopy(value, offset, value, offset+len, count-offset);
+ str.getChars(0, len, value, offset);
+ count += len;
+ return this;
+ }
+
+ public synchronized StringBuffer insert (int offset, char[] data)
+ {
+ if (offset < 0 || offset > count)
+ throw new StringIndexOutOfBoundsException (offset);
+ int len = data.length;
+ ensureCapacity (count+len);
+ System.arraycopy(value, offset, value, offset+len, count-offset);
+ System.arraycopy(data, 0, value, offset, len);
+ count += len;
+ return this;
+ }
+
+ public int length ()
+ {
+ return count;
+ }
+
+ public synchronized StringBuffer reverse ()
+ {
+ for (int i = 0; i < count / 2; ++i)
+ {
+ char c = value[i];
+ value[i] = value[count - i - 1];
+ value[count - i - 1] = c;
+ }
+ return this;
+ }
+
+ public synchronized void setCharAt (int index, char ch)
+ {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException (index);
+ // Call ensureCapacity to enforce copy-on-write.
+ ensureCapacity (count);
+ value[index] = ch;
+ }
+
+ public synchronized void setLength (int newLength)
+ {
+ if (newLength < 0)
+ throw new StringIndexOutOfBoundsException (newLength);
+
+ ensureCapacity (newLength);
+ for (int i = count; i < newLength; ++i)
+ value[i] = '\0';
+ count = newLength;
+ }
+
+ public StringBuffer ()
+ {
+ this (16);
+ }
+
+ public StringBuffer (int capacity)
+ {
+ count = 0;
+ value = new char[capacity];
+ shared = false;
+ }
+
+ public StringBuffer (String str)
+ {
+ // Note: nowhere does it say that we should handle a null
+ // argument here. In fact, the JCL implies that we should not.
+ // But this leads to an asymmetry: `null + ""' will fail, while
+ // `"" + null' will work.
+ if (str == null)
+ str = "null";
+ count = str.length();
+ // JLS: The initial capacity of the string buffer is 16 plus the
+ // length of the argument string.
+ value = new char[count + 16];
+ str.getChars(0, count, value, 0);
+ shared = false;
+ }
+
+ public String toString ()
+ {
+ shared = true;
+ return new String (this);
+ }
+
+ // The buffer. Note that this has permissions set this way so that
+ // String can get the value.
+ char[] value;
+
+ // Index of next available character. Note that this has
+ // permissions set this way so that String can get the value.
+ int count;
+
+ // True if we need to copy the buffer before writing to it again.
+ // FIXME: JDK 1.2 doesn't specify this. The new buffer-growing
+ // semantics make this less useful in that case, too.
+ private boolean shared;
+}
diff --git a/libjava/java/lang/StringIndexOutOfBoundsException.java b/libjava/java/lang/StringIndexOutOfBoundsException.java
new file mode 100644
index 00000000000..200acb896f0
--- /dev/null
+++ b/libjava/java/lang/StringIndexOutOfBoundsException.java
@@ -0,0 +1,37 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 StringIndexOutOfBoundsException extends IndexOutOfBoundsException
+{
+ public StringIndexOutOfBoundsException()
+ {
+ super();
+ }
+
+ public StringIndexOutOfBoundsException(int index)
+ {
+ this("String index out of range: " + index);
+ }
+
+ public StringIndexOutOfBoundsException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/System.java b/libjava/java/lang/System.java
new file mode 100644
index 00000000000..6f6dee42057
--- /dev/null
+++ b/libjava/java/lang/System.java
@@ -0,0 +1,166 @@
+// System.java - System-specific info.
+
+/* 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.lang;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.util.Properties;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date August 27, 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: 1.1. Some 1.2 methods missing. Properties code not fully
+ * implemented.
+ */
+
+public final class System
+{
+ public static native void arraycopy (Object src, int srcOffset,
+ Object dst, int dstOffset,
+ int count);
+
+ public static native long currentTimeMillis ();
+
+ public static void exit (int status)
+ {
+ Runtime.getRuntime().exit(status);
+ }
+
+ public static void gc ()
+ {
+ Runtime.getRuntime().gc();
+ }
+
+ // Marked deprecated in 1.1. We implement what the JCL book says.
+ public static String getenv (String name)
+ {
+ throw new Error ();
+ }
+
+ private static native void init_properties ();
+
+ public static Properties getProperties ()
+ {
+ if (secman != null)
+ secman.checkPropertiesAccess();
+ init_properties ();
+ return properties;
+ }
+
+ public static String getProperty (String property)
+ {
+ if (secman != null)
+ secman.checkPropertyAccess(property);
+ init_properties ();
+ return properties.getProperty(property);
+ }
+
+ public static String getProperty (String property, String defval)
+ {
+ if (secman != null)
+ secman.checkPropertyAccess(property, defval);
+ init_properties ();
+ return properties.getProperty(property, defval);
+ }
+
+ public static SecurityManager getSecurityManager ()
+ {
+ return secman;
+ }
+
+ public static native int identityHashCode (Object obj);
+
+ public static void load (String pathname)
+ {
+ Runtime.getRuntime().load(pathname);
+ }
+
+ public static void loadLibrary (String libname)
+ {
+ Runtime.getRuntime().loadLibrary(libname);
+ }
+
+ public static void runFinalization ()
+ {
+ Runtime.getRuntime().runFinalization();
+ }
+
+ // Marked as deprecated in 1.2.
+ public static void runFinalizersOnExit (boolean run)
+ {
+ Runtime.getRuntime().runFinalizersOnExit(run);
+ }
+
+ private static void checkSetIO ()
+ {
+ // In 1.1, we are supposed to call checkExec, but the argument is
+ // not specified. In 1.2, we are supposed to use checkPermission,
+ // which doesn't exist in 1.1.
+ if (secman != null)
+ secman.checkExec("");
+ }
+
+ public static native void setErr (PrintStream newErr);
+ public static native void setIn (InputStream newIn);
+ public static native void setOut (PrintStream newOut);
+
+ public static void setProperties (Properties props)
+ {
+ if (secman != null)
+ secman.checkPropertiesAccess();
+ // We might not have initialized yet.
+ prop_init = true;
+ properties = props;
+ }
+
+ // TODO 1.2.
+ // public static String setProperty (String key, String value);
+
+ // TODO 1.2.
+ // public static String mapLibraryName (String libname);
+
+ public static void setSecurityManager (SecurityManager s)
+ {
+ if (secman != null)
+ throw new SecurityException ();
+ secman = s;
+ }
+
+ // Public data.
+ public static final InputStream in = new BufferedInputStream (new FileInputStream (FileDescriptor.in));
+
+ public static final PrintStream out = new PrintStream (new BufferedOutputStream (new FileOutputStream (FileDescriptor.out)), true);
+
+ public static final PrintStream err = new PrintStream (new BufferedOutputStream (new FileOutputStream (FileDescriptor.err)), true);
+
+ // Don't allow System objects to be made.
+ private System ()
+ {
+ }
+
+ // Private data.
+ private static SecurityManager secman = null;
+ private static Properties properties = null;
+ // This boolean is only required for 1.1 and earlier. After 1.1, a
+ // null properties should always be re-initialized.
+ private static boolean prop_init = false;
+}
diff --git a/libjava/java/lang/Thread.java b/libjava/java/lang/Thread.java
new file mode 100644
index 00000000000..f21d3a3fb7d
--- /dev/null
+++ b/libjava/java/lang/Thread.java
@@ -0,0 +1,297 @@
+// Thread.java - Thread class.
+
+/* 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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date August 24, 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: Complete to version 1.1, with caveats
+ * Known problems:
+ * No attempt was made to implement suspend/resume
+ * (this could be done in some cases)
+ * Various methods which assume a VM are likewise unimplemented
+ * We do implement stop() even though it is deprecated.
+ */
+
+public class Thread implements Runnable
+{
+ public final static int MAX_PRIORITY = 10;
+ public final static int MIN_PRIORITY = 1;
+ public final static int NORM_PRIORITY = 5;
+
+ public static int activeCount ()
+ {
+ return currentThread().getThreadGroup().activeCount();
+ }
+
+ public void checkAccess ()
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkAccess(this);
+ }
+
+ public native int countStackFrames ();
+ public static native Thread currentThread ();
+ public native void destroy ();
+ public static native void dumpStack ();
+
+ public static int enumerate (Thread[] threads)
+ {
+ return currentThread().group.enumerate(threads);
+ }
+
+ public final String getName ()
+ {
+ return name;
+ }
+
+ public final int getPriority ()
+ {
+ return priority;
+ }
+
+ public final ThreadGroup getThreadGroup ()
+ {
+ return group;
+ }
+
+ public native void interrupt ();
+
+ public static boolean interrupted ()
+ {
+ return currentThread().isInterrupted();
+ }
+
+ // FIXME: it seems to me that this should be synchronized.
+ public boolean isInterrupted ()
+ {
+ boolean r = interrupt_flag;
+ interrupt_flag = false;
+ return r;
+ }
+
+ public final boolean isAlive ()
+ {
+ return alive_flag;
+ }
+
+ public final boolean isDaemon ()
+ {
+ return daemon_flag;
+ }
+
+ public final void join () throws InterruptedException
+ {
+ join (0, 0);
+ }
+
+ public final void join (long timeout) throws InterruptedException
+ {
+ join (timeout, 0);
+ }
+
+ public final native void join (long timeout, int nanos)
+ throws InterruptedException;
+
+ public final native void resume ();
+
+ // This method exists only to avoid a warning from the C++ compiler.
+ private static final native void run__ (Object obj);
+ private native final void finish_ ();
+ private final void run_ ()
+ {
+ try
+ {
+ run ();
+ }
+ catch (Throwable e)
+ {
+ // Uncaught exceptions are forwarded to the ThreadGroup. If
+ // this results in an uncaught exception, that is ignored.
+ try
+ {
+ group.uncaughtException(this, e);
+ }
+ catch (Throwable f)
+ {
+ // Nothing.
+ }
+ }
+ finish_ ();
+ }
+
+ public void run ()
+ {
+ if (runnable != null)
+ runnable.run();
+ }
+
+ public final void setDaemon (boolean status)
+ {
+ checkAccess ();
+ if (isAlive ())
+ throw new IllegalThreadStateException ();
+ daemon_flag = status;
+ }
+
+ // TODO12:
+ // public ClassLoader getContextClassLoader()
+ // {
+ // }
+
+ // TODO12:
+ // public void setContextClassLoader(ClassLoader cl)
+ // {
+ // }
+
+ public final void setName (String n)
+ {
+ checkAccess ();
+ // The Class Libraries book says ``threadName cannot be null''. I
+ // take this to mean NullPointerException.
+ if (n == null)
+ throw new NullPointerException ();
+ name = n;
+ }
+
+ public final native void setPriority (int newPriority);
+
+ public static void sleep (long timeout) throws InterruptedException
+ {
+ sleep (timeout, 0);
+ }
+
+ public static native void sleep (long timeout, int nanos)
+ throws InterruptedException;
+ public synchronized native void start ();
+
+ public final void stop ()
+ {
+ stop (new ThreadDeath ());
+ }
+
+ public final synchronized native void stop (Throwable e);
+ public final native void suspend ();
+
+ private final native void initialize_native ();
+
+ private final synchronized static String gen_name ()
+ {
+ String n;
+ n = "Thread-" + nextThreadNumber;
+ ++nextThreadNumber;
+ return n;
+ }
+
+ public Thread (ThreadGroup g, Runnable r, String n)
+ {
+ // Note that CURRENT can be null when we are creating the very
+ // first thread. That's why we check it below.
+ Thread current = currentThread ();
+
+ if (g != null)
+ {
+ // If CURRENT is null, then we are creating the first thread.
+ // In this case we don't do the security check.
+ if (current != null)
+ g.checkAccess();
+ }
+ else
+ g = current.getThreadGroup();
+
+ // The Class Libraries book says ``threadName cannot be null''. I
+ // take this to mean NullPointerException.
+ if (n == null)
+ throw new NullPointerException ();
+
+ name = n;
+ group = g;
+ g.add(this);
+ runnable = r;
+
+ data = null;
+ interrupt_flag = false;
+ alive_flag = false;
+ if (current != null)
+ {
+ daemon_flag = current.isDaemon();
+ priority = current.getPriority();
+ }
+ else
+ {
+ daemon_flag = false;
+ priority = NORM_PRIORITY;
+ }
+
+ initialize_native ();
+ }
+
+ public Thread ()
+ {
+ this (null, null, gen_name ());
+ }
+
+ public Thread (Runnable r)
+ {
+ this (null, r, gen_name ());
+ }
+
+ public Thread (String n)
+ {
+ this (null, null, n);
+ }
+
+ public Thread (ThreadGroup g, Runnable r)
+ {
+ this (g, r, gen_name ());
+ }
+
+ public Thread (ThreadGroup g, String n)
+ {
+ this (g, null, n);
+ }
+
+ public Thread (Runnable r, String n)
+ {
+ this (null, r, n);
+ }
+
+ public String toString ()
+ {
+ return "Thread[" + name + "," + priority + "," + group.getName() + "]";
+ }
+
+ public static native void yield ();
+
+ // Private data.
+ private ThreadGroup group;
+ private String name;
+ private Runnable runnable;
+ private int priority;
+ private boolean daemon_flag;
+ private boolean interrupt_flag;
+ private boolean alive_flag;
+
+ // This is a bit odd. We need a way to represent some data that is
+ // manipulated only by the native side of this class. We represent
+ // it as a Java object reference. However, it is not actually a
+ // Java object.
+ private Object data;
+
+ // Next thread number to assign.
+ private static int nextThreadNumber = 0;
+}
diff --git a/libjava/java/lang/ThreadDeath.java b/libjava/java/lang/ThreadDeath.java
new file mode 100644
index 00000000000..caffc936d2e
--- /dev/null
+++ b/libjava/java/lang/ThreadDeath.java
@@ -0,0 +1,35 @@
+// ThreadDeath.java - Special exception registering Thread death.
+
+/* 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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date August 26, 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: Complete to version 1.1
+ */
+
+public class ThreadDeath extends Error
+{
+ public ThreadDeath ()
+ {
+ super ();
+ }
+
+ public ThreadDeath (String message)
+ {
+ super (message);
+ }
+}
diff --git a/libjava/java/lang/ThreadGroup.java b/libjava/java/lang/ThreadGroup.java
new file mode 100644
index 00000000000..1aa1a9a3bed
--- /dev/null
+++ b/libjava/java/lang/ThreadGroup.java
@@ -0,0 +1,406 @@
+// ThreadGroup.java - ThreadGroup class.
+
+/* 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.lang;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date August 25, 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: Complete for 1.1. Parts from the JDK 1.0 spec only are
+ * not implemented. Parts of the 1.2 spec are also not implemented.
+ */
+
+public class ThreadGroup
+{
+ public int activeCount ()
+ {
+ int ac = threads.size();
+ Enumeration e = groups.elements();
+ while (e.hasMoreElements())
+ {
+ ThreadGroup g = (ThreadGroup) e.nextElement();
+ ac += g.activeCount();
+ }
+ return ac;
+ }
+
+ public int activeGroupCount ()
+ {
+ int ac = groups.size();
+ Enumeration e = groups.elements();
+ while (e.hasMoreElements())
+ {
+ ThreadGroup g = (ThreadGroup) e.nextElement();
+ ac += g.activeGroupCount();
+ }
+ return ac;
+ }
+
+ // Deprecated in 1.2.
+ public boolean allowThreadSuspension (boolean allow)
+ {
+ // There is no way for a Java program to determine whether this
+ // has any effect whatsoever. We don't need it.
+ return true;
+ }
+
+ public final void checkAccess ()
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkAccess(this);
+ }
+
+ // This is called to remove a ThreadGroup from our internal list.
+ private final void remove (ThreadGroup g)
+ {
+ groups.removeElement(g);
+ if (daemon_flag && groups.size() == 0 && threads.size() == 0)
+ {
+ // We inline destroy to avoid the access check.
+ destroyed_flag = true;
+ if (parent != null)
+ parent.remove(this);
+ }
+ }
+
+ // This is called by the Thread code to remove a Thread from our
+ // internal list. FIXME: currently, it isn't called at all. There
+ // doesn't appear to be any way to remove a Thread from a
+ // ThreadGroup (except the unimplemented destroy method).
+ final void remove (Thread t)
+ {
+ threads.removeElement(t);
+ if (daemon_flag && groups.size() == 0 && threads.size() == 0)
+ {
+ // We inline destroy to avoid the access check.
+ destroyed_flag = true;
+ if (parent != null)
+ parent.remove(this);
+ }
+ }
+
+ // This is called by the Thread code to add a Thread to our internal
+ // list.
+ final void add (Thread t)
+ {
+ if (destroyed_flag)
+ throw new IllegalThreadStateException ();
+
+ threads.addElement(t);
+ }
+
+ // This is a helper that is used to implement the destroy method.
+ private final boolean canDestroy ()
+ {
+ if (! threads.isEmpty())
+ return false;
+ Enumeration e = groups.elements();
+ while (e.hasMoreElements())
+ {
+ ThreadGroup g = (ThreadGroup) e.nextElement();
+ if (! g.canDestroy())
+ return false;
+ }
+ return true;
+ }
+
+ public final void destroy ()
+ {
+ checkAccess ();
+ if (! canDestroy ())
+ throw new IllegalThreadStateException ();
+ destroyed_flag = true;
+ if (parent != null)
+ parent.remove(this);
+ }
+
+ // This actually implements enumerate.
+ private final int enumerate (Thread[] ts, int next_index, boolean recurse)
+ {
+ Enumeration e = threads.elements();
+ while (e.hasMoreElements() && next_index < ts.length)
+ ts[next_index++] = (Thread) e.nextElement();
+ if (recurse && next_index != ts.length)
+ {
+ e = groups.elements();
+ while (e.hasMoreElements() && next_index < ts.length)
+ {
+ ThreadGroup g = (ThreadGroup) e.nextElement();
+ next_index = g.enumerate(ts, next_index, true);
+ }
+ }
+ return next_index;
+ }
+
+ public int enumerate (Thread[] ts)
+ {
+ return enumerate (ts, 0, true);
+ }
+
+ public int enumerate (Thread[] ts, boolean recurse)
+ {
+ return enumerate (ts, 0, recurse);
+ }
+
+ // This actually implements enumerate.
+ private final int enumerate (ThreadGroup[] ts, int next_index,
+ boolean recurse)
+ {
+ Enumeration e = groups.elements();
+ while (e.hasMoreElements() && next_index < ts.length)
+ {
+ ThreadGroup g = (ThreadGroup) e.nextElement();
+ ts[next_index++] = g;
+ if (recurse && next_index != ts.length)
+ next_index = g.enumerate(ts, next_index, true);
+ }
+ return next_index;
+ }
+
+ public int enumerate (ThreadGroup[] gs)
+ {
+ return enumerate (gs, 0, true);
+ }
+
+ public int enumerate (ThreadGroup[] gs, boolean recurse)
+ {
+ return enumerate (gs, 0, recurse);
+ }
+
+ public final int getMaxPriority ()
+ {
+ return maxpri;
+ }
+
+ public final String getName ()
+ {
+ return name;
+ }
+
+ public final ThreadGroup getParent ()
+ {
+ return parent;
+ }
+
+ // JDK 1.2.
+ // public void interrupt ();
+
+ public final boolean isDaemon ()
+ {
+ return daemon_flag;
+ }
+
+ public synchronized boolean isDestroyed ()
+ {
+ return destroyed_flag;
+ }
+
+ private final void list (String indentation)
+ {
+ System.out.print(indentation);
+ System.out.println(toString ());
+ String sub = indentation + " ";
+ Enumeration e = threads.elements();
+ while (e.hasMoreElements())
+ {
+ Thread t = (Thread) e.nextElement();
+ System.out.print(sub);
+ System.out.println(t.toString());
+ }
+ e = groups.elements();
+ while (e.hasMoreElements())
+ {
+ ThreadGroup g = (ThreadGroup) e.nextElement();
+ g.list(sub);
+ }
+ }
+
+ public void list ()
+ {
+ list ("");
+ }
+
+ public final boolean parentOf (ThreadGroup g)
+ {
+ while (g != null)
+ {
+ if (this == g)
+ return true;
+ g = g.parent;
+ }
+ return false;
+ }
+
+ // Deprecated in 1.2.
+ public final void resume ()
+ {
+ checkAccess ();
+ Enumeration e = threads.elements();
+ while (e.hasMoreElements())
+ {
+ Thread t = (Thread) e.nextElement();
+ t.resume();
+ }
+ e = groups.elements();
+ while (e.hasMoreElements())
+ {
+ ThreadGroup g = (ThreadGroup) e.nextElement();
+ g.resume();
+ }
+ }
+
+ public final void setDaemon (boolean daemon)
+ {
+ checkAccess ();
+ daemon_flag = daemon;
+ // FIXME: the docs don't say you are supposed to do this. But
+ // they don't say you aren't, either.
+ if (groups.size() == 0 && threads.size() == 0)
+ destroy ();
+ }
+
+ public final void setMaxPriority (int pri)
+ {
+ checkAccess ();
+
+ // FIXME: JDK 1.2 behaviour is different: if the newMaxPriority
+ // argument is < MIN_PRIORITY or > MAX_PRIORITY an
+ // IllegalArgumentException should be thrown.
+ if (pri >= Thread.MIN_PRIORITY && pri <= maxpri)
+ {
+ maxpri = pri;
+
+ Enumeration e = groups.elements();
+ while (e.hasMoreElements())
+ {
+ ThreadGroup g = (ThreadGroup) e.nextElement();
+ g.setMaxPriority (maxpri);
+ }
+ }
+ }
+
+ // Deprecated in 1.2.
+ public final void stop ()
+ {
+ checkAccess ();
+ Enumeration e = threads.elements();
+ while (e.hasMoreElements())
+ {
+ Thread t = (Thread) e.nextElement();
+ t.stop();
+ }
+ e = groups.elements();
+ while (e.hasMoreElements())
+ {
+ ThreadGroup g = (ThreadGroup) e.nextElement();
+ g.stop();
+ }
+ }
+
+ // Deprecated in 1.2.
+ public final void suspend ()
+ {
+ checkAccess ();
+ Enumeration e = threads.elements();
+ while (e.hasMoreElements())
+ {
+ Thread t = (Thread) e.nextElement();
+ t.suspend();
+ }
+ e = groups.elements();
+ while (e.hasMoreElements())
+ {
+ ThreadGroup g = (ThreadGroup) e.nextElement();
+ g.suspend();
+ }
+ }
+
+ // This constructor appears in the Class Libraries book but in
+ // neither the Language Spec nor the 1.2 docs.
+ public ThreadGroup ()
+ {
+ this (Thread.currentThread().getThreadGroup(), null);
+ }
+
+ public ThreadGroup (String n)
+ {
+ this (Thread.currentThread().getThreadGroup(), n);
+ }
+
+ public ThreadGroup (ThreadGroup p, String n)
+ {
+ checkAccess ();
+ if (p == null)
+ throw new NullPointerException ();
+ if (p.destroyed_flag)
+ throw new IllegalArgumentException ();
+
+ parent = p;
+ name = n;
+ maxpri = p.maxpri;
+ threads = new Vector ();
+ groups = new Vector ();
+ daemon_flag = p.daemon_flag;
+ destroyed_flag = false;
+ p.groups.addElement(this);
+ }
+
+ // This is the constructor that is used when creating the very first
+ // ThreadGroup. We have an arbitrary argument here just to
+ // differentiate this constructor from the others.
+ private ThreadGroup (int dummy)
+ {
+ parent = null;
+ name = "main";
+ maxpri = Thread.MAX_PRIORITY;
+ threads = new Vector ();
+ groups = new Vector ();
+ daemon_flag = false;
+ destroyed_flag = false;
+ }
+
+ public String toString ()
+ {
+ // Language Spec and Class Libraries book disagree a bit here. We
+ // follow the Spec, but add "ThreadGroup" per the book. We
+ // include "java.lang" based on the list() example in the Class
+ // Libraries book.
+ return "java.lang.ThreadGroup[name=" + name + ",maxpri=" + maxpri + "]";
+ }
+
+ public void uncaughtException (Thread thread, Throwable e)
+ {
+ // FIXME: in 1.2, this has different semantics. In particular if
+ // this group has a parent, the exception is passed upwards and
+ // not processed locally.
+ if (! (e instanceof ThreadDeath))
+ {
+ e.printStackTrace();
+ }
+ }
+
+ // Private data.
+ private ThreadGroup parent;
+ private String name;
+ private int maxpri;
+ private Vector threads;
+ private Vector groups;
+ private boolean daemon_flag;
+ private boolean destroyed_flag;
+}
diff --git a/libjava/java/lang/Throwable.java b/libjava/java/lang/Throwable.java
new file mode 100644
index 00000000000..5ae39ae2594
--- /dev/null
+++ b/libjava/java/lang/Throwable.java
@@ -0,0 +1,80 @@
+// Throwable.java - Superclass for all 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.lang;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 30, 1998
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Sufficient for compiled code, but methods applicable to
+ * bytecode not implemented. JDK 1.1.
+ */
+
+public class Throwable implements Serializable
+{
+ public Throwable fillInStackTrace ()
+ {
+ return this;
+ }
+
+ public String getLocalizedMessage ()
+ {
+ return getMessage ();
+ }
+
+ public String getMessage ()
+ {
+ return detailMessage;
+ }
+
+ public void printStackTrace ()
+ {
+ printStackTrace (System.err);
+ }
+
+ public void printStackTrace (PrintStream s)
+ {
+ // No stack trace, but we can still print this object.
+ s.println(toString ());
+ }
+
+ public void printStackTrace (PrintWriter wr)
+ {
+ // No stack trace, but we can still print this object.
+ wr.println(toString ());
+ }
+
+ public Throwable ()
+ {
+ detailMessage = null;
+ }
+
+ public Throwable (String message)
+ {
+ detailMessage = message;
+ }
+
+ public String toString ()
+ {
+ return ((detailMessage == null)
+ ? getClass().getName()
+ : getClass().getName() + ": " + getMessage ());
+ }
+
+ // Name of this field comes from serialization spec.
+ private String detailMessage;
+}
diff --git a/libjava/java/lang/UnknownError.java b/libjava/java/lang/UnknownError.java
new file mode 100644
index 00000000000..edf050c77ec
--- /dev/null
+++ b/libjava/java/lang/UnknownError.java
@@ -0,0 +1,34 @@
+// UnknownError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 UnknownError extends VirtualMachineError
+{
+ public UnknownError ()
+ {
+ super ();
+ }
+
+ public UnknownError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/UnsatisfiedLinkError.java b/libjava/java/lang/UnsatisfiedLinkError.java
new file mode 100644
index 00000000000..63930f5555f
--- /dev/null
+++ b/libjava/java/lang/UnsatisfiedLinkError.java
@@ -0,0 +1,34 @@
+// UnsatisfiedLinkError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 UnsatisfiedLinkError extends LinkageError
+{
+ public UnsatisfiedLinkError ()
+ {
+ super ();
+ }
+
+ public UnsatisfiedLinkError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/UnsupportedOperationException.java b/libjava/java/lang/UnsupportedOperationException.java
new file mode 100644
index 00000000000..d2bee88622a
--- /dev/null
+++ b/libjava/java/lang/UnsupportedOperationException.java
@@ -0,0 +1,32 @@
+/* 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.lang;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 18, 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 UnsupportedOperationException extends RuntimeException
+{
+ public UnsupportedOperationException()
+ {
+ super();
+ }
+
+ public UnsupportedOperationException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/lang/VerifyError.java b/libjava/java/lang/VerifyError.java
new file mode 100644
index 00000000000..69d6a69baf5
--- /dev/null
+++ b/libjava/java/lang/VerifyError.java
@@ -0,0 +1,34 @@
+// VerifyError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 VerifyError extends LinkageError
+{
+ public VerifyError ()
+ {
+ super ();
+ }
+
+ public VerifyError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/VirtualMachineError.java b/libjava/java/lang/VirtualMachineError.java
new file mode 100644
index 00000000000..dcc907c5d03
--- /dev/null
+++ b/libjava/java/lang/VirtualMachineError.java
@@ -0,0 +1,34 @@
+// VirtualMachineError.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.lang;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 VirtualMachineError extends Error
+{
+ public VirtualMachineError ()
+ {
+ super ();
+ }
+
+ public VirtualMachineError (String msg)
+ {
+ super (msg);
+ }
+}
diff --git a/libjava/java/lang/Void.java b/libjava/java/lang/Void.java
new file mode 100644
index 00000000000..5390552a622
--- /dev/null
+++ b/libjava/java/lang/Void.java
@@ -0,0 +1,30 @@
+/* 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.lang;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date April 18, 1998.
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Complete.
+ */
+
+public final class Void
+{
+ // This initialization is seemingly circular, but it is accepted
+ // by javac, and is handled specially by gcc.
+ public final static Class TYPE = void.class;
+
+ // Don't allow Void objects to be made.
+ private Void ()
+ {
+ }
+}
diff --git a/libjava/java/lang/dtoa.c b/libjava/java/lang/dtoa.c
new file mode 100644
index 00000000000..fae45c5aeb4
--- /dev/null
+++ b/libjava/java/lang/dtoa.c
@@ -0,0 +1,906 @@
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991 by AT&T.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* Please send bug reports to
+ David M. Gay
+ AT&T Bell Laboratories, Room 2C-463
+ 600 Mountain Avenue
+ Murray Hill, NJ 07974-2070
+ U.S.A.
+ dmg@research.att.com or research!dmg
+ */
+
+#include "mprec.h"
+
+static int
+_DEFUN (quorem,
+ (b, S),
+ _Jv_Bigint * b _AND _Jv_Bigint * S)
+{
+ int n;
+ long borrow, y;
+ unsigned long carry, q, ys;
+ unsigned long *bx, *bxe, *sx, *sxe;
+#ifdef Pack_32
+ long z;
+ unsigned long si, zs;
+#endif
+
+ n = S->_wds;
+#ifdef DEBUG
+ /*debug*/ if (b->_wds > n)
+ /*debug*/ Bug ("oversize b in quorem");
+#endif
+ if (b->_wds < n)
+ return 0;
+ sx = S->_x;
+ sxe = sx + --n;
+ bx = b->_x;
+ bxe = bx + n;
+ q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
+#ifdef DEBUG
+ /*debug*/ if (q > 9)
+ /*debug*/ Bug ("oversized quotient in quorem");
+#endif
+ if (q)
+ {
+ borrow = 0;
+ carry = 0;
+ do
+ {
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) * q + carry;
+ zs = (si >> 16) * q + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend (borrow, y);
+ z = (*bx >> 16) - (zs & 0xffff) + borrow;
+ borrow = z >> 16;
+ Sign_Extend (borrow, z);
+ Storeinc (bx, z, y);
+#else
+ ys = *sx++ * q + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend (borrow, y);
+ *bx++ = y & 0xffff;
+#endif
+ }
+ while (sx <= sxe);
+ if (!*bxe)
+ {
+ bx = b->_x;
+ while (--bxe > bx && !*bxe)
+ --n;
+ b->_wds = n;
+ }
+ }
+ if (cmp (b, S) >= 0)
+ {
+ q++;
+ borrow = 0;
+ carry = 0;
+ bx = b->_x;
+ sx = S->_x;
+ do
+ {
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) + carry;
+ zs = (si >> 16) + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend (borrow, y);
+ z = (*bx >> 16) - (zs & 0xffff) + borrow;
+ borrow = z >> 16;
+ Sign_Extend (borrow, z);
+ Storeinc (bx, z, y);
+#else
+ ys = *sx++ + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend (borrow, y);
+ *bx++ = y & 0xffff;
+#endif
+ }
+ while (sx <= sxe);
+ bx = b->_x;
+ bxe = bx + n;
+ if (!*bxe)
+ {
+ while (--bxe > bx && !*bxe)
+ --n;
+ b->_wds = n;
+ }
+ }
+ return q;
+}
+
+#ifdef DEBUG
+#include <stdio.h>
+
+void
+print (_Jv_Bigint * b)
+{
+ int i, wds;
+ unsigned long *x, y;
+ wds = b->_wds;
+ x = b->_x+wds;
+ i = 0;
+ do
+ {
+ x--;
+ fprintf (stderr, "%08x", *x);
+ }
+ while (++i < wds);
+ fprintf (stderr, "\n");
+}
+#endif
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ * 1. Rather than iterating, we use a simple numeric overestimate
+ * to determine k = floor(log10(d)). We scale relevant
+ * quantities using O(log2(k)) rather than O(k) multiplications.
+ * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ * try to generate digits strictly left to right. Instead, we
+ * compute with fewer bits and propagate the carry if necessary
+ * when rounding the final digit up. This is often faster.
+ * 3. Under the assumption that input will be rounded nearest,
+ * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ * That is, we allow equality in stopping tests when the
+ * round-nearest rule will give the same floating-point value
+ * as would satisfaction of the stopping test with strict
+ * inequality.
+ * 4. We remove common factors of powers of 2 from relevant
+ * quantities.
+ * 5. When converting floating-point integers less than 1e16,
+ * we use floating-point arithmetic rather than resorting
+ * to multiple-precision integers.
+ * 6. When asked to produce fewer than 15 digits, we first try
+ * to get by with floating-point arithmetic; we resort to
+ * multiple-precision integer arithmetic only if we cannot
+ * guarantee that the floating-point calculation has given
+ * the correctly rounded result. For k requested digits and
+ * "uniformly" distributed input, the probability is
+ * something like 10^(k-15) that we must resort to the long
+ * calculation.
+ */
+
+
+char *
+_DEFUN (_dtoa_r,
+ (ptr, _d, mode, ndigits, decpt, sign, rve, float_type),
+ struct _Jv_reent *ptr _AND
+ double _d _AND
+ int mode _AND
+ int ndigits _AND
+ int *decpt _AND
+ int *sign _AND
+ char **rve _AND
+ int float_type)
+{
+ /*
+ float_type == 0 for double precision, 1 for float.
+
+ Arguments ndigits, decpt, sign are similar to those
+ of ecvt and fcvt; trailing zeros are suppressed from
+ the returned string. If not null, *rve is set to point
+ to the end of the return value. If d is +-Infinity or NaN,
+ then *decpt is set to 9999.
+
+ mode:
+ 0 ==> shortest string that yields d when read in
+ and rounded to nearest.
+ 1 ==> like 0, but with Steele & White stopping rule;
+ e.g. with IEEE P754 arithmetic , mode 0 gives
+ 1e23 whereas mode 1 gives 9.999999999999999e22.
+ 2 ==> max(1,ndigits) significant digits. This gives a
+ return value similar to that of ecvt, except
+ that trailing zeros are suppressed.
+ 3 ==> through ndigits past the decimal point. This
+ gives a return value similar to that from fcvt,
+ except that trailing zeros are suppressed, and
+ ndigits can be negative.
+ 4-9 should give the same return values as 2-3, i.e.,
+ 4 <= mode <= 9 ==> same return as mode
+ 2 + (mode & 1). These modes are mainly for
+ debugging; often they run slower but sometimes
+ faster than modes 2-3.
+ 4,5,8,9 ==> left-to-right digit generation.
+ 6-9 ==> don't try fast floating-point estimate
+ (if applicable).
+
+ > 16 ==> Floating-point arg is treated as single precision.
+
+ Values of mode other than 0-9 are treated as mode 0.
+
+ Sufficient space is allocated to the return value
+ to hold the suppressed trailing zeros.
+ */
+
+ int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, j, j1, k, k0,
+ k_check, leftright, m2, m5, s2, s5, spec_case, try_quick;
+ union double_union d, d2, eps;
+ long L;
+#ifndef Sudden_Underflow
+ int denorm;
+ unsigned long x;
+#endif
+ _Jv_Bigint *b, *b1, *delta, *mlo, *mhi, *S;
+ double ds;
+ char *s, *s0;
+
+ d.d = _d;
+
+ if (ptr->_result)
+ {
+ ptr->_result->_k = ptr->_result_k;
+ ptr->_result->_maxwds = 1 << ptr->_result_k;
+ Bfree (ptr, ptr->_result);
+ ptr->_result = 0;
+ }
+
+ if (word0 (d) & Sign_bit)
+ {
+ /* set sign for everything, including 0's and NaNs */
+ *sign = 1;
+ word0 (d) &= ~Sign_bit; /* clear sign bit */
+ }
+ else
+ *sign = 0;
+
+#if defined(IEEE_Arith) + defined(VAX)
+#ifdef IEEE_Arith
+ if ((word0 (d) & Exp_mask) == Exp_mask)
+#else
+ if (word0 (d) == 0x8000)
+#endif
+ {
+ /* Infinity or NaN */
+ *decpt = 9999;
+ s =
+#ifdef IEEE_Arith
+ !word1 (d) && !(word0 (d) & 0xfffff) ? "Infinity" :
+#endif
+ "NaN";
+ if (rve)
+ *rve =
+#ifdef IEEE_Arith
+ s[3] ? s + 8 :
+#endif
+ s + 3;
+ return s;
+ }
+#endif
+#ifdef IBM
+ d.d += 0; /* normalize */
+#endif
+ if (!d.d)
+ {
+ *decpt = 1;
+ s = "0";
+ if (rve)
+ *rve = s + 1;
+ return s;
+ }
+
+ b = d2b (ptr, d.d, &be, &bbits);
+#ifdef Sudden_Underflow
+ i = (int) (word0 (d) >> Exp_shift1 & (Exp_mask >> Exp_shift1));
+#else
+ if ((i = (int) (word0 (d) >> Exp_shift1 & (Exp_mask >> Exp_shift1))))
+ {
+#endif
+ d2.d = d.d;
+ word0 (d2) &= Frac_mask1;
+ word0 (d2) |= Exp_11;
+#ifdef IBM
+ if (j = 11 - hi0bits (word0 (d2) & Frac_mask))
+ d2.d /= 1 << j;
+#endif
+
+ /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
+ * log10(x) = log(x) / log(10)
+ * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+ * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+ *
+ * This suggests computing an approximation k to log10(d) by
+ *
+ * k = (i - Bias)*0.301029995663981
+ * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+ *
+ * We want k to be too large rather than too small.
+ * The error in the first-order Taylor series approximation
+ * is in our favor, so we just round up the constant enough
+ * to compensate for any error in the multiplication of
+ * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+ * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+ * adding 1e-13 to the constant term more than suffices.
+ * Hence we adjust the constant term to 0.1760912590558.
+ * (We could get a more accurate k by invoking log10,
+ * but this is probably not worthwhile.)
+ */
+
+ i -= Bias;
+#ifdef IBM
+ i <<= 2;
+ i += j;
+#endif
+#ifndef Sudden_Underflow
+ denorm = 0;
+ }
+ else
+ {
+ /* d is denormalized */
+
+ i = bbits + be + (Bias + (P - 1) - 1);
+ x = i > 32 ? word0 (d) << (64 - i) | word1 (d) >> (i - 32)
+ : word1 (d) << (32 - i);
+ d2.d = x;
+ word0 (d2) -= 31 * Exp_msk1; /* adjust exponent */
+ i -= (Bias + (P - 1) - 1) + 1;
+ denorm = 1;
+ }
+#endif
+ ds = (d2.d - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981;
+ k = (int) ds;
+ if (ds < 0. && ds != k)
+ k--; /* want k = floor(ds) */
+ k_check = 1;
+ if (k >= 0 && k <= Ten_pmax)
+ {
+ if (d.d < tens[k])
+ k--;
+ k_check = 0;
+ }
+ j = bbits - i - 1;
+ if (j >= 0)
+ {
+ b2 = 0;
+ s2 = j;
+ }
+ else
+ {
+ b2 = -j;
+ s2 = 0;
+ }
+ if (k >= 0)
+ {
+ b5 = 0;
+ s5 = k;
+ s2 += k;
+ }
+ else
+ {
+ b2 -= k;
+ b5 = -k;
+ s5 = 0;
+ }
+ if (mode < 0 || mode > 9)
+ mode = 0;
+ try_quick = 1;
+ if (mode > 5)
+ {
+ mode -= 4;
+ try_quick = 0;
+ }
+ leftright = 1;
+ switch (mode)
+ {
+ case 0:
+ case 1:
+ ilim = ilim1 = -1;
+ i = 18;
+ ndigits = 0;
+ break;
+ case 2:
+ leftright = 0;
+ /* no break */
+ case 4:
+ if (ndigits <= 0)
+ ndigits = 1;
+ ilim = ilim1 = i = ndigits;
+ break;
+ case 3:
+ leftright = 0;
+ /* no break */
+ case 5:
+ i = ndigits + k + 1;
+ ilim = i;
+ ilim1 = i - 1;
+ if (i <= 0)
+ i = 1;
+ }
+ j = sizeof (unsigned long);
+ for (ptr->_result_k = 0; (int) (sizeof (_Jv_Bigint) - sizeof (unsigned long)) + j <= i;
+ j <<= 1)
+ ptr->_result_k++;
+ ptr->_result = Balloc (ptr, ptr->_result_k);
+ s = s0 = (char *) ptr->_result;
+
+ if (ilim >= 0 && ilim <= Quick_max && try_quick)
+ {
+ /* Try to get by with floating-point arithmetic. */
+
+ i = 0;
+ d2.d = d.d;
+ k0 = k;
+ ilim0 = ilim;
+ ieps = 2; /* conservative */
+ if (k > 0)
+ {
+ ds = tens[k & 0xf];
+ j = k >> 4;
+ if (j & Bletch)
+ {
+ /* prevent overflows */
+ j &= Bletch - 1;
+ d.d /= bigtens[n_bigtens - 1];
+ ieps++;
+ }
+ for (; j; j >>= 1, i++)
+ if (j & 1)
+ {
+ ieps++;
+ ds *= bigtens[i];
+ }
+ d.d /= ds;
+ }
+ else if ((j1 = -k))
+ {
+ d.d *= tens[j1 & 0xf];
+ for (j = j1 >> 4; j; j >>= 1, i++)
+ if (j & 1)
+ {
+ ieps++;
+ d.d *= bigtens[i];
+ }
+ }
+ if (k_check && d.d < 1. && ilim > 0)
+ {
+ if (ilim1 <= 0)
+ goto fast_failed;
+ ilim = ilim1;
+ k--;
+ d.d *= 10.;
+ ieps++;
+ }
+ eps.d = ieps * d.d + 7.;
+ word0 (eps) -= (P - 1) * Exp_msk1;
+ if (ilim == 0)
+ {
+ S = mhi = 0;
+ d.d -= 5.;
+ if (d.d > eps.d)
+ goto one_digit;
+ if (d.d < -eps.d)
+ goto no_digits;
+ goto fast_failed;
+ }
+#ifndef No_leftright
+ if (leftright)
+ {
+ /* Use Steele & White method of only
+ * generating digits needed.
+ */
+ eps.d = 0.5 / tens[ilim - 1] - eps.d;
+ for (i = 0;;)
+ {
+ L = d.d;
+ d.d -= L;
+ *s++ = '0' + (int) L;
+ if (d.d < eps.d)
+ goto ret1;
+ if (1. - d.d < eps.d)
+ goto bump_up;
+ if (++i >= ilim)
+ break;
+ eps.d *= 10.;
+ d.d *= 10.;
+ }
+ }
+ else
+ {
+#endif
+ /* Generate ilim digits, then fix them up. */
+ eps.d *= tens[ilim - 1];
+ for (i = 1;; i++, d.d *= 10.)
+ {
+ L = d.d;
+ d.d -= L;
+ *s++ = '0' + (int) L;
+ if (i == ilim)
+ {
+ if (d.d > 0.5 + eps.d)
+ goto bump_up;
+ else if (d.d < 0.5 - eps.d)
+ {
+ while (*--s == '0');
+ s++;
+ goto ret1;
+ }
+ break;
+ }
+ }
+#ifndef No_leftright
+ }
+#endif
+ fast_failed:
+ s = s0;
+ d.d = d2.d;
+ k = k0;
+ ilim = ilim0;
+ }
+
+ /* Do we have a "small" integer? */
+
+ if (be >= 0 && k <= Int_max)
+ {
+ /* Yes. */
+ ds = tens[k];
+ if (ndigits < 0 && ilim <= 0)
+ {
+ S = mhi = 0;
+ if (ilim < 0 || d.d <= 5 * ds)
+ goto no_digits;
+ goto one_digit;
+ }
+ for (i = 1;; i++)
+ {
+ L = d.d / ds;
+ d.d -= L * ds;
+#ifdef Check_FLT_ROUNDS
+ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+ if (d.d < 0)
+ {
+ L--;
+ d.d += ds;
+ }
+#endif
+ *s++ = '0' + (int) L;
+ if (i == ilim)
+ {
+ d.d += d.d;
+ if (d.d > ds || (d.d == ds && L & 1))
+ {
+ bump_up:
+ while (*--s == '9')
+ if (s == s0)
+ {
+ k++;
+ *s = '0';
+ break;
+ }
+ ++*s++;
+ }
+ break;
+ }
+ if (!(d.d *= 10.))
+ break;
+ }
+ goto ret1;
+ }
+
+ m2 = b2;
+ m5 = b5;
+ mhi = mlo = 0;
+ if (leftright)
+ {
+ if (mode < 2)
+ {
+ i =
+#ifndef Sudden_Underflow
+ denorm ? be + (Bias + (P - 1) - 1 + 1) :
+#endif
+#ifdef IBM
+ 1 + 4 * P - 3 - bbits + ((bbits + be - 1) & 3);
+#else
+ 1 + P - bbits;
+#endif
+ }
+ else
+ {
+ j = ilim - 1;
+ if (m5 >= j)
+ m5 -= j;
+ else
+ {
+ s5 += j -= m5;
+ b5 += j;
+ m5 = 0;
+ }
+ if ((i = ilim) < 0)
+ {
+ m2 -= i;
+ i = 0;
+ }
+ }
+ b2 += i;
+ s2 += i;
+ mhi = i2b (ptr, 1);
+ }
+ if (m2 > 0 && s2 > 0)
+ {
+ i = m2 < s2 ? m2 : s2;
+ b2 -= i;
+ m2 -= i;
+ s2 -= i;
+ }
+ if (b5 > 0)
+ {
+ if (leftright)
+ {
+ if (m5 > 0)
+ {
+ mhi = pow5mult (ptr, mhi, m5);
+ b1 = mult (ptr, mhi, b);
+ Bfree (ptr, b);
+ b = b1;
+ }
+ if ((j = b5 - m5))
+ b = pow5mult (ptr, b, j);
+ }
+ else
+ b = pow5mult (ptr, b, b5);
+ }
+ S = i2b (ptr, 1);
+ if (s5 > 0)
+ S = pow5mult (ptr, S, s5);
+
+ /* Check for special case that d is a normalized power of 2. */
+
+ if (mode < 2)
+ {
+ if (!word1 (d) && !(word0 (d) & Bndry_mask)
+#ifndef Sudden_Underflow
+ && word0 (d) & Exp_mask
+#endif
+ )
+ {
+ /* The special case */
+ b2 += Log2P;
+ s2 += Log2P;
+ spec_case = 1;
+ }
+ else
+ spec_case = 0;
+ }
+
+ /* Arrange for convenient computation of quotients:
+ * shift left if necessary so divisor has 4 leading 0 bits.
+ *
+ * Perhaps we should just compute leading 28 bits of S once
+ * and for all and pass them and a shift to quorem, so it
+ * can do shifts and ors to compute the numerator for q.
+ */
+
+#ifdef Pack_32
+ if ((i = ((s5 ? 32 - hi0bits (S->_x[S->_wds - 1]) : 1) + s2) & 0x1f))
+ i = 32 - i;
+#else
+ if ((i = ((s5 ? 32 - hi0bits (S->_x[S->_wds - 1]) : 1) + s2) & 0xf))
+ i = 16 - i;
+#endif
+ if (i > 4)
+ {
+ i -= 4;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ else if (i < 4)
+ {
+ i += 28;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ if (b2 > 0)
+ b = lshift (ptr, b, b2);
+ if (s2 > 0)
+ S = lshift (ptr, S, s2);
+ if (k_check)
+ {
+ if (cmp (b, S) < 0)
+ {
+ k--;
+ b = multadd (ptr, b, 10, 0); /* we botched the k estimate */
+ if (leftright)
+ mhi = multadd (ptr, mhi, 10, 0);
+ ilim = ilim1;
+ }
+ }
+ if (ilim <= 0 && mode > 2)
+ {
+ if (ilim < 0 || cmp (b, S = multadd (ptr, S, 5, 0)) <= 0)
+ {
+ /* no digits, fcvt style */
+ no_digits:
+ k = -1 - ndigits;
+ goto ret;
+ }
+ one_digit:
+ *s++ = '1';
+ k++;
+ goto ret;
+ }
+ if (leftright)
+ {
+ if (m2 > 0)
+ mhi = lshift (ptr, mhi, m2);
+
+ /* Single precision case, */
+ if (float_type)
+ mhi = lshift (ptr, mhi, 29);
+
+ /* Compute mlo -- check for special case
+ * that d is a normalized power of 2.
+ */
+
+ mlo = mhi;
+ if (spec_case)
+ {
+ mhi = Balloc (ptr, mhi->_k);
+ Bcopy (mhi, mlo);
+ mhi = lshift (ptr, mhi, Log2P);
+ }
+
+ for (i = 1;; i++)
+ {
+ dig = quorem (b, S) + '0';
+ /* Do we yet have the shortest decimal string
+ * that will round to d?
+ */
+ j = cmp (b, mlo);
+ delta = diff (ptr, S, mhi);
+ j1 = delta->_sign ? 1 : cmp (b, delta);
+ Bfree (ptr, delta);
+#ifndef ROUND_BIASED
+ if (j1 == 0 && !mode && !(word1 (d) & 1))
+ {
+ if (dig == '9')
+ goto round_9_up;
+ if (j > 0)
+ dig++;
+ *s++ = dig;
+ goto ret;
+ }
+#endif
+ if (j < 0 || (j == 0 && !mode
+#ifndef ROUND_BIASED
+ && !(word1 (d) & 1)
+#endif
+ ))
+ {
+ if (j1 > 0)
+ {
+ b = lshift (ptr, b, 1);
+ j1 = cmp (b, S);
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
+ && dig++ == '9')
+ goto round_9_up;
+ }
+ *s++ = dig;
+ goto ret;
+ }
+ if (j1 > 0)
+ {
+ if (dig == '9')
+ { /* possible if i == 1 */
+ round_9_up:
+ *s++ = '9';
+ goto roundoff;
+ }
+ *s++ = dig + 1;
+ goto ret;
+ }
+ *s++ = dig;
+ if (i == ilim)
+ break;
+ b = multadd (ptr, b, 10, 0);
+ if (mlo == mhi)
+ mlo = mhi = multadd (ptr, mhi, 10, 0);
+ else
+ {
+ mlo = multadd (ptr, mlo, 10, 0);
+ mhi = multadd (ptr, mhi, 10, 0);
+ }
+ }
+ }
+ else
+ for (i = 1;; i++)
+ {
+ *s++ = dig = quorem (b, S) + '0';
+ if (i >= ilim)
+ break;
+ b = multadd (ptr, b, 10, 0);
+ }
+
+ /* Round off last digit */
+
+ b = lshift (ptr, b, 1);
+ j = cmp (b, S);
+ if (j > 0 || (j == 0 && dig & 1))
+ {
+ roundoff:
+ while (*--s == '9')
+ if (s == s0)
+ {
+ k++;
+ *s++ = '1';
+ goto ret;
+ }
+ ++*s++;
+ }
+ else
+ {
+ while (*--s == '0');
+ s++;
+ }
+ret:
+ Bfree (ptr, S);
+ if (mhi)
+ {
+ if (mlo && mlo != mhi)
+ Bfree (ptr, mlo);
+ Bfree (ptr, mhi);
+ }
+ret1:
+ Bfree (ptr, b);
+ *s = 0;
+ *decpt = k + 1;
+ if (rve)
+ *rve = s;
+ return s0;
+}
+
+
+_VOID
+_DEFUN (_dtoa,
+ (_d, mode, ndigits, decpt, sign, rve, buf, float_type),
+ double _d _AND
+ int mode _AND
+ int ndigits _AND
+ int *decpt _AND
+ int *sign _AND
+ char **rve _AND
+ char *buf _AND
+ int float_type)
+{
+ struct _Jv_reent reent;
+ char *p;
+ memset (&reent, 0, sizeof reent);
+
+ p = _dtoa_r (&reent, _d, mode, ndigits, decpt, sign, rve, float_type);
+ strcpy (buf, p);
+
+ return;
+}
+
+
diff --git a/libjava/java/lang/e_acos.c b/libjava/java/lang/e_acos.c
new file mode 100644
index 00000000000..319b1d56fa0
--- /dev/null
+++ b/libjava/java/lang/e_acos.c
@@ -0,0 +1,111 @@
+
+/* @(#)e_acos.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_acos(x)
+ * Method :
+ * acos(x) = pi/2 - asin(x)
+ * acos(-x) = pi/2 + asin(x)
+ * For |x|<=0.5
+ * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c)
+ * For x>0.5
+ * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2)))
+ * = 2asin(sqrt((1-x)/2))
+ * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z)
+ * = 2f + (2c + 2s*z*R(z))
+ * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term
+ * for f so that f+c ~ sqrt(z).
+ * For x<-0.5
+ * acos(x) = pi - 2asin(sqrt((1-|x|)/2))
+ * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z)
+ *
+ * Special cases:
+ * if x is NaN, return x itself;
+ * if |x|>1, return NaN with invalid signal.
+ *
+ * Function needed: sqrt
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
+pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
+pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
+pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
+pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
+pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
+pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
+pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
+pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
+qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
+qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
+qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
+qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
+
+#ifdef __STDC__
+ double __ieee754_acos(double x)
+#else
+ double __ieee754_acos(x)
+ double x;
+#endif
+{
+ double z,p,q,r,w,s,c,df;
+ __int32_t hx,ix;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x3ff00000) { /* |x| >= 1 */
+ __uint32_t lx;
+ GET_LOW_WORD(lx,x);
+ if(((ix-0x3ff00000)|lx)==0) { /* |x|==1 */
+ if(hx>0) return 0.0; /* acos(1) = 0 */
+ else return pi+2.0*pio2_lo; /* acos(-1)= pi */
+ }
+ return (x-x)/(x-x); /* acos(|x|>1) is NaN */
+ }
+ if(ix<0x3fe00000) { /* |x| < 0.5 */
+ if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/
+ z = x*x;
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ r = p/q;
+ return pio2_hi - (x - (pio2_lo-x*r));
+ } else if (hx<0) { /* x < -0.5 */
+ z = (one+x)*0.5;
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ s = __ieee754_sqrt(z);
+ r = p/q;
+ w = r*s-pio2_lo;
+ return pi - 2.0*(s+w);
+ } else { /* x > 0.5 */
+ z = (one-x)*0.5;
+ s = __ieee754_sqrt(z);
+ df = s;
+ SET_LOW_WORD(df,0);
+ c = (z-df*df)/(s+df);
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ r = p/q;
+ w = r*s+c;
+ return 2.0*(df+w);
+ }
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/e_asin.c b/libjava/java/lang/e_asin.c
new file mode 100644
index 00000000000..559f2884a26
--- /dev/null
+++ b/libjava/java/lang/e_asin.c
@@ -0,0 +1,120 @@
+
+/* @(#)e_asin.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_asin(x)
+ * Method :
+ * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
+ * we approximate asin(x) on [0,0.5] by
+ * asin(x) = x + x*x^2*R(x^2)
+ * where
+ * R(x^2) is a rational approximation of (asin(x)-x)/x^3
+ * and its remez error is bounded by
+ * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
+ *
+ * For x in [0.5,1]
+ * asin(x) = pi/2-2*asin(sqrt((1-x)/2))
+ * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
+ * then for x>0.98
+ * asin(x) = pi/2 - 2*(s+s*z*R(z))
+ * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
+ * For x<=0.98, let pio4_hi = pio2_hi/2, then
+ * f = hi part of s;
+ * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z)
+ * and
+ * asin(x) = pi/2 - 2*(s+s*z*R(z))
+ * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
+ * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
+ *
+ * Special cases:
+ * if x is NaN, return x itself;
+ * if |x|>1, return NaN with invalid signal.
+ *
+ */
+
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+huge = 1.000e+300,
+pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
+pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
+pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
+ /* coefficient for R(x^2) */
+pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
+pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
+pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
+pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
+pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
+pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
+qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
+qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
+qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
+qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
+
+#ifdef __STDC__
+ double __ieee754_asin(double x)
+#else
+ double __ieee754_asin(x)
+ double x;
+#endif
+{
+ double t,w,p,q,c,r,s;
+ __int32_t hx,ix;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>= 0x3ff00000) { /* |x|>= 1 */
+ __uint32_t lx;
+ GET_LOW_WORD(lx,x);
+ if(((ix-0x3ff00000)|lx)==0)
+ /* asin(1)=+-pi/2 with inexact */
+ return x*pio2_hi+x*pio2_lo;
+ return (x-x)/(x-x); /* asin(|x|>1) is NaN */
+ } else if (ix<0x3fe00000) { /* |x|<0.5 */
+ if(ix<0x3e400000) { /* if |x| < 2**-27 */
+ if(huge+x>one) return x;/* return x with inexact if x!=0*/
+ } else
+ t = x*x;
+ p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+ q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+ w = p/q;
+ return x+x*w;
+ }
+ /* 1> |x|>= 0.5 */
+ w = one-fabs(x);
+ t = w*0.5;
+ p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+ q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+ s = __ieee754_sqrt(t);
+ if(ix>=0x3FEF3333) { /* if |x| > 0.975 */
+ w = p/q;
+ t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
+ } else {
+ w = s;
+ SET_LOW_WORD(w,0);
+ c = (t-w*w)/(s+w);
+ r = p/q;
+ p = 2.0*s*r-(pio2_lo-2.0*c);
+ q = pio4_hi-2.0*w;
+ t = pio4_hi-(p-q);
+ }
+ if(hx>0) return t; else return -t;
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/e_atan2.c b/libjava/java/lang/e_atan2.c
new file mode 100644
index 00000000000..8e9650f290d
--- /dev/null
+++ b/libjava/java/lang/e_atan2.c
@@ -0,0 +1,131 @@
+
+/* @(#)e_atan2.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/* __ieee754_atan2(y,x)
+ * Method :
+ * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
+ * 2. Reduce x to positive by (if x and y are unexceptional):
+ * ARG (x+iy) = arctan(y/x) ... if x > 0,
+ * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,
+ *
+ * Special cases:
+ *
+ * ATAN2((anything), NaN ) is NaN;
+ * ATAN2(NAN , (anything) ) is NaN;
+ * ATAN2(+-0, +(anything but NaN)) is +-0 ;
+ * ATAN2(+-0, -(anything but NaN)) is +-pi ;
+ * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
+ * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
+ * ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
+ * ATAN2(+-INF,+INF ) is +-pi/4 ;
+ * ATAN2(+-INF,-INF ) is +-3pi/4;
+ * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+tiny = 1.0e-300,
+zero = 0.0,
+pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
+pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
+pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
+pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
+
+#ifdef __STDC__
+ double __ieee754_atan2(double y, double x)
+#else
+ double __ieee754_atan2(y,x)
+ double y,x;
+#endif
+{
+ double z;
+ __int32_t k,m,hx,hy,ix,iy;
+ __uint32_t lx,ly;
+
+ EXTRACT_WORDS(hx,lx,x);
+ ix = hx&0x7fffffff;
+ EXTRACT_WORDS(hy,ly,y);
+ iy = hy&0x7fffffff;
+ if(((ix|((lx|-lx)>>31))>0x7ff00000)||
+ ((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */
+ return x+y;
+ if(((hx-0x3ff00000)|lx)==0) return atan(y); /* x=1.0 */
+ m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */
+
+ /* when y = 0 */
+ if((iy|ly)==0) {
+ switch(m) {
+ case 0:
+ case 1: return y; /* atan(+-0,+anything)=+-0 */
+ case 2: return pi+tiny;/* atan(+0,-anything) = pi */
+ case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+ }
+ }
+ /* when x = 0 */
+ if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+ /* when x is INF */
+ if(ix==0x7ff00000) {
+ if(iy==0x7ff00000) {
+ switch(m) {
+ case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */
+ case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
+ case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
+ case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
+ }
+ } else {
+ switch(m) {
+ case 0: return zero ; /* atan(+...,+INF) */
+ case 1: return -zero ; /* atan(-...,+INF) */
+ case 2: return pi+tiny ; /* atan(+...,-INF) */
+ case 3: return -pi-tiny ; /* atan(-...,-INF) */
+ }
+ }
+ }
+ /* when y is INF */
+ if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+ /* compute y/x */
+ k = (iy-ix)>>20;
+ if(k > 60) z=pi_o_2+0.5*pi_lo; /* |y/x| > 2**60 */
+ else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */
+ else z=atan(fabs(y/x)); /* safe to do y/x */
+ switch (m) {
+ case 0: return z ; /* atan(+,+) */
+ case 1: {
+ __uint32_t zh;
+ GET_HIGH_WORD(zh,z);
+ SET_HIGH_WORD(z,zh ^ 0x80000000);
+ }
+ return z ; /* atan(-,+) */
+ case 2: return pi-(z-pi_lo);/* atan(+,-) */
+ default: /* case 3 */
+ return (z-pi_lo)-pi;/* atan(-,-) */
+ }
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/e_exp.c b/libjava/java/lang/e_exp.c
new file mode 100644
index 00000000000..ce093c61065
--- /dev/null
+++ b/libjava/java/lang/e_exp.c
@@ -0,0 +1,167 @@
+
+/* @(#)e_exp.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_exp(x)
+ * Returns the exponential of x.
+ *
+ * Method
+ * 1. Argument reduction:
+ * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+ * Given x, find r and integer k such that
+ *
+ * x = k*ln2 + r, |r| <= 0.5*ln2.
+ *
+ * Here r will be represented as r = hi-lo for better
+ * accuracy.
+ *
+ * 2. Approximation of exp(r) by a special rational function on
+ * the interval [0,0.34658]:
+ * Write
+ * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+ * We use a special Reme algorithm on [0,0.34658] to generate
+ * a polynomial of degree 5 to approximate R. The maximum error
+ * of this polynomial approximation is bounded by 2**-59. In
+ * other words,
+ * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+ * (where z=r*r, and the values of P1 to P5 are listed below)
+ * and
+ * | 5 | -59
+ * | 2.0+P1*z+...+P5*z - R(z) | <= 2
+ * | |
+ * The computation of exp(r) thus becomes
+ * 2*r
+ * exp(r) = 1 + -------
+ * R - r
+ * r*R1(r)
+ * = 1 + r + ----------- (for better accuracy)
+ * 2 - R1(r)
+ * where
+ * 2 4 10
+ * R1(r) = r - (P1*r + P2*r + ... + P5*r ).
+ *
+ * 3. Scale back to obtain exp(x):
+ * From step 1, we have
+ * exp(x) = 2^k * exp(r)
+ *
+ * Special cases:
+ * exp(INF) is INF, exp(NaN) is NaN;
+ * exp(-INF) is 0, and
+ * for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ * For IEEE double
+ * if x > 7.09782712893383973096e+02 then exp(x) overflow
+ * if x < -7.45133219101941108420e+02 then exp(x) underflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.0,
+halF[2] = {0.5,-0.5,},
+huge = 1.0e+300,
+twom1000= 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/
+o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
+u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */
+ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */
+ -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */
+ln2LO[2] ={ 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */
+ -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */
+invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
+P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
+
+
+#ifdef __STDC__
+ double __ieee754_exp(double x) /* default IEEE double exp */
+#else
+ double __ieee754_exp(x) /* default IEEE double exp */
+ double x;
+#endif
+{
+ double y,hi,lo,c,t;
+ __int32_t k,xsb;
+ __uint32_t hx;
+
+ GET_HIGH_WORD(hx,x);
+ xsb = (hx>>31)&1; /* sign bit of x */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* filter out non-finite argument */
+ if(hx >= 0x40862E42) { /* if |x|>=709.78... */
+ if(hx>=0x7ff00000) {
+ __uint32_t lx;
+ GET_LOW_WORD(lx,x);
+ if(((hx&0xfffff)|lx)!=0)
+ return x+x; /* NaN */
+ else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */
+ }
+ if(x > o_threshold) return huge*huge; /* overflow */
+ if(x < u_threshold) return twom1000*twom1000; /* underflow */
+ }
+
+ /* argument reduction */
+ if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
+ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+ hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
+ } else {
+ k = invln2*x+halF[xsb];
+ t = k;
+ hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */
+ lo = t*ln2LO[0];
+ }
+ x = hi - lo;
+ }
+ else if(hx < 0x3e300000) { /* when |x|<2**-28 */
+ if(huge+x>one) return one+x;/* trigger inexact */
+ }
+ else k = 0;
+
+ /* x is now in primary range */
+ t = x*x;
+ c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ if(k==0) return one-((x*c)/(c-2.0)-x);
+ else y = one-((lo-(x*c)/(2.0-c))-hi);
+ if(k >= -1021) {
+ __uint32_t hy;
+ GET_HIGH_WORD(hy,y);
+ SET_HIGH_WORD(y,hy+(k<<20)); /* add k to y's exponent */
+ return y;
+ } else {
+ __uint32_t hy;
+ GET_HIGH_WORD(hy,y);
+ SET_HIGH_WORD(y,hy+((k+1000)<<20)); /* add k to y's exponent */
+ return y*twom1000;
+ }
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/e_fmod.c b/libjava/java/lang/e_fmod.c
new file mode 100644
index 00000000000..f9739eec25d
--- /dev/null
+++ b/libjava/java/lang/e_fmod.c
@@ -0,0 +1,140 @@
+
+/* @(#)e_fmod.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * __ieee754_fmod(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double one = 1.0, Zero[] = {0.0, -0.0,};
+#else
+static double one = 1.0, Zero[] = {0.0, -0.0,};
+#endif
+
+#ifdef __STDC__
+ double __ieee754_fmod(double x, double y)
+#else
+ double __ieee754_fmod(x,y)
+ double x,y ;
+#endif
+{
+ __int32_t n,hx,hy,hz,ix,iy,sx,i;
+ __uint32_t lx,ly,lz;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hy,ly,y);
+ sx = hx&0x80000000; /* sign of x */
+ hx ^=sx; /* |x| */
+ hy &= 0x7fffffff; /* |y| */
+
+ /* purge off exception values */
+ if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */
+ ((hy|((ly|-ly)>>31))>0x7ff00000)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(hx<=hy) {
+ if((hx<hy)||(lx<ly)) return x; /* |x|<|y| return x */
+ if(lx==ly)
+ return Zero[(__uint32_t)sx>>31]; /* |x|=|y| return x*0*/
+ }
+
+ /* determine ix = ilogb(x) */
+ if(hx<0x00100000) { /* subnormal x */
+ if(hx==0) {
+ for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
+ } else {
+ for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
+ }
+ } else ix = (hx>>20)-1023;
+
+ /* determine iy = ilogb(y) */
+ if(hy<0x00100000) { /* subnormal y */
+ if(hy==0) {
+ for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
+ } else {
+ for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
+ }
+ } else iy = (hy>>20)-1023;
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ if(ix >= -1022)
+ hx = 0x00100000|(0x000fffff&hx);
+ else { /* subnormal x, shift x to normal */
+ n = -1022-ix;
+ if(n<=31) {
+ hx = (hx<<n)|(lx>>(32-n));
+ lx <<= n;
+ } else {
+ hx = lx<<(n-32);
+ lx = 0;
+ }
+ }
+ if(iy >= -1022)
+ hy = 0x00100000|(0x000fffff&hy);
+ else { /* subnormal y, shift y to normal */
+ n = -1022-iy;
+ if(n<=31) {
+ hy = (hy<<n)|(ly>>(32-n));
+ ly <<= n;
+ } else {
+ hy = ly<<(n-32);
+ ly = 0;
+ }
+ }
+
+ /* fix point fmod */
+ n = ix - iy;
+ while(n--) {
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
+ else {
+ if((hz|lz)==0) /* return sign(x)*0 */
+ return Zero[(__uint32_t)sx>>31];
+ hx = hz+hz+(lz>>31); lx = lz+lz;
+ }
+ }
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz>=0) {hx=hz;lx=lz;}
+
+ /* convert back to floating value and restore the sign */
+ if((hx|lx)==0) /* return sign(x)*0 */
+ return Zero[(__uint32_t)sx>>31];
+ while(hx<0x00100000) { /* normalize x */
+ hx = hx+hx+(lx>>31); lx = lx+lx;
+ iy -= 1;
+ }
+ if(iy>= -1022) { /* normalize output */
+ hx = ((hx-0x00100000)|((iy+1023)<<20));
+ INSERT_WORDS(x,hx|sx,lx);
+ } else { /* subnormal output */
+ n = -1022 - iy;
+ if(n<=20) {
+ lx = (lx>>n)|((__uint32_t)hx<<(32-n));
+ hx >>= n;
+ } else if (n<=31) {
+ lx = (hx<<(32-n))|(lx>>n); hx = sx;
+ } else {
+ lx = hx>>(n-32); hx = sx;
+ }
+ INSERT_WORDS(x,hx|sx,lx);
+ x *= one; /* create necessary signal */
+ }
+ return x; /* exact output */
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/e_log.c b/libjava/java/lang/e_log.c
new file mode 100644
index 00000000000..ea6c55f6c36
--- /dev/null
+++ b/libjava/java/lang/e_log.c
@@ -0,0 +1,152 @@
+
+/* @(#)e_log.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_log(x)
+ * Return the logrithm of x
+ *
+ * Method :
+ * 1. Argument Reduction: find k and f such that
+ * x = 2^k * (1+f),
+ * where sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ * 2. Approximation of log(1+f).
+ * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ * = 2s + s*R
+ * We use a special Reme algorithm on [0,0.1716] to generate
+ * a polynomial of degree 14 to approximate R The maximum error
+ * of this polynomial approximation is bounded by 2**-58.45. In
+ * other words,
+ * 2 4 6 8 10 12 14
+ * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
+ * (the values of Lg1 to Lg7 are listed in the program)
+ * and
+ * | 2 14 | -58.45
+ * | Lg1*s +...+Lg7*s - R(z) | <= 2
+ * | |
+ * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ * In order to guarantee error in log below 1ulp, we compute log
+ * by
+ * log(1+f) = f - s*(f - R) (if f is not too large)
+ * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
+ *
+ * 3. Finally, log(x) = k*ln2 + log(1+f).
+ * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ * Here ln2 is split into two floating point number:
+ * ln2_hi + ln2_lo,
+ * where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ * log(x) is NaN with signal if x < 0 (including -INF) ;
+ * log(+INF) is +INF; log(0) is -INF with signal;
+ * log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
+ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
+two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
+Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
+Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
+Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
+Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
+Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
+Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
+Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
+
+#ifdef __STDC__
+static const double zero = 0.0;
+#else
+static double zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ double __ieee754_log(double x)
+#else
+ double __ieee754_log(x)
+ double x;
+#endif
+{
+ double hfsq,f,s,z,R,w,t1,t2,dk;
+ __int32_t k,hx,i,j;
+ __uint32_t lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+
+ k=0;
+ if (hx < 0x00100000) { /* x < 2**-1022 */
+ if (((hx&0x7fffffff)|lx)==0)
+ return -two54/zero; /* log(+-0)=-inf */
+ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 54; x *= two54; /* subnormal number, scale up x */
+ GET_HIGH_WORD(hx,x);
+ }
+ if (hx >= 0x7ff00000) return x+x;
+ k += (hx>>20)-1023;
+ hx &= 0x000fffff;
+ i = (hx+0x95f64)&0x100000;
+ SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */
+ k += (i>>20);
+ f = x-1.0;
+ if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */
+ if(f==zero) {
+ if(k==0)
+ return zero;
+ else {
+ dk=(double)k;
+ return dk*ln2_hi+dk*ln2_lo;
+ }
+ }
+ R = f*f*(0.5-0.33333333333333333*f);
+ if(k==0) return f-R; else {dk=(double)k;
+ return dk*ln2_hi-((R-dk*ln2_lo)-f);}
+ }
+ s = f/(2.0+f);
+ dk = (double)k;
+ z = s*s;
+ i = hx-0x6147a;
+ w = z*z;
+ j = 0x6b851-hx;
+ t1= w*(Lg2+w*(Lg4+w*Lg6));
+ t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
+ i |= j;
+ R = t2+t1;
+ if(i>0) {
+ hfsq=0.5*f*f;
+ if(k==0) return f-(hfsq-s*(hfsq+R)); else
+ return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
+ } else {
+ if(k==0) return f-s*(f-R); else
+ return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
+ }
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/e_pow.c b/libjava/java/lang/e_pow.c
new file mode 100644
index 00000000000..f078dff344d
--- /dev/null
+++ b/libjava/java/lang/e_pow.c
@@ -0,0 +1,312 @@
+
+/* @(#)e_pow.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_pow(x,y) return x**y
+ *
+ * n
+ * Method: Let x = 2 * (1+f)
+ * 1. Compute and return log2(x) in two pieces:
+ * log2(x) = w1 + w2,
+ * where w1 has 53-24 = 29 bit trailing zeros.
+ * 2. Perform y*log2(x) = n+y' by simulating muti-precision
+ * arithmetic, where |y'|<=0.5.
+ * 3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ * 1. (anything) ** 0 is 1
+ * 2. (anything) ** 1 is itself
+ * 3. (anything) ** NAN is NAN
+ * 4. NAN ** (anything except 0) is NAN
+ * 5. +-(|x| > 1) ** +INF is +INF
+ * 6. +-(|x| > 1) ** -INF is +0
+ * 7. +-(|x| < 1) ** +INF is +0
+ * 8. +-(|x| < 1) ** -INF is +INF
+ * 9. +-1 ** +-INF is NAN
+ * 10. +0 ** (+anything except 0, NAN) is +0
+ * 11. -0 ** (+anything except 0, NAN, odd integer) is +0
+ * 12. +0 ** (-anything except 0, NAN) is +INF
+ * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
+ * 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ * 15. +INF ** (+anything except 0,NAN) is +INF
+ * 16. +INF ** (-anything except 0,NAN) is +0
+ * 17. -INF ** (anything) = -0 ** (-anything)
+ * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ * 19. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ * Accuracy:
+ * pow(x,y) returns x**y nearly rounded. In particular
+ * pow(integer,integer)
+ * always returns the correct integer provided it is
+ * representable.
+ *
+ * Constants :
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
+dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
+zero = 0.0,
+one = 1.0,
+two = 2.0,
+two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
+huge = 1.0e300,
+tiny = 1.0e-300,
+ /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
+L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
+L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
+L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
+L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
+L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
+P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
+lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
+lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
+ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
+cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
+cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
+cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
+ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
+ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
+ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
+
+#ifdef __STDC__
+ double __ieee754_pow(double x, double y)
+#else
+ double __ieee754_pow(x,y)
+ double x, y;
+#endif
+{
+ double z,ax,z_h,z_l,p_h,p_l;
+ double y1,t1,t2,r,s,t,u,v,w;
+ __int32_t i,j,k,yisint,n;
+ __int32_t hx,hy,ix,iy;
+ __uint32_t lx,ly;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hy,ly,y);
+ ix = hx&0x7fffffff; iy = hy&0x7fffffff;
+
+ /* y==zero: x**0 = 1 */
+ if((iy|ly)==0) return one;
+
+ /* +-NaN return x+y */
+ if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
+ iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
+ return x+y;
+
+ /* determine if y is an odd int when x < 0
+ * yisint = 0 ... y is not an integer
+ * yisint = 1 ... y is an odd int
+ * yisint = 2 ... y is an even int
+ */
+ yisint = 0;
+ if(hx<0) {
+ if(iy>=0x43400000) yisint = 2; /* even integer y */
+ else if(iy>=0x3ff00000) {
+ k = (iy>>20)-0x3ff; /* exponent */
+ if(k>20) {
+ j = ly>>(52-k);
+ if((__uint32_t)(j<<(52-k))==ly) yisint = 2-(j&1);
+ } else if(ly==0) {
+ j = iy>>(20-k);
+ if((j<<(20-k))==iy) yisint = 2-(j&1);
+ }
+ }
+ }
+
+ /* special value of y */
+ if(ly==0) {
+ if (iy==0x7ff00000) { /* y is +-inf */
+ if(((ix-0x3ff00000)|lx)==0)
+ return y - y; /* inf**+-1 is NaN */
+ else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
+ return (hy>=0)? y: zero;
+ else /* (|x|<1)**-,+inf = inf,0 */
+ return (hy<0)?-y: zero;
+ }
+ if(iy==0x3ff00000) { /* y is +-1 */
+ if(hy<0) return one/x; else return x;
+ }
+ if(hy==0x40000000) return x*x; /* y is 2 */
+ if(hy==0x3fe00000) { /* y is 0.5 */
+ if(hx>=0) /* x >= +0 */
+ return __ieee754_sqrt(x);
+ }
+ }
+
+ ax = fabs(x);
+ /* special value of x */
+ if(lx==0) {
+ if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
+ z = ax; /*x is +-0,+-inf,+-1*/
+ if(hy<0) z = one/z; /* z = (1/|x|) */
+ if(hx<0) {
+ if(((ix-0x3ff00000)|yisint)==0) {
+ z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+ } else if(yisint==1)
+ z = -z; /* (x<0)**odd = -(|x|**odd) */
+ }
+ return z;
+ }
+ }
+
+ /* (x<0)**(non-int) is NaN */
+ /* CYGNUS LOCAL: This used to be
+ if((((hx>>31)+1)|yisint)==0) return (x-x)/(x-x);
+ but ANSI C says a right shift of a signed negative quantity is
+ implementation defined. */
+ if(((((__uint32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x);
+
+ /* |y| is huge */
+ if(iy>0x41e00000) { /* if |y| > 2**31 */
+ if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */
+ if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+ if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+ }
+ /* over/underflow if x is not close to one */
+ if(ix<0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+ if(ix>0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+ /* now |1-x| is tiny <= 2**-20, suffice to compute
+ log(x) by x-x^2/2+x^3/3-x^4/4 */
+ t = x-1; /* t has 20 trailing zeros */
+ w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
+ u = ivln2_h*t; /* ivln2_h has 21 sig. bits */
+ v = t*ivln2_l-w*ivln2;
+ t1 = u+v;
+ SET_LOW_WORD(t1,0);
+ t2 = v-(t1-u);
+ } else {
+ double s2,s_h,s_l,t_h,t_l;
+ n = 0;
+ /* take care subnormal number */
+ if(ix<0x00100000)
+ {ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); }
+ n += ((ix)>>20)-0x3ff;
+ j = ix&0x000fffff;
+ /* determine interval */
+ ix = j|0x3ff00000; /* normalize ix */
+ if(j<=0x3988E) k=0; /* |x|<sqrt(3/2) */
+ else if(j<0xBB67A) k=1; /* |x|<sqrt(3) */
+ else {k=0;n+=1;ix -= 0x00100000;}
+ SET_HIGH_WORD(ax,ix);
+
+ /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+ u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
+ v = one/(ax+bp[k]);
+ s = u*v;
+ s_h = s;
+ SET_LOW_WORD(s_h,0);
+ /* t_h=ax+bp[k] High */
+ t_h = zero;
+ SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18));
+ t_l = ax - (t_h-bp[k]);
+ s_l = v*((u-s_h*t_h)-s_h*t_l);
+ /* compute log(ax) */
+ s2 = s*s;
+ r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+ r += s_l*(s_h+s);
+ s2 = s_h*s_h;
+ t_h = 3.0+s2+r;
+ SET_LOW_WORD(t_h,0);
+ t_l = r-((t_h-3.0)-s2);
+ /* u+v = s*(1+...) */
+ u = s_h*t_h;
+ v = s_l*t_h+t_l*s;
+ /* 2/(3log2)*(s+...) */
+ p_h = u+v;
+ SET_LOW_WORD(p_h,0);
+ p_l = v-(p_h-u);
+ z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
+ z_l = cp_l*p_h+p_l*cp+dp_l[k];
+ /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+ t = (double)n;
+ t1 = (((z_h+z_l)+dp_h[k])+t);
+ SET_LOW_WORD(t1,0);
+ t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+ }
+
+ s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+ if(((((__uint32_t)hx>>31)-1)|(yisint-1))==0)
+ s = -one;/* (-ve)**(odd int) */
+
+ /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+ y1 = y;
+ SET_LOW_WORD(y1,0);
+ p_l = (y-y1)*t1+y*t2;
+ p_h = y1*t1;
+ z = p_l+p_h;
+ EXTRACT_WORDS(j,i,z);
+ if (j>=0x40900000) { /* z >= 1024 */
+ if(((j-0x40900000)|i)!=0) /* if z > 1024 */
+ return s*huge*huge; /* overflow */
+ else {
+ if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
+ }
+ } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */
+ if(((j-0xc090cc00)|i)!=0) /* z < -1075 */
+ return s*tiny*tiny; /* underflow */
+ else {
+ if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
+ }
+ }
+ /*
+ * compute 2**(p_h+p_l)
+ */
+ i = j&0x7fffffff;
+ k = (i>>20)-0x3ff;
+ n = 0;
+ if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
+ n = j+(0x00100000>>(k+1));
+ k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */
+ t = zero;
+ SET_HIGH_WORD(t,n&~(0x000fffff>>k));
+ n = ((n&0x000fffff)|0x00100000)>>(20-k);
+ if(j<0) n = -n;
+ p_h -= t;
+ }
+ t = p_l+p_h;
+ SET_LOW_WORD(t,0);
+ u = t*lg2_h;
+ v = (p_l-(t-p_h))*lg2+t*lg2_l;
+ z = u+v;
+ w = v-(z-u);
+ t = z*z;
+ t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ r = (z*t1)/(t1-two)-(w+z*w);
+ z = one-(r-z);
+ GET_HIGH_WORD(j,z);
+ j += (n<<20);
+ if((j>>20)<=0) z = scalbn(z,(int)n); /* subnormal output */
+ else SET_HIGH_WORD(z,j);
+ return s*z;
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/e_rem_pio2.c b/libjava/java/lang/e_rem_pio2.c
new file mode 100644
index 00000000000..3e5d0f7a227
--- /dev/null
+++ b/libjava/java/lang/e_rem_pio2.c
@@ -0,0 +1,185 @@
+
+/* @(#)e_rem_pio2.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/* __ieee754_rem_pio2(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2()
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ */
+#ifdef __STDC__
+static const __int32_t two_over_pi[] = {
+#else
+static __int32_t two_over_pi[] = {
+#endif
+0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
+0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
+0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
+0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
+0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
+0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
+0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
+0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
+0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
+0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
+0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
+};
+
+#ifdef __STDC__
+static const __int32_t npio2_hw[] = {
+#else
+static __int32_t npio2_hw[] = {
+#endif
+0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
+0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
+0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
+0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
+0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
+0x404858EB, 0x404921FB,
+};
+
+/*
+ * invpio2: 53 bits of 2/pi
+ * pio2_1: first 33 bit of pi/2
+ * pio2_1t: pi/2 - pio2_1
+ * pio2_2: second 33 bit of pi/2
+ * pio2_2t: pi/2 - (pio2_1+pio2_2)
+ * pio2_3: third 33 bit of pi/2
+ * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
+pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
+pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
+pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
+pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
+pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
+
+#ifdef __STDC__
+ __int32_t __ieee754_rem_pio2(double x, double *y)
+#else
+ __int32_t __ieee754_rem_pio2(x,y)
+ double x,y[];
+#endif
+{
+ double z,w,t,r,fn;
+ double tx[3];
+ __int32_t i,j,n,ix,hx;
+ int e0,nx;
+ __uint32_t low;
+
+ GET_HIGH_WORD(hx,x); /* high word of x */
+ ix = hx&0x7fffffff;
+ if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */
+ {y[0] = x; y[1] = 0; return 0;}
+ if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */
+ if(hx>0) {
+ z = x - pio2_1;
+ if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */
+ y[0] = z - pio2_1t;
+ y[1] = (z-y[0])-pio2_1t;
+ } else { /* near pi/2, use 33+33+53 bit pi */
+ z -= pio2_2;
+ y[0] = z - pio2_2t;
+ y[1] = (z-y[0])-pio2_2t;
+ }
+ return 1;
+ } else { /* negative x */
+ z = x + pio2_1;
+ if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */
+ y[0] = z + pio2_1t;
+ y[1] = (z-y[0])+pio2_1t;
+ } else { /* near pi/2, use 33+33+53 bit pi */
+ z += pio2_2;
+ y[0] = z + pio2_2t;
+ y[1] = (z-y[0])+pio2_2t;
+ }
+ return -1;
+ }
+ }
+ if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
+ t = fabs(x);
+ n = (__int32_t) (t*invpio2+half);
+ fn = (double)n;
+ r = t-fn*pio2_1;
+ w = fn*pio2_1t; /* 1st round good to 85 bit */
+ if(n<32&&ix!=npio2_hw[n-1]) {
+ y[0] = r-w; /* quick check no cancellation */
+ } else {
+ __uint32_t high;
+ j = ix>>20;
+ y[0] = r-w;
+ GET_HIGH_WORD(high,y[0]);
+ i = j-((high>>20)&0x7ff);
+ if(i>16) { /* 2nd iteration needed, good to 118 */
+ t = r;
+ w = fn*pio2_2;
+ r = t-w;
+ w = fn*pio2_2t-((t-r)-w);
+ y[0] = r-w;
+ GET_HIGH_WORD(high,y[0]);
+ i = j-((high>>20)&0x7ff);
+ if(i>49) { /* 3rd iteration need, 151 bits acc */
+ t = r; /* will cover all possible cases */
+ w = fn*pio2_3;
+ r = t-w;
+ w = fn*pio2_3t-((t-r)-w);
+ y[0] = r-w;
+ }
+ }
+ }
+ y[1] = (r-y[0])-w;
+ if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+ else return n;
+ }
+ /*
+ * all other (large) arguments
+ */
+ if(ix>=0x7ff00000) { /* x is inf or NaN */
+ y[0]=y[1]=x-x; return 0;
+ }
+ /* set z = scalbn(|x|,ilogb(x)-23) */
+ GET_LOW_WORD(low,x);
+ SET_LOW_WORD(z,low);
+ e0 = (int)((ix>>20)-1046); /* e0 = ilogb(z)-23; */
+ SET_HIGH_WORD(z, ix - ((__int32_t)e0<<20));
+ for(i=0;i<2;i++) {
+ tx[i] = (double)((__int32_t)(z));
+ z = (z-tx[i])*two24;
+ }
+ tx[2] = z;
+ nx = 3;
+ while(tx[nx-1]==zero) nx--; /* skip zero term */
+ n = __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi);
+ if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+ return n;
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/e_remainder.c b/libjava/java/lang/e_remainder.c
new file mode 100644
index 00000000000..ae7ce649ad5
--- /dev/null
+++ b/libjava/java/lang/e_remainder.c
@@ -0,0 +1,80 @@
+
+/* @(#)e_remainder.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_remainder(x,p)
+ * Return :
+ * returns x REM p = x - [x/p]*p as if in infinite
+ * precise arithmetic, where [x/p] is the (infinite bit)
+ * integer nearest x/p (in half way case choose the even one).
+ * Method :
+ * Based on fmod() return x-[x/p]chopped*p exactlp.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double zero = 0.0;
+#else
+static double zero = 0.0;
+#endif
+
+
+#ifdef __STDC__
+ double __ieee754_remainder(double x, double p)
+#else
+ double __ieee754_remainder(x,p)
+ double x,p;
+#endif
+{
+ __int32_t hx,hp;
+ __uint32_t sx,lx,lp;
+ double p_half;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hp,lp,p);
+ sx = hx&0x80000000;
+ hp &= 0x7fffffff;
+ hx &= 0x7fffffff;
+
+ /* purge off exception values */
+ if((hp|lp)==0) return (x*p)/(x*p); /* p = 0 */
+ if((hx>=0x7ff00000)|| /* x not finite */
+ ((hp>=0x7ff00000)&& /* p is NaN */
+ (((hp-0x7ff00000)|lp)!=0)))
+ return (x*p)/(x*p);
+
+
+ if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p); /* now x < 2p */
+ if (((hx-hp)|(lx-lp))==0) return zero*x;
+ x = fabs(x);
+ p = fabs(p);
+ if (hp<0x00200000) {
+ if(x+x>p) {
+ x-=p;
+ if(x+x>=p) x -= p;
+ }
+ } else {
+ p_half = 0.5*p;
+ if(x>p_half) {
+ x-=p;
+ if(x>=p_half) x -= p;
+ }
+ }
+ GET_HIGH_WORD(hx,x);
+ SET_HIGH_WORD(x,hx^sx);
+ return x;
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/e_scalb.c b/libjava/java/lang/e_scalb.c
new file mode 100644
index 00000000000..0bb924b43ee
--- /dev/null
+++ b/libjava/java/lang/e_scalb.c
@@ -0,0 +1,55 @@
+
+/* @(#)e_scalb.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * __ieee754_scalb(x, fn) is provide for
+ * passing various standard test suite. One
+ * should use scalbn() instead.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef _SCALB_INT
+#ifdef __STDC__
+ double __ieee754_scalb(double x, int fn)
+#else
+ double __ieee754_scalb(x,fn)
+ double x; int fn;
+#endif
+#else
+#ifdef __STDC__
+ double __ieee754_scalb(double x, double fn)
+#else
+ double __ieee754_scalb(x,fn)
+ double x, fn;
+#endif
+#endif
+{
+#ifdef _SCALB_INT
+ return scalbn(x,fn);
+#else
+ if (isnan(x)||isnan(fn)) return x*fn;
+ if (!finite(fn)) {
+ if(fn>0.0) return x*fn;
+ else return x/(-fn);
+ }
+ if (rint(fn)!=fn) return (fn-fn)/(fn-fn);
+ if ( fn > 65000.0) return scalbn(x, 65000);
+ if (-fn > 65000.0) return scalbn(x,-65000);
+ return scalbn(x,(int)fn);
+#endif
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/e_sqrt.c b/libjava/java/lang/e_sqrt.c
new file mode 100644
index 00000000000..b56b1eedc94
--- /dev/null
+++ b/libjava/java/lang/e_sqrt.c
@@ -0,0 +1,452 @@
+
+/* @(#)e_sqrt.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_sqrt(x)
+ * Return correctly rounded sqrt.
+ * ------------------------------------------
+ * | Use the hardware sqrt if you have one |
+ * ------------------------------------------
+ * Method:
+ * Bit by bit method using integer arithmetic. (Slow, but portable)
+ * 1. Normalization
+ * Scale x to y in [1,4) with even powers of 2:
+ * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then
+ * sqrt(x) = 2^k * sqrt(y)
+ * 2. Bit by bit computation
+ * Let q = sqrt(y) truncated to i bit after binary point (q = 1),
+ * i 0
+ * i+1 2
+ * s = 2*q , and y = 2 * ( y - q ). (1)
+ * i i i i
+ *
+ * To compute q from q , one checks whether
+ * i+1 i
+ *
+ * -(i+1) 2
+ * (q + 2 ) <= y. (2)
+ * i
+ * -(i+1)
+ * If (2) is false, then q = q ; otherwise q = q + 2 .
+ * i+1 i i+1 i
+ *
+ * With some algebric manipulation, it is not difficult to see
+ * that (2) is equivalent to
+ * -(i+1)
+ * s + 2 <= y (3)
+ * i i
+ *
+ * The advantage of (3) is that s and y can be computed by
+ * i i
+ * the following recurrence formula:
+ * if (3) is false
+ *
+ * s = s , y = y ; (4)
+ * i+1 i i+1 i
+ *
+ * otherwise,
+ * -i -(i+1)
+ * s = s + 2 , y = y - s - 2 (5)
+ * i+1 i i+1 i i
+ *
+ * One may easily use induction to prove (4) and (5).
+ * Note. Since the left hand side of (3) contain only i+2 bits,
+ * it does not necessary to do a full (53-bit) comparison
+ * in (3).
+ * 3. Final rounding
+ * After generating the 53 bits result, we compute one more bit.
+ * Together with the remainder, we can decide whether the
+ * result is exact, bigger than 1/2ulp, or less than 1/2ulp
+ * (it will never equal to 1/2ulp).
+ * The rounding mode can be detected by checking whether
+ * huge + tiny is equal to huge, and whether huge - tiny is
+ * equal to huge for some floating point number "huge" and "tiny".
+ *
+ * Special cases:
+ * sqrt(+-0) = +-0 ... exact
+ * sqrt(inf) = inf
+ * sqrt(-ve) = NaN ... with invalid signal
+ * sqrt(NaN) = NaN ... with invalid signal for signaling NaN
+ *
+ * Other methods : see the appended file at the end of the program below.
+ *---------------
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double one = 1.0, tiny=1.0e-300;
+#else
+static double one = 1.0, tiny=1.0e-300;
+#endif
+
+#ifdef __STDC__
+ double __ieee754_sqrt(double x)
+#else
+ double __ieee754_sqrt(x)
+ double x;
+#endif
+{
+ double z;
+ __int32_t sign = (int)0x80000000;
+ __uint32_t r,t1,s1,ix1,q1;
+ __int32_t ix0,s0,q,m,t,i;
+
+ EXTRACT_WORDS(ix0,ix1,x);
+
+ /* take care of Inf and NaN */
+ if((ix0&0x7ff00000)==0x7ff00000) {
+ return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+ sqrt(-inf)=sNaN */
+ }
+ /* take care of zero */
+ if(ix0<=0) {
+ if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
+ else if(ix0<0)
+ return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
+ }
+ /* normalize x */
+ m = (ix0>>20);
+ if(m==0) { /* subnormal x */
+ while(ix0==0) {
+ m -= 21;
+ ix0 |= (ix1>>11); ix1 <<= 21;
+ }
+ for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
+ m -= i-1;
+ ix0 |= (ix1>>(32-i));
+ ix1 <<= i;
+ }
+ m -= 1023; /* unbias exponent */
+ ix0 = (ix0&0x000fffff)|0x00100000;
+ if(m&1){ /* odd m, double x to make it even */
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ }
+ m >>= 1; /* m = [m/2] */
+
+ /* generate sqrt(x) bit by bit */
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
+ r = 0x00200000; /* r = moving bit from right to left */
+
+ while(r!=0) {
+ t = s0+r;
+ if(t<=ix0) {
+ s0 = t+r;
+ ix0 -= t;
+ q += r;
+ }
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ r>>=1;
+ }
+
+ r = sign;
+ while(r!=0) {
+ t1 = s1+r;
+ t = s0;
+ if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
+ s1 = t1+r;
+ if(((t1&sign)==(__uint32_t)sign)&&(s1&sign)==0) s0 += 1;
+ ix0 -= t;
+ if (ix1 < t1) ix0 -= 1;
+ ix1 -= t1;
+ q1 += r;
+ }
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ r>>=1;
+ }
+
+ /* use floating add to find out rounding direction */
+ if((ix0|ix1)!=0) {
+ z = one-tiny; /* trigger inexact flag */
+ if (z>=one) {
+ z = one+tiny;
+ if (q1==(__uint32_t)0xffffffff) { q1=0; q += 1;}
+ else if (z>one) {
+ if (q1==(__uint32_t)0xfffffffe) q+=1;
+ q1+=2;
+ } else
+ q1 += (q1&1);
+ }
+ }
+ ix0 = (q>>1)+0x3fe00000;
+ ix1 = q1>>1;
+ if ((q&1)==1) ix1 |= sign;
+ ix0 += (m <<20);
+ INSERT_WORDS(z,ix0,ix1);
+ return z;
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
+
+/*
+Other methods (use floating-point arithmetic)
+-------------
+(This is a copy of a drafted paper by Prof W. Kahan
+and K.C. Ng, written in May, 1986)
+
+ Two algorithms are given here to implement sqrt(x)
+ (IEEE double precision arithmetic) in software.
+ Both supply sqrt(x) correctly rounded. The first algorithm (in
+ Section A) uses newton iterations and involves four divisions.
+ The second one uses reciproot iterations to avoid division, but
+ requires more multiplications. Both algorithms need the ability
+ to chop results of arithmetic operations instead of round them,
+ and the INEXACT flag to indicate when an arithmetic operation
+ is executed exactly with no roundoff error, all part of the
+ standard (IEEE 754-1985). The ability to perform shift, add,
+ subtract and logical AND operations upon 32-bit words is needed
+ too, though not part of the standard.
+
+A. sqrt(x) by Newton Iteration
+
+ (1) Initial approximation
+
+ Let x0 and x1 be the leading and the trailing 32-bit words of
+ a floating point number x (in IEEE double format) respectively
+
+ 1 11 52 ...widths
+ ------------------------------------------------------
+ x: |s| e | f |
+ ------------------------------------------------------
+ msb lsb msb lsb ...order
+
+
+ ------------------------ ------------------------
+ x0: |s| e | f1 | x1: | f2 |
+ ------------------------ ------------------------
+
+ By performing shifts and subtracts on x0 and x1 (both regarded
+ as integers), we obtain an 8-bit approximation of sqrt(x) as
+ follows.
+
+ k := (x0>>1) + 0x1ff80000;
+ y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits
+ Here k is a 32-bit integer and T1[] is an integer array containing
+ correction terms. Now magically the floating value of y (y's
+ leading 32-bit word is y0, the value of its trailing word is 0)
+ approximates sqrt(x) to almost 8-bit.
+
+ Value of T1:
+ static int T1[32]= {
+ 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592,
+ 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215,
+ 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581,
+ 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,};
+
+ (2) Iterative refinement
+
+ Apply Heron's rule three times to y, we have y approximates
+ sqrt(x) to within 1 ulp (Unit in the Last Place):
+
+ y := (y+x/y)/2 ... almost 17 sig. bits
+ y := (y+x/y)/2 ... almost 35 sig. bits
+ y := y-(y-x/y)/2 ... within 1 ulp
+
+
+ Remark 1.
+ Another way to improve y to within 1 ulp is:
+
+ y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x)
+ y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x)
+
+ 2
+ (x-y )*y
+ y := y + 2* ---------- ...within 1 ulp
+ 2
+ 3y + x
+
+
+ This formula has one division fewer than the one above; however,
+ it requires more multiplications and additions. Also x must be
+ scaled in advance to avoid spurious overflow in evaluating the
+ expression 3y*y+x. Hence it is not recommended uless division
+ is slow. If division is very slow, then one should use the
+ reciproot algorithm given in section B.
+
+ (3) Final adjustment
+
+ By twiddling y's last bit it is possible to force y to be
+ correctly rounded according to the prevailing rounding mode
+ as follows. Let r and i be copies of the rounding mode and
+ inexact flag before entering the square root program. Also we
+ use the expression y+-ulp for the next representable floating
+ numbers (up and down) of y. Note that y+-ulp = either fixed
+ point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+ mode.
+
+ I := FALSE; ... reset INEXACT flag I
+ R := RZ; ... set rounding mode to round-toward-zero
+ z := x/y; ... chopped quotient, possibly inexact
+ If(not I) then { ... if the quotient is exact
+ if(z=y) {
+ I := i; ... restore inexact flag
+ R := r; ... restore rounded mode
+ return sqrt(x):=y.
+ } else {
+ z := z - ulp; ... special rounding
+ }
+ }
+ i := TRUE; ... sqrt(x) is inexact
+ If (r=RN) then z=z+ulp ... rounded-to-nearest
+ If (r=RP) then { ... round-toward-+inf
+ y = y+ulp; z=z+ulp;
+ }
+ y := y+z; ... chopped sum
+ y0:=y0-0x00100000; ... y := y/2 is correctly rounded.
+ I := i; ... restore inexact flag
+ R := r; ... restore rounded mode
+ return sqrt(x):=y.
+
+ (4) Special cases
+
+ Square root of +inf, +-0, or NaN is itself;
+ Square root of a negative number is NaN with invalid signal.
+
+
+B. sqrt(x) by Reciproot Iteration
+
+ (1) Initial approximation
+
+ Let x0 and x1 be the leading and the trailing 32-bit words of
+ a floating point number x (in IEEE double format) respectively
+ (see section A). By performing shifs and subtracts on x0 and y0,
+ we obtain a 7.8-bit approximation of 1/sqrt(x) as follows.
+
+ k := 0x5fe80000 - (x0>>1);
+ y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits
+
+ Here k is a 32-bit integer and T2[] is an integer array
+ containing correction terms. Now magically the floating
+ value of y (y's leading 32-bit word is y0, the value of
+ its trailing word y1 is set to zero) approximates 1/sqrt(x)
+ to almost 7.8-bit.
+
+ Value of T2:
+ static int T2[64]= {
+ 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866,
+ 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f,
+ 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d,
+ 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0,
+ 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989,
+ 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd,
+ 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e,
+ 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,};
+
+ (2) Iterative refinement
+
+ Apply Reciproot iteration three times to y and multiply the
+ result by x to get an approximation z that matches sqrt(x)
+ to about 1 ulp. To be exact, we will have
+ -1ulp < sqrt(x)-z<1.0625ulp.
+
+ ... set rounding mode to Round-to-nearest
+ y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x)
+ y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x)
+ ... special arrangement for better accuracy
+ z := x*y ... 29 bits to sqrt(x), with z*y<1
+ z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x)
+
+ Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that
+ (a) the term z*y in the final iteration is always less than 1;
+ (b) the error in the final result is biased upward so that
+ -1 ulp < sqrt(x) - z < 1.0625 ulp
+ instead of |sqrt(x)-z|<1.03125ulp.
+
+ (3) Final adjustment
+
+ By twiddling y's last bit it is possible to force y to be
+ correctly rounded according to the prevailing rounding mode
+ as follows. Let r and i be copies of the rounding mode and
+ inexact flag before entering the square root program. Also we
+ use the expression y+-ulp for the next representable floating
+ numbers (up and down) of y. Note that y+-ulp = either fixed
+ point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+ mode.
+
+ R := RZ; ... set rounding mode to round-toward-zero
+ switch(r) {
+ case RN: ... round-to-nearest
+ if(x<= z*(z-ulp)...chopped) z = z - ulp; else
+ if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp;
+ break;
+ case RZ:case RM: ... round-to-zero or round-to--inf
+ R:=RP; ... reset rounding mod to round-to-+inf
+ if(x<z*z ... rounded up) z = z - ulp; else
+ if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp;
+ break;
+ case RP: ... round-to-+inf
+ if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else
+ if(x>z*z ...chopped) z = z+ulp;
+ break;
+ }
+
+ Remark 3. The above comparisons can be done in fixed point. For
+ example, to compare x and w=z*z chopped, it suffices to compare
+ x1 and w1 (the trailing parts of x and w), regarding them as
+ two's complement integers.
+
+ ...Is z an exact square root?
+ To determine whether z is an exact square root of x, let z1 be the
+ trailing part of z, and also let x0 and x1 be the leading and
+ trailing parts of x.
+
+ If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0
+ I := 1; ... Raise Inexact flag: z is not exact
+ else {
+ j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2
+ k := z1 >> 26; ... get z's 25-th and 26-th
+ fraction bits
+ I := i or (k&j) or ((k&(j+j+1))!=(x1&3));
+ }
+ R:= r ... restore rounded mode
+ return sqrt(x):=z.
+
+ If multiplication is cheaper then the foregoing red tape, the
+ Inexact flag can be evaluated by
+
+ I := i;
+ I := (z*z!=x) or I.
+
+ Note that z*z can overwrite I; this value must be sensed if it is
+ True.
+
+ Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be
+ zero.
+
+ --------------------
+ z1: | f2 |
+ --------------------
+ bit 31 bit 0
+
+ Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd
+ or even of logb(x) have the following relations:
+
+ -------------------------------------------------
+ bit 27,26 of z1 bit 1,0 of x1 logb(x)
+ -------------------------------------------------
+ 00 00 odd and even
+ 01 01 even
+ 10 10 odd
+ 10 00 even
+ 11 01 even
+ -------------------------------------------------
+
+ (4) Special cases (see (4) of Section A).
+
+ */
diff --git a/libjava/java/lang/fdlibm.h b/libjava/java/lang/fdlibm.h
new file mode 100644
index 00000000000..3f72070cf81
--- /dev/null
+++ b/libjava/java/lang/fdlibm.h
@@ -0,0 +1,343 @@
+
+/* @(#)fdlibm.h 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <config.h>
+#include <stdlib.h>
+
+/* CYGNUS LOCAL: Include files. */
+#include "ieeefp.h"
+
+/* CYGNUS LOCAL: Default to XOPEN_MODE. */
+#define _XOPEN_MODE
+
+#ifdef __STDC__
+#define __P(p) p
+#else
+#define __P(p) ()
+#endif
+
+#define HUGE ((float)3.40282346638528860e+38)
+
+/*
+ * set X_TLOSS = pi*2**52, which is possibly defined in <values.h>
+ * (one may replace the following line by "#include <values.h>")
+ */
+
+#define X_TLOSS 1.41484755040568800000e+16
+
+/* These typedefs are true for the targets running Java. */
+
+#ifndef HAVE_INT32_DEFINED
+typedef int __int32_t;
+typedef unsigned int __uint32_t;
+#endif
+
+#define _IEEE_LIBM
+
+/*
+ * ANSI/POSIX
+ */
+extern double acos __P((double));
+extern double asin __P((double));
+extern double atan __P((double));
+extern double atan2 __P((double, double));
+extern double cos __P((double));
+extern double sin __P((double));
+extern double tan __P((double));
+
+extern double cosh __P((double));
+extern double sinh __P((double));
+extern double tanh __P((double));
+
+extern double exp __P((double));
+extern double frexp __P((double, int *));
+extern double ldexp __P((double, int));
+extern double log __P((double));
+extern double log10 __P((double));
+extern double modf __P((double, double *));
+
+extern double pow __P((double, double));
+extern double sqrt __P((double));
+
+extern double ceil __P((double));
+extern double fabs __P((double));
+extern double floor __P((double));
+extern double fmod __P((double, double));
+
+extern double erf __P((double));
+extern double erfc __P((double));
+extern double gamma __P((double));
+extern double hypot __P((double, double));
+extern int isnan __P((double));
+extern int finite __P((double));
+extern double j0 __P((double));
+extern double j1 __P((double));
+extern double jn __P((int, double));
+extern double lgamma __P((double));
+extern double y0 __P((double));
+extern double y1 __P((double));
+extern double yn __P((int, double));
+
+extern double acosh __P((double));
+extern double asinh __P((double));
+extern double atanh __P((double));
+extern double cbrt __P((double));
+extern double logb __P((double));
+extern double nextafter __P((double, double));
+extern double remainder __P((double, double));
+
+/* Functions that are not documented, and are not in <math.h>. */
+
+extern double logb __P((double));
+#ifdef _SCALB_INT
+extern double scalb __P((double, int));
+#else
+extern double scalb __P((double, double));
+#endif
+extern double significand __P((double));
+
+/* ieee style elementary functions */
+extern double __ieee754_sqrt __P((double));
+extern double __ieee754_acos __P((double));
+extern double __ieee754_acosh __P((double));
+extern double __ieee754_log __P((double));
+extern double __ieee754_atanh __P((double));
+extern double __ieee754_asin __P((double));
+extern double __ieee754_atan2 __P((double,double));
+extern double __ieee754_exp __P((double));
+extern double __ieee754_cosh __P((double));
+extern double __ieee754_fmod __P((double,double));
+extern double __ieee754_pow __P((double,double));
+extern double __ieee754_lgamma_r __P((double,int *));
+extern double __ieee754_gamma_r __P((double,int *));
+extern double __ieee754_log10 __P((double));
+extern double __ieee754_sinh __P((double));
+extern double __ieee754_hypot __P((double,double));
+extern double __ieee754_j0 __P((double));
+extern double __ieee754_j1 __P((double));
+extern double __ieee754_y0 __P((double));
+extern double __ieee754_y1 __P((double));
+extern double __ieee754_jn __P((int,double));
+extern double __ieee754_yn __P((int,double));
+extern double __ieee754_remainder __P((double,double));
+extern __int32_t __ieee754_rem_pio2 __P((double,double*));
+#ifdef _SCALB_INT
+extern double __ieee754_scalb __P((double,int));
+#else
+extern double __ieee754_scalb __P((double,double));
+#endif
+
+/* fdlibm kernel function */
+extern double __kernel_standard __P((double,double,int));
+extern double __kernel_sin __P((double,double,int));
+extern double __kernel_cos __P((double,double));
+extern double __kernel_tan __P((double,double,int));
+extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const __int32_t*));
+
+/* Undocumented float functions. */
+extern float logbf __P((float));
+#ifdef _SCALB_INT
+extern float scalbf __P((float, int));
+#else
+extern float scalbf __P((float, float));
+#endif
+extern float significandf __P((float));
+
+/*
+ * Functions callable from C, intended to support IEEE arithmetic.
+ */
+extern double copysign __P((double, double));
+extern int ilogb __P((double));
+extern double rint __P((double));
+extern float rintf __P((float));
+extern double scalbn __P((double, int));
+
+/* ieee style elementary float functions */
+extern float __ieee754_sqrtf __P((float));
+extern float __ieee754_acosf __P((float));
+extern float __ieee754_acoshf __P((float));
+extern float __ieee754_logf __P((float));
+extern float __ieee754_atanhf __P((float));
+extern float __ieee754_asinf __P((float));
+extern float __ieee754_atan2f __P((float,float));
+extern float __ieee754_expf __P((float));
+extern float __ieee754_coshf __P((float));
+extern float __ieee754_fmodf __P((float,float));
+extern float __ieee754_powf __P((float,float));
+extern float __ieee754_lgammaf_r __P((float,int *));
+extern float __ieee754_gammaf_r __P((float,int *));
+extern float __ieee754_log10f __P((float));
+extern float __ieee754_sinhf __P((float));
+extern float __ieee754_hypotf __P((float,float));
+extern float __ieee754_j0f __P((float));
+extern float __ieee754_j1f __P((float));
+extern float __ieee754_y0f __P((float));
+extern float __ieee754_y1f __P((float));
+extern float __ieee754_jnf __P((int,float));
+extern float __ieee754_ynf __P((int,float));
+extern float __ieee754_remainderf __P((float,float));
+extern __int32_t __ieee754_rem_pio2f __P((float,float*));
+#ifdef _SCALB_INT
+extern float __ieee754_scalbf __P((float,int));
+#else
+extern float __ieee754_scalbf __P((float,float));
+#endif
+
+/* float versions of fdlibm kernel functions */
+extern float __kernel_sinf __P((float,float,int));
+extern float __kernel_cosf __P((float,float));
+extern float __kernel_tanf __P((float,float,int));
+extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const __int32_t*));
+
+/* The original code used statements like
+ n0 = ((*(int*)&one)>>29)^1; * index of high word *
+ ix0 = *(n0+(int*)&x); * high word of x *
+ ix1 = *((1-n0)+(int*)&x); * low word of x *
+ to dig two 32 bit words out of the 64 bit IEEE floating point
+ value. That is non-ANSI, and, moreover, the gcc instruction
+ scheduler gets it wrong. We instead use the following macros.
+ Unlike the original code, we determine the endianness at compile
+ time, not at run time; I don't see much benefit to selecting
+ endianness at run time. */
+
+#ifndef __IEEE_BIG_ENDIAN
+#ifndef __IEEE_LITTLE_ENDIAN
+ #error Must define endianness
+#endif
+#endif
+
+/* A union which permits us to convert between a double and two 32 bit
+ ints. */
+
+#ifdef __IEEE_BIG_ENDIAN
+
+typedef union
+{
+ double value;
+ struct
+ {
+ __uint32_t msw;
+ __uint32_t lsw;
+ } parts;
+} ieee_double_shape_type;
+
+#endif
+
+#ifdef __IEEE_LITTLE_ENDIAN
+
+typedef union
+{
+ double value;
+ struct
+ {
+ __uint32_t lsw;
+ __uint32_t msw;
+ } parts;
+} ieee_double_shape_type;
+
+#endif
+
+/* Get two 32 bit ints from a double. */
+
+#define EXTRACT_WORDS(ix0,ix1,d) \
+do { \
+ ieee_double_shape_type ew_u; \
+ ew_u.value = (d); \
+ (ix0) = ew_u.parts.msw; \
+ (ix1) = ew_u.parts.lsw; \
+} while (0)
+
+/* Get the more significant 32 bit int from a double. */
+
+#define GET_HIGH_WORD(i,d) \
+do { \
+ ieee_double_shape_type gh_u; \
+ gh_u.value = (d); \
+ (i) = gh_u.parts.msw; \
+} while (0)
+
+/* Get the less significant 32 bit int from a double. */
+
+#define GET_LOW_WORD(i,d) \
+do { \
+ ieee_double_shape_type gl_u; \
+ gl_u.value = (d); \
+ (i) = gl_u.parts.lsw; \
+} while (0)
+
+/* Set a double from two 32 bit ints. */
+
+#define INSERT_WORDS(d,ix0,ix1) \
+do { \
+ ieee_double_shape_type iw_u; \
+ iw_u.parts.msw = (ix0); \
+ iw_u.parts.lsw = (ix1); \
+ (d) = iw_u.value; \
+} while (0)
+
+/* Set the more significant 32 bits of a double from an int. */
+
+#define SET_HIGH_WORD(d,v) \
+do { \
+ ieee_double_shape_type sh_u; \
+ sh_u.value = (d); \
+ sh_u.parts.msw = (v); \
+ (d) = sh_u.value; \
+} while (0)
+
+/* Set the less significant 32 bits of a double from an int. */
+
+#define SET_LOW_WORD(d,v) \
+do { \
+ ieee_double_shape_type sl_u; \
+ sl_u.value = (d); \
+ sl_u.parts.lsw = (v); \
+ (d) = sl_u.value; \
+} while (0)
+
+/* A union which permits us to convert between a float and a 32 bit
+ int. */
+
+typedef union
+{
+ float value;
+ __uint32_t word;
+} ieee_float_shape_type;
+
+/* Get a 32 bit int from a float. */
+
+#define GET_FLOAT_WORD(i,d) \
+do { \
+ ieee_float_shape_type gf_u; \
+ gf_u.value = (d); \
+ (i) = gf_u.word; \
+} while (0)
+
+/* Set a float from a 32 bit int. */
+
+#define SET_FLOAT_WORD(d,i) \
+do { \
+ ieee_float_shape_type sf_u; \
+ sf_u.word = (i); \
+ (d) = sf_u.value; \
+} while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/libjava/java/lang/ieeefp.h b/libjava/java/lang/ieeefp.h
new file mode 100644
index 00000000000..931bafb7d1a
--- /dev/null
+++ b/libjava/java/lang/ieeefp.h
@@ -0,0 +1,103 @@
+#ifndef __IEEE_BIG_ENDIAN
+#ifndef __IEEE_LITTLE_ENDIAN
+
+#ifdef __arm__
+/* ARM always has big-endian words. Within those words the byte ordering
+ appears to be big or little endian. Newlib doesn't seem to care about
+ the byte ordering within words. */
+#define __IEEE_BIG_ENDIAN
+#endif
+
+#ifdef __hppa__
+#define __IEEE_BIG_ENDIAN
+#endif
+
+#if defined (__sparc) || defined (__sparc__)
+#define __IEEE_BIG_ENDIAN
+#endif
+
+#if defined(__m68k__) || defined(__mc68000__)
+#define __IEEE_BIG_ENDIAN
+#endif
+
+#if defined (__H8300__) || defined (__H8300H__)
+#define __IEEE_BIG_ENDIAN
+#define __SMALL_BITFIELDS
+#define _DOUBLE_IS_32BITS
+#endif
+
+#ifdef __H8500__
+#define __IEEE_BIG_ENDIAN
+#define __SMALL_BITFIELDS
+#define _DOUBLE_IS_32BITS
+#endif
+
+#ifdef __sh__
+#ifdef __LITTLE_ENDIAN__
+#define __IEEE_LITTLE_ENDIAN
+#else
+#define __IEEE_BIG_ENDIAN
+#endif
+#ifdef __SH3E__
+#define _DOUBLE_IS_32BITS
+#endif
+#endif
+
+#ifdef _AM29K
+#define __IEEE_BIG_ENDIAN
+#endif
+
+#ifdef __i386__
+#define __IEEE_LITTLE_ENDIAN
+#endif
+
+#ifdef __i960__
+#define __IEEE_LITTLE_ENDIAN
+#endif
+
+#ifdef __MIPSEL__
+#define __IEEE_LITTLE_ENDIAN
+#endif
+#ifdef __MIPSEB__
+#define __IEEE_BIG_ENDIAN
+#endif
+
+/* necv70 was __IEEE_LITTLE_ENDIAN. */
+
+#ifdef __W65__
+#define __IEEE_LITTLE_ENDIAN
+#define __SMALL_BITFIELDS
+#define _DOUBLE_IS_32BITS
+#endif
+
+#if defined(__Z8001__) || defined(__Z8002__)
+#define __IEEE_BIG_ENDIAN
+#endif
+
+#ifdef __m88k__
+#define __IEEE_BIG_ENDIAN
+#endif
+
+#ifdef __v800
+#define __IEEE_LITTLE_ENDIAN
+#endif
+
+#ifdef __PPC__
+#if (defined(_BIG_ENDIAN) && _BIG_ENDIAN) || (defined(_AIX) && _AIX)
+#define __IEEE_BIG_ENDIAN
+#else
+#if (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN) || (defined(__sun__) && __sun__) || (defined(__WIN32__) && __WIN32__)
+#define __IEEE_LITTLE_ENDIAN
+#endif
+#endif
+#endif
+
+#ifndef __IEEE_BIG_ENDIAN
+#ifndef __IEEE_LITTLE_ENDIAN
+#error Endianess not declared!!
+#endif /* not __IEEE_LITTLE_ENDIAN */
+#endif /* not __IEEE_BIG_ENDIAN */
+
+#endif /* not __IEEE_LITTLE_ENDIAN */
+#endif /* not __IEEE_BIG_ENDIAN */
+
diff --git a/libjava/java/lang/k_cos.c b/libjava/java/lang/k_cos.c
new file mode 100644
index 00000000000..6c60c243856
--- /dev/null
+++ b/libjava/java/lang/k_cos.c
@@ -0,0 +1,96 @@
+
+/* @(#)k_cos.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * __kernel_cos( x, y )
+ * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ *
+ * Algorithm
+ * 1. Since cos(-x) = cos(x), we need only to consider positive x.
+ * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
+ * 3. cos(x) is approximated by a polynomial of degree 14 on
+ * [0,pi/4]
+ * 4 14
+ * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
+ * where the remez error is
+ *
+ * | 2 4 6 8 10 12 14 | -58
+ * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2
+ * | |
+ *
+ * 4 6 8 10 12 14
+ * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then
+ * cos(x) = 1 - x*x/2 + r
+ * since cos(x+y) ~ cos(x) - sin(x)*y
+ * ~ cos(x) - x*y,
+ * a correction term is necessary in cos(x) and hence
+ * cos(x+y) = 1 - (x*x/2 - (r - x*y))
+ * For better accuracy when x > 0.3, let qx = |x|/4 with
+ * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
+ * Then
+ * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
+ * Note that 1-qx and (x*x/2-qx) is EXACT here, and the
+ * magnitude of the latter is at least a quarter of x*x/2,
+ * thus, reducing the rounding error in the subtraction.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
+C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
+C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
+C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
+C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
+C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
+
+#ifdef __STDC__
+ double __kernel_cos(double x, double y)
+#else
+ double __kernel_cos(x, y)
+ double x,y;
+#endif
+{
+ double a,hz,z,r,qx;
+ __int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff; /* ix = |x|'s high word*/
+ if(ix<0x3e400000) { /* if x < 2**27 */
+ if(((int)x)==0) return one; /* generate inexact */
+ }
+ z = x*x;
+ r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
+ if(ix < 0x3FD33333) /* if |x| < 0.3 */
+ return one - (0.5*z - (z*r - x*y));
+ else {
+ if(ix > 0x3fe90000) { /* x > 0.78125 */
+ qx = 0.28125;
+ } else {
+ INSERT_WORDS(qx,ix-0x00200000,0); /* x/4 */
+ }
+ hz = 0.5*z-qx;
+ a = one-qx;
+ return a - (hz - (z*r-x*y));
+ }
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/k_rem_pio2.c b/libjava/java/lang/k_rem_pio2.c
new file mode 100644
index 00000000000..8569256686c
--- /dev/null
+++ b/libjava/java/lang/k_rem_pio2.c
@@ -0,0 +1,320 @@
+
+/* @(#)k_rem_pio2.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
+ * double x[],y[]; int e0,nx,prec; int ipio2[];
+ *
+ * __kernel_rem_pio2 return the last three digits of N with
+ * y = x - N*pi/2
+ * so that |y| < pi/2.
+ *
+ * The method is to compute the integer (mod 8) and fraction parts of
+ * (2/pi)*x without doing the full multiplication. In general we
+ * skip the part of the product that are known to be a huge integer (
+ * more accurately, = 0 mod 8 ). Thus the number of operations are
+ * independent of the exponent of the input.
+ *
+ * (2/pi) is represented by an array of 24-bit integers in ipio2[].
+ *
+ * Input parameters:
+ * x[] The input value (must be positive) is broken into nx
+ * pieces of 24-bit integers in double precision format.
+ * x[i] will be the i-th 24 bit of x. The scaled exponent
+ * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
+ * match x's up to 24 bits.
+ *
+ * Example of breaking a double positive z into x[0]+x[1]+x[2]:
+ * e0 = ilogb(z)-23
+ * z = scalbn(z,-e0)
+ * for i = 0,1,2
+ * x[i] = floor(z)
+ * z = (z-x[i])*2**24
+ *
+ *
+ * y[] ouput result in an array of double precision numbers.
+ * The dimension of y[] is:
+ * 24-bit precision 1
+ * 53-bit precision 2
+ * 64-bit precision 2
+ * 113-bit precision 3
+ * The actual value is the sum of them. Thus for 113-bit
+ * precison, one may have to do something like:
+ *
+ * long double t,w,r_head, r_tail;
+ * t = (long double)y[2] + (long double)y[1];
+ * w = (long double)y[0];
+ * r_head = t+w;
+ * r_tail = w - (r_head - t);
+ *
+ * e0 The exponent of x[0]
+ *
+ * nx dimension of x[]
+ *
+ * prec an integer indicating the precision:
+ * 0 24 bits (single)
+ * 1 53 bits (double)
+ * 2 64 bits (extended)
+ * 3 113 bits (quad)
+ *
+ * ipio2[]
+ * integer array, contains the (24*i)-th to (24*i+23)-th
+ * bit of 2/pi after binary point. The corresponding
+ * floating value is
+ *
+ * ipio2[i] * 2^(-24(i+1)).
+ *
+ * External function:
+ * double scalbn(), floor();
+ *
+ *
+ * Here is the description of some local variables:
+ *
+ * jk jk+1 is the initial number of terms of ipio2[] needed
+ * in the computation. The recommended value is 2,3,4,
+ * 6 for single, double, extended,and quad.
+ *
+ * jz local integer variable indicating the number of
+ * terms of ipio2[] used.
+ *
+ * jx nx - 1
+ *
+ * jv index for pointing to the suitable ipio2[] for the
+ * computation. In general, we want
+ * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
+ * is an integer. Thus
+ * e0-3-24*jv >= 0 or (e0-3)/24 >= jv
+ * Hence jv = max(0,(e0-3)/24).
+ *
+ * jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
+ *
+ * q[] double array with integral value, representing the
+ * 24-bits chunk of the product of x and 2/pi.
+ *
+ * q0 the corresponding exponent of q[0]. Note that the
+ * exponent for q[i] would be q0-24*i.
+ *
+ * PIo2[] double precision array, obtained by cutting pi/2
+ * into 24 bits chunks.
+ *
+ * f[] ipio2[] in floating point
+ *
+ * iq[] integer array by breaking up q[] in 24-bits chunk.
+ *
+ * fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
+ *
+ * ih integer. If >0 it indicates q[] is >= 0.5, hence
+ * it also indicates the *sign* of the result.
+ *
+ */
+
+
+/*
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const int init_jk[] = {2,3,4,6}; /* initial value for jk */
+#else
+static int init_jk[] = {2,3,4,6};
+#endif
+
+#ifdef __STDC__
+static const double PIo2[] = {
+#else
+static double PIo2[] = {
+#endif
+ 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
+ 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
+ 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
+ 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
+ 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
+ 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
+ 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
+ 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
+};
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+zero = 0.0,
+one = 1.0,
+two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
+
+#ifdef __STDC__
+ int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const __int32_t *ipio2)
+#else
+ int __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
+ double x[], y[]; int e0,nx,prec; __int32_t ipio2[];
+#endif
+{
+ __int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+ double z,fw,f[20],fq[20],q[20];
+
+ /* initialize jk*/
+ jk = init_jk[prec];
+ jp = jk;
+
+ /* determine jx,jv,q0, note that 3>q0 */
+ jx = nx-1;
+ jv = (e0-3)/24; if(jv<0) jv=0;
+ q0 = e0-24*(jv+1);
+
+ /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+ j = jv-jx; m = jx+jk;
+ for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j];
+
+ /* compute q[0],q[1],...q[jk] */
+ for (i=0;i<=jk;i++) {
+ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+ }
+
+ jz = jk;
+recompute:
+ /* distill q[] into iq[] reversingly */
+ for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+ fw = (double)((__int32_t)(twon24* z));
+ iq[i] = (__int32_t)(z-two24*fw);
+ z = q[j-1]+fw;
+ }
+
+ /* compute n */
+ z = scalbn(z,(int)q0); /* actual value of z */
+ z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */
+ n = (__int32_t) z;
+ z -= (double)n;
+ ih = 0;
+ if(q0>0) { /* need iq[jz-1] to determine n */
+ i = (iq[jz-1]>>(24-q0)); n += i;
+ iq[jz-1] -= i<<(24-q0);
+ ih = iq[jz-1]>>(23-q0);
+ }
+ else if(q0==0) ih = iq[jz-1]>>23;
+ else if(z>=0.5) ih=2;
+
+ if(ih>0) { /* q > 0.5 */
+ n += 1; carry = 0;
+ for(i=0;i<jz ;i++) { /* compute 1-q */
+ j = iq[i];
+ if(carry==0) {
+ if(j!=0) {
+ carry = 1; iq[i] = 0x1000000- j;
+ }
+ } else iq[i] = 0xffffff - j;
+ }
+ if(q0>0) { /* rare case: chance is 1 in 12 */
+ switch(q0) {
+ case 1:
+ iq[jz-1] &= 0x7fffff; break;
+ case 2:
+ iq[jz-1] &= 0x3fffff; break;
+ }
+ }
+ if(ih==2) {
+ z = one - z;
+ if(carry!=0) z -= scalbn(one,(int)q0);
+ }
+ }
+
+ /* check if recomputation is needed */
+ if(z==zero) {
+ j = 0;
+ for (i=jz-1;i>=jk;i--) j |= iq[i];
+ if(j==0) { /* need recomputation */
+ for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
+
+ for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
+ f[jx+i] = (double) ipio2[jv+i];
+ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+ q[i] = fw;
+ }
+ jz += k;
+ goto recompute;
+ }
+ }
+
+ /* chop off zero terms */
+ if(z==0.0) {
+ jz -= 1; q0 -= 24;
+ while(iq[jz]==0) { jz--; q0-=24;}
+ } else { /* break z into 24-bit if necessary */
+ z = scalbn(z,-(int)q0);
+ if(z>=two24) {
+ fw = (double)((__int32_t)(twon24*z));
+ iq[jz] = (__int32_t)(z-two24*fw);
+ jz += 1; q0 += 24;
+ iq[jz] = (__int32_t) fw;
+ } else iq[jz] = (__int32_t) z ;
+ }
+
+ /* convert integer "bit" chunk to floating-point value */
+ fw = scalbn(one,(int)q0);
+ for(i=jz;i>=0;i--) {
+ q[i] = fw*(double)iq[i]; fw*=twon24;
+ }
+
+ /* compute PIo2[0,...,jp]*q[jz,...,0] */
+ for(i=jz;i>=0;i--) {
+ for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+ fq[jz-i] = fw;
+ }
+
+ /* compress fq[] into y[] */
+ switch(prec) {
+ case 0:
+ fw = 0.0;
+ for (i=jz;i>=0;i--) fw += fq[i];
+ y[0] = (ih==0)? fw: -fw;
+ break;
+ case 1:
+ case 2:
+ fw = 0.0;
+ for (i=jz;i>=0;i--) fw += fq[i];
+ y[0] = (ih==0)? fw: -fw;
+ fw = fq[0]-fw;
+ for (i=1;i<=jz;i++) fw += fq[i];
+ y[1] = (ih==0)? fw: -fw;
+ break;
+ case 3: /* painful */
+ for (i=jz;i>0;i--) {
+ fw = fq[i-1]+fq[i];
+ fq[i] += fq[i-1]-fw;
+ fq[i-1] = fw;
+ }
+ for (i=jz;i>1;i--) {
+ fw = fq[i-1]+fq[i];
+ fq[i] += fq[i-1]-fw;
+ fq[i-1] = fw;
+ }
+ for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
+ if(ih==0) {
+ y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
+ } else {
+ y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+ }
+ }
+ return n&7;
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/k_sin.c b/libjava/java/lang/k_sin.c
new file mode 100644
index 00000000000..f119916dfbc
--- /dev/null
+++ b/libjava/java/lang/k_sin.c
@@ -0,0 +1,79 @@
+
+/* @(#)k_sin.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __kernel_sin( x, y, iy)
+ * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
+ *
+ * Algorithm
+ * 1. Since sin(-x) = -sin(x), we need only to consider positive x.
+ * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
+ * 3. sin(x) is approximated by a polynomial of degree 13 on
+ * [0,pi/4]
+ * 3 13
+ * sin(x) ~ x + S1*x + ... + S6*x
+ * where
+ *
+ * |sin(x) 2 4 6 8 10 12 | -58
+ * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
+ * | x |
+ *
+ * 4. sin(x+y) = sin(x) + sin'(x')*y
+ * ~ sin(x) + (1-x*x/2)*y
+ * For better accuracy, let
+ * 3 2 2 2 2
+ * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
+ * then 3 2
+ * sin(x) = x + (S1*x + (x *(r-y/2)+y))
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
+S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
+S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
+S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
+S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
+S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
+
+#ifdef __STDC__
+ double __kernel_sin(double x, double y, int iy)
+#else
+ double __kernel_sin(x, y, iy)
+ double x,y; int iy; /* iy=0 if y is zero */
+#endif
+{
+ double z,r,v;
+ __int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff; /* high word of x */
+ if(ix<0x3e400000) /* |x| < 2**-27 */
+ {if((int)x==0) return x;} /* generate inexact */
+ z = x*x;
+ v = z*x;
+ r = S2+z*(S3+z*(S4+z*(S5+z*S6)));
+ if(iy==0) return x+v*(S1+z*r);
+ else return x-((z*(half*y-v*r)-y)-v*S1);
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/k_tan.c b/libjava/java/lang/k_tan.c
new file mode 100644
index 00000000000..9f5b307600c
--- /dev/null
+++ b/libjava/java/lang/k_tan.c
@@ -0,0 +1,132 @@
+
+/* @(#)k_tan.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __kernel_tan( x, y, k )
+ * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input k indicates whether tan (if k=1) or
+ * -1/tan (if k= -1) is returned.
+ *
+ * Algorithm
+ * 1. Since tan(-x) = -tan(x), we need only to consider positive x.
+ * 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
+ * 3. tan(x) is approximated by a odd polynomial of degree 27 on
+ * [0,0.67434]
+ * 3 27
+ * tan(x) ~ x + T1*x + ... + T13*x
+ * where
+ *
+ * |tan(x) 2 4 26 | -59.2
+ * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
+ * | x |
+ *
+ * Note: tan(x+y) = tan(x) + tan'(x)*y
+ * ~ tan(x) + (1+x*x)*y
+ * Therefore, for better accuracy in computing tan(x+y), let
+ * 3 2 2 2 2
+ * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
+ * then
+ * 3 2
+ * tan(x+y) = x + (T1*x + (x *(r+y)+y))
+ *
+ * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
+ * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
+ * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
+pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */
+T[] = {
+ 3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */
+ 1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */
+ 5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */
+ 2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */
+ 8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */
+ 3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */
+ 1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */
+ 5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */
+ 2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */
+ 7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */
+ 7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */
+ -1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */
+ 2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */
+};
+
+#ifdef __STDC__
+ double __kernel_tan(double x, double y, int iy)
+#else
+ double __kernel_tan(x, y, iy)
+ double x,y; int iy;
+#endif
+{
+ double z,r,v,w,s;
+ __int32_t ix,hx;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff; /* high word of |x| */
+ if(ix<0x3e300000) /* x < 2**-28 */
+ {if((int)x==0) { /* generate inexact */
+ __uint32_t low;
+ GET_LOW_WORD(low,x);
+ if(((ix|low)|(iy+1))==0) return one/fabs(x);
+ else return (iy==1)? x: -one/x;
+ }
+ }
+ if(ix>=0x3FE59428) { /* |x|>=0.6744 */
+ if(hx<0) {x = -x; y = -y;}
+ z = pio4-x;
+ w = pio4lo-y;
+ x = z+w; y = 0.0;
+ }
+ z = x*x;
+ w = z*z;
+ /* Break x^5*(T[1]+x^2*T[2]+...) into
+ * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
+ * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
+ */
+ r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
+ v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
+ s = z*x;
+ r = y + z*(s*(r+v)+y);
+ r += T[0]*s;
+ w = x+r;
+ if(ix>=0x3FE59428) {
+ v = (double)iy;
+ return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r)));
+ }
+ if(iy==1) return w;
+ else { /* if allow error up to 2 ulp,
+ simply return -1.0/(x+r) here */
+ /* compute -1.0/(x+r) accurately */
+ double a,t;
+ z = w;
+ SET_LOW_WORD(z,0);
+ v = r-(z - x); /* z+v = r+x */
+ t = a = -1.0/w; /* a = -1.0/w */
+ SET_LOW_WORD(t,0);
+ s = 1.0+t*z;
+ return t+a*(s+t*v);
+ }
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/mprec.c b/libjava/java/lang/mprec.c
new file mode 100644
index 00000000000..12dd5d2617a
--- /dev/null
+++ b/libjava/java/lang/mprec.c
@@ -0,0 +1,958 @@
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991 by AT&T.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* Please send bug reports to
+ David M. Gay
+ AT&T Bell Laboratories, Room 2C-463
+ 600 Mountain Avenue
+ Murray Hill, NJ 07974-2070
+ U.S.A.
+ dmg@research.att.com or research!dmg
+ */
+
+/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
+ *
+ * This strtod returns a nearest machine number to the input decimal
+ * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
+ * broken by the IEEE round-even rule. Otherwise ties are broken by
+ * biased rounding (add half and chop).
+ *
+ * Inspired loosely by William D. Clinger's paper "How to Read Floating
+ * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *
+ * 1. We only require IEEE, IBM, or VAX double-precision
+ * arithmetic (not IEEE double-extended).
+ * 2. We get by with floating-point arithmetic in a case that
+ * Clinger missed -- when we're computing d * 10^n
+ * for a small integer d and the integer n is not too
+ * much larger than 22 (the maximum integer k for which
+ * we can represent 10^k exactly), we may be able to
+ * compute (d*10^k) * 10^(e-k) with just one roundoff.
+ * 3. Rather than a bit-at-a-time adjustment of the binary
+ * result in the hard case, we use floating-point
+ * arithmetic to determine the adjustment to within
+ * one bit; only in really hard cases do we need to
+ * compute a second residual.
+ * 4. Because of 3., we don't need a large table of powers of 10
+ * for ten-to-e (just some small tables, e.g. of 10^k
+ * for 0 <= k <= 22).
+ */
+
+/*
+ * #define IEEE_8087 for IEEE-arithmetic machines where the least
+ * significant byte has the lowest address.
+ * #define IEEE_MC68k for IEEE-arithmetic machines where the most
+ * significant byte has the lowest address.
+ * #define Sudden_Underflow for IEEE-format machines without gradual
+ * underflow (i.e., that flush to zero on underflow).
+ * #define IBM for IBM mainframe-style floating-point arithmetic.
+ * #define VAX for VAX-style floating-point arithmetic.
+ * #define Unsigned_Shifts if >> does treats its left operand as unsigned.
+ * #define No_leftright to omit left-right logic in fast floating-point
+ * computation of dtoa.
+ * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
+ * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
+ * that use extended-precision instructions to compute rounded
+ * products and quotients) with IBM.
+ * #define ROUND_BIASED for IEEE-format with biased rounding.
+ * #define Inaccurate_Divide for IEEE-format with correctly rounded
+ * products but inaccurate quotients, e.g., for Intel i860.
+ * #define Just_16 to store 16 bits per 32-bit long when doing high-precision
+ * integer arithmetic. Whether this speeds things up or slows things
+ * down depends on the machine and the number being converted.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <java-assert.h>
+#include "mprec.h"
+
+/* reent.c knows this value */
+#define _Kmax 15
+#include <stdio.h>
+
+_Jv_Bigint *
+_DEFUN (Balloc, (ptr, k), struct _Jv_reent *ptr _AND int k)
+{
+ _Jv_Bigint *rv = NULL;
+
+ int i = 0;
+ int j = 1;
+
+ JvAssert ((1 << k) < MAX_BIGNUM_WDS);
+
+ while ((ptr->_allocation_map & j) && i < MAX_BIGNUMS)
+ i++, j <<= 1;
+
+ JvAssert (i < MAX_BIGNUMS);
+
+ if (i >= MAX_BIGNUMS)
+ return NULL;
+
+ ptr->_allocation_map |= j;
+ rv = &ptr->_freelist[i];
+
+ rv->_k = k;
+ rv->_maxwds = 32;
+
+ return rv;
+}
+
+
+void
+_DEFUN (Bfree, (ptr, v), struct _Jv_reent *ptr _AND _Jv_Bigint * v)
+{
+ long i;
+
+ i = v - ptr->_freelist;
+
+ JvAssert (i >= 0 && i < MAX_BIGNUMS);
+
+ if (i >= 0 && i < MAX_BIGNUMS)
+ ptr->_allocation_map &= ~ (1 << i);
+}
+
+
+_Jv_Bigint *
+_DEFUN (multadd, (ptr, b, m, a),
+ struct _Jv_reent *ptr _AND
+ _Jv_Bigint * b _AND
+ int m _AND
+ int a)
+{
+ int i, wds;
+ unsigned long *x, y;
+#ifdef Pack_32
+ unsigned long xi, z;
+#endif
+ _Jv_Bigint *b1;
+
+ wds = b->_wds;
+ x = b->_x;
+ i = 0;
+ do
+ {
+#ifdef Pack_32
+ xi = *x;
+ y = (xi & 0xffff) * m + a;
+ z = (xi >> 16) * m + (y >> 16);
+ a = (int) (z >> 16);
+ *x++ = (z << 16) + (y & 0xffff);
+#else
+ y = *x * m + a;
+ a = (int) (y >> 16);
+ *x++ = y & 0xffff;
+#endif
+ }
+ while (++i < wds);
+ if (a)
+ {
+ if (wds >= b->_maxwds)
+ {
+ b1 = Balloc (ptr, b->_k + 1);
+ Bcopy (b1, b);
+ Bfree (ptr, b);
+ b = b1;
+ }
+ b->_x[wds++] = a;
+ b->_wds = wds;
+ }
+ return b;
+}
+
+_Jv_Bigint *
+_DEFUN (s2b, (ptr, s, nd0, nd, y9),
+ struct _Jv_reent * ptr _AND
+ _CONST char *s _AND
+ int nd0 _AND
+ int nd _AND
+ unsigned long y9)
+{
+ _Jv_Bigint *b;
+ int i, k;
+ long x, y;
+
+ x = (nd + 8) / 9;
+ for (k = 0, y = 1; x > y; y <<= 1, k++);
+#ifdef Pack_32
+ b = Balloc (ptr, k);
+ b->_x[0] = y9;
+ b->_wds = 1;
+#else
+ b = Balloc (ptr, k + 1);
+ b->_x[0] = y9 & 0xffff;
+ b->_wds = (b->_x[1] = y9 >> 16) ? 2 : 1;
+#endif
+
+ i = 9;
+ if (9 < nd0)
+ {
+ s += 9;
+ do
+ b = multadd (ptr, b, 10, *s++ - '0');
+ while (++i < nd0);
+ s++;
+ }
+ else
+ s += 10;
+ for (; i < nd; i++)
+ b = multadd (ptr, b, 10, *s++ - '0');
+ return b;
+}
+
+int
+_DEFUN (hi0bits,
+ (x), register unsigned long x)
+{
+ register int k = 0;
+
+ if (!(x & 0xffff0000))
+ {
+ k = 16;
+ x <<= 16;
+ }
+ if (!(x & 0xff000000))
+ {
+ k += 8;
+ x <<= 8;
+ }
+ if (!(x & 0xf0000000))
+ {
+ k += 4;
+ x <<= 4;
+ }
+ if (!(x & 0xc0000000))
+ {
+ k += 2;
+ x <<= 2;
+ }
+ if (!(x & 0x80000000))
+ {
+ k++;
+ if (!(x & 0x40000000))
+ return 32;
+ }
+ return k;
+}
+
+int
+_DEFUN (lo0bits, (y), unsigned long *y)
+{
+ register int k;
+ register unsigned long x = *y;
+
+ if (x & 7)
+ {
+ if (x & 1)
+ return 0;
+ if (x & 2)
+ {
+ *y = x >> 1;
+ return 1;
+ }
+ *y = x >> 2;
+ return 2;
+ }
+ k = 0;
+ if (!(x & 0xffff))
+ {
+ k = 16;
+ x >>= 16;
+ }
+ if (!(x & 0xff))
+ {
+ k += 8;
+ x >>= 8;
+ }
+ if (!(x & 0xf))
+ {
+ k += 4;
+ x >>= 4;
+ }
+ if (!(x & 0x3))
+ {
+ k += 2;
+ x >>= 2;
+ }
+ if (!(x & 1))
+ {
+ k++;
+ x >>= 1;
+ if (!x & 1)
+ return 32;
+ }
+ *y = x;
+ return k;
+}
+
+_Jv_Bigint *
+_DEFUN (i2b, (ptr, i), struct _Jv_reent * ptr _AND int i)
+{
+ _Jv_Bigint *b;
+
+ b = Balloc (ptr, 1);
+ b->_x[0] = i;
+ b->_wds = 1;
+ return b;
+}
+
+_Jv_Bigint *
+_DEFUN (mult, (ptr, a, b), struct _Jv_reent * ptr _AND _Jv_Bigint * a _AND _Jv_Bigint * b)
+{
+ _Jv_Bigint *c;
+ int k, wa, wb, wc;
+ unsigned long carry, y, z;
+ unsigned long *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+#ifdef Pack_32
+ unsigned long z2;
+#endif
+
+ if (a->_wds < b->_wds)
+ {
+ c = a;
+ a = b;
+ b = c;
+ }
+ k = a->_k;
+ wa = a->_wds;
+ wb = b->_wds;
+ wc = wa + wb;
+ if (wc > a->_maxwds)
+ k++;
+ c = Balloc (ptr, k);
+ for (x = c->_x, xa = x + wc; x < xa; x++)
+ *x = 0;
+ xa = a->_x;
+ xae = xa + wa;
+ xb = b->_x;
+ xbe = xb + wb;
+ xc0 = c->_x;
+#ifdef Pack_32
+ for (; xb < xbe; xb++, xc0++)
+ {
+ if ((y = *xb & 0xffff))
+ {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do
+ {
+ z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
+ carry = z >> 16;
+ z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
+ carry = z2 >> 16;
+ Storeinc (xc, z2, z);
+ }
+ while (x < xae);
+ *xc = carry;
+ }
+ if ((y = *xb >> 16))
+ {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ z2 = *xc;
+ do
+ {
+ z = (*x & 0xffff) * y + (*xc >> 16) + carry;
+ carry = z >> 16;
+ Storeinc (xc, z, z2);
+ z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
+ carry = z2 >> 16;
+ }
+ while (x < xae);
+ *xc = z2;
+ }
+ }
+#else
+ for (; xb < xbe; xc0++)
+ {
+ if (y = *xb++)
+ {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do
+ {
+ z = *x++ * y + *xc + carry;
+ carry = z >> 16;
+ *xc++ = z & 0xffff;
+ }
+ while (x < xae);
+ *xc = carry;
+ }
+ }
+#endif
+ for (xc0 = c->_x, xc = xc0 + wc; wc > 0 && !*--xc; --wc);
+ c->_wds = wc;
+ return c;
+}
+
+_Jv_Bigint *
+_DEFUN (pow5mult,
+ (ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int k)
+{
+ _Jv_Bigint *b1, *p5, *p51;
+ int i;
+ static _CONST int p05[3] = {5, 25, 125};
+
+ if ((i = k & 3))
+ b = multadd (ptr, b, p05[i - 1], 0);
+
+ if (!(k >>= 2))
+ return b;
+ if (!(p5 = ptr->_p5s))
+ {
+ /* first time */
+ p5 = ptr->_p5s = i2b (ptr, 625);
+ p5->_next = 0;
+ }
+ for (;;)
+ {
+ if (k & 1)
+ {
+ b1 = mult (ptr, b, p5);
+ Bfree (ptr, b);
+ b = b1;
+ }
+ if (!(k >>= 1))
+ break;
+ if (!(p51 = p5->_next))
+ {
+ p51 = p5->_next = mult (ptr, p5, p5);
+ p51->_next = 0;
+ }
+ p5 = p51;
+ }
+ return b;
+}
+
+_Jv_Bigint *
+_DEFUN (lshift, (ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int k)
+{
+ int i, k1, n, n1;
+ _Jv_Bigint *b1;
+ unsigned long *x, *x1, *xe, z;
+
+#ifdef Pack_32
+ n = k >> 5;
+#else
+ n = k >> 4;
+#endif
+ k1 = b->_k;
+ n1 = n + b->_wds + 1;
+ for (i = b->_maxwds; n1 > i; i <<= 1)
+ k1++;
+ b1 = Balloc (ptr, k1);
+ x1 = b1->_x;
+ for (i = 0; i < n; i++)
+ *x1++ = 0;
+ x = b->_x;
+ xe = x + b->_wds;
+#ifdef Pack_32
+ if (k &= 0x1f)
+ {
+ k1 = 32 - k;
+ z = 0;
+ do
+ {
+ *x1++ = *x << k | z;
+ z = *x++ >> k1;
+ }
+ while (x < xe);
+ if ((*x1 = z))
+ ++n1;
+ }
+#else
+ if (k &= 0xf)
+ {
+ k1 = 16 - k;
+ z = 0;
+ do
+ {
+ *x1++ = *x << k & 0xffff | z;
+ z = *x++ >> k1;
+ }
+ while (x < xe);
+ if (*x1 = z)
+ ++n1;
+ }
+#endif
+ else
+ do
+ *x1++ = *x++;
+ while (x < xe);
+ b1->_wds = n1 - 1;
+ Bfree (ptr, b);
+ return b1;
+}
+
+int
+_DEFUN (cmp, (a, b), _Jv_Bigint * a _AND _Jv_Bigint * b)
+{
+ unsigned long *xa, *xa0, *xb, *xb0;
+ int i, j;
+
+ i = a->_wds;
+ j = b->_wds;
+#ifdef DEBUG
+ if (i > 1 && !a->_x[i - 1])
+ Bug ("cmp called with a->_x[a->_wds-1] == 0");
+ if (j > 1 && !b->_x[j - 1])
+ Bug ("cmp called with b->_x[b->_wds-1] == 0");
+#endif
+ if (i -= j)
+ return i;
+ xa0 = a->_x;
+ xa = xa0 + j;
+ xb0 = b->_x;
+ xb = xb0 + j;
+ for (;;)
+ {
+ if (*--xa != *--xb)
+ return *xa < *xb ? -1 : 1;
+ if (xa <= xa0)
+ break;
+ }
+ return 0;
+}
+
+_Jv_Bigint *
+_DEFUN (diff, (ptr, a, b), struct _Jv_reent * ptr _AND
+ _Jv_Bigint * a _AND _Jv_Bigint * b)
+{
+ _Jv_Bigint *c;
+ int i, wa, wb;
+ long borrow, y; /* We need signed shifts here. */
+ unsigned long *xa, *xae, *xb, *xbe, *xc;
+#ifdef Pack_32
+ long z;
+#endif
+
+ i = cmp (a, b);
+ if (!i)
+ {
+ c = Balloc (ptr, 0);
+ c->_wds = 1;
+ c->_x[0] = 0;
+ return c;
+ }
+ if (i < 0)
+ {
+ c = a;
+ a = b;
+ b = c;
+ i = 1;
+ }
+ else
+ i = 0;
+ c = Balloc (ptr, a->_k);
+ c->_sign = i;
+ wa = a->_wds;
+ xa = a->_x;
+ xae = xa + wa;
+ wb = b->_wds;
+ xb = b->_x;
+ xbe = xb + wb;
+ xc = c->_x;
+ borrow = 0;
+#ifdef Pack_32
+ do
+ {
+ y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend (borrow, y);
+ z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
+ borrow = z >> 16;
+ Sign_Extend (borrow, z);
+ Storeinc (xc, z, y);
+ }
+ while (xb < xbe);
+ while (xa < xae)
+ {
+ y = (*xa & 0xffff) + borrow;
+ borrow = y >> 16;
+ Sign_Extend (borrow, y);
+ z = (*xa++ >> 16) + borrow;
+ borrow = z >> 16;
+ Sign_Extend (borrow, z);
+ Storeinc (xc, z, y);
+ }
+#else
+ do
+ {
+ y = *xa++ - *xb++ + borrow;
+ borrow = y >> 16;
+ Sign_Extend (borrow, y);
+ *xc++ = y & 0xffff;
+ }
+ while (xb < xbe);
+ while (xa < xae)
+ {
+ y = *xa++ + borrow;
+ borrow = y >> 16;
+ Sign_Extend (borrow, y);
+ *xc++ = y & 0xffff;
+ }
+#endif
+ while (!*--xc)
+ wa--;
+ c->_wds = wa;
+ return c;
+}
+
+double
+_DEFUN (ulp, (_x), double _x)
+{
+ union double_union x, a;
+ register long L;
+
+ x.d = _x;
+
+ L = (word0 (x) & Exp_mask) - (P - 1) * Exp_msk1;
+#ifndef Sudden_Underflow
+ if (L > 0)
+ {
+#endif
+#ifdef IBM
+ L |= Exp_msk1 >> 4;
+#endif
+ word0 (a) = L;
+#ifndef _DOUBLE_IS_32BITS
+ word1 (a) = 0;
+#endif
+
+#ifndef Sudden_Underflow
+ }
+ else
+ {
+ L = -L >> Exp_shift;
+ if (L < Exp_shift)
+ {
+ word0 (a) = 0x80000 >> L;
+#ifndef _DOUBLE_IS_32BITS
+ word1 (a) = 0;
+#endif
+ }
+ else
+ {
+ word0 (a) = 0;
+ L -= Exp_shift;
+#ifndef _DOUBLE_IS_32BITS
+ word1 (a) = L >= 31 ? 1 : 1 << (31 - L);
+#endif
+ }
+ }
+#endif
+ return a.d;
+}
+
+double
+_DEFUN (b2d, (a, e),
+ _Jv_Bigint * a _AND int *e)
+{
+ unsigned long *xa, *xa0, w, y, z;
+ int k;
+ union double_union d;
+#ifdef VAX
+ unsigned long d0, d1;
+#else
+#define d0 word0(d)
+#define d1 word1(d)
+#endif
+
+ xa0 = a->_x;
+ xa = xa0 + a->_wds;
+ y = *--xa;
+#ifdef DEBUG
+ if (!y)
+ Bug ("zero y in b2d");
+#endif
+ k = hi0bits (y);
+ *e = 32 - k;
+#ifdef Pack_32
+ if (k < Ebits)
+ {
+ d0 = Exp_1 | y >> (Ebits - k);
+ w = xa > xa0 ? *--xa : 0;
+#ifndef _DOUBLE_IS_32BITS
+ d1 = y << (32 - Ebits + k) | w >> (Ebits - k);
+#endif
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ if (k -= Ebits)
+ {
+ d0 = Exp_1 | y << k | z >> (32 - k);
+ y = xa > xa0 ? *--xa : 0;
+#ifndef _DOUBLE_IS_32BITS
+ d1 = z << k | y >> (32 - k);
+#endif
+ }
+ else
+ {
+ d0 = Exp_1 | y;
+#ifndef _DOUBLE_IS_32BITS
+ d1 = z;
+#endif
+ }
+#else
+ if (k < Ebits + 16)
+ {
+ z = xa > xa0 ? *--xa : 0;
+ d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
+ w = xa > xa0 ? *--xa : 0;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ w = xa > xa0 ? *--xa : 0;
+ k -= Ebits + 16;
+ d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = w << k + 16 | y << k;
+#endif
+ret_d:
+#ifdef VAX
+ word0 (d) = d0 >> 16 | d0 << 16;
+ word1 (d) = d1 >> 16 | d1 << 16;
+#else
+#undef d0
+#undef d1
+#endif
+ return d.d;
+}
+
+_Jv_Bigint *
+_DEFUN (d2b,
+ (ptr, _d, e, bits),
+ struct _Jv_reent * ptr _AND
+ double _d _AND
+ int *e _AND
+ int *bits)
+
+{
+ union double_union d;
+ _Jv_Bigint *b;
+ int de, i, k;
+ unsigned long *x, y, z;
+#ifdef VAX
+ unsigned long d0, d1;
+ d.d = _d;
+ d0 = word0 (d) >> 16 | word0 (d) << 16;
+ d1 = word1 (d) >> 16 | word1 (d) << 16;
+#else
+#define d0 word0(d)
+#define d1 word1(d)
+ d.d = _d;
+#endif
+
+#ifdef Pack_32
+ b = Balloc (ptr, 1);
+#else
+ b = Balloc (ptr, 2);
+#endif
+ x = b->_x;
+
+ z = d0 & Frac_mask;
+ d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
+#ifdef Sudden_Underflow
+ de = (int) (d0 >> Exp_shift);
+#ifndef IBM
+ z |= Exp_msk11;
+#endif
+#else
+ if ((de = (int) (d0 >> Exp_shift)))
+ z |= Exp_msk1;
+#endif
+#ifdef Pack_32
+#ifndef _DOUBLE_IS_32BITS
+ if ((y = d1))
+ {
+ if ((k = lo0bits (&y)))
+ {
+ x[0] = y | z << (32 - k);
+ z >>= k;
+ }
+ else
+ x[0] = y;
+ i = b->_wds = (x[1] = z) ? 2 : 1;
+ }
+ else
+#endif
+ {
+#ifdef DEBUG
+ if (!z)
+ Bug ("Zero passed to d2b");
+#endif
+ k = lo0bits (&z);
+ x[0] = z;
+ i = b->_wds = 1;
+#ifndef _DOUBLE_IS_32BITS
+ k += 32;
+#endif
+ }
+#else
+ if (y = d1)
+ {
+ if (k = lo0bits (&y))
+ if (k >= 16)
+ {
+ x[0] = y | z << 32 - k & 0xffff;
+ x[1] = z >> k - 16 & 0xffff;
+ x[2] = z >> k;
+ i = 2;
+ }
+ else
+ {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16 | z << 16 - k & 0xffff;
+ x[2] = z >> k & 0xffff;
+ x[3] = z >> k + 16;
+ i = 3;
+ }
+ else
+ {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16;
+ x[2] = z & 0xffff;
+ x[3] = z >> 16;
+ i = 3;
+ }
+ }
+ else
+ {
+#ifdef DEBUG
+ if (!z)
+ Bug ("Zero passed to d2b");
+#endif
+ k = lo0bits (&z);
+ if (k >= 16)
+ {
+ x[0] = z;
+ i = 0;
+ }
+ else
+ {
+ x[0] = z & 0xffff;
+ x[1] = z >> 16;
+ i = 1;
+ }
+ k += 32;
+ }
+ while (!x[i])
+ --i;
+ b->_wds = i + 1;
+#endif
+#ifndef Sudden_Underflow
+ if (de)
+ {
+#endif
+#ifdef IBM
+ *e = (de - Bias - (P - 1) << 2) + k;
+ *bits = 4 * P + 8 - k - hi0bits (word0 (d) & Frac_mask);
+#else
+ *e = de - Bias - (P - 1) + k;
+ *bits = P - k;
+#endif
+#ifndef Sudden_Underflow
+ }
+ else
+ {
+ *e = de - Bias - (P - 1) + 1 + k;
+#ifdef Pack_32
+ *bits = 32 * i - hi0bits (x[i - 1]);
+#else
+ *bits = (i + 2) * 16 - hi0bits (x[i]);
+#endif
+ }
+#endif
+ return b;
+}
+#undef d0
+#undef d1
+
+double
+_DEFUN (ratio, (a, b), _Jv_Bigint * a _AND _Jv_Bigint * b)
+
+{
+ union double_union da, db;
+ int k, ka, kb;
+
+ da.d = b2d (a, &ka);
+ db.d = b2d (b, &kb);
+#ifdef Pack_32
+ k = ka - kb + 32 * (a->_wds - b->_wds);
+#else
+ k = ka - kb + 16 * (a->_wds - b->_wds);
+#endif
+#ifdef IBM
+ if (k > 0)
+ {
+ word0 (da) += (k >> 2) * Exp_msk1;
+ if (k &= 3)
+ da.d *= 1 << k;
+ }
+ else
+ {
+ k = -k;
+ word0 (db) += (k >> 2) * Exp_msk1;
+ if (k &= 3)
+ db.d *= 1 << k;
+ }
+#else
+ if (k > 0)
+ word0 (da) += k * Exp_msk1;
+ else
+ {
+ k = -k;
+ word0 (db) += k * Exp_msk1;
+ }
+#endif
+ return da.d / db.d;
+}
+
+
+_CONST double
+ tens[] =
+{
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22, 1e23, 1e24
+
+};
+
+#if !defined(_DOUBLE_IS_32BITS) && !defined(__v800)
+_CONST double bigtens[] =
+{1e16, 1e32, 1e64, 1e128, 1e256};
+
+_CONST double tinytens[] =
+{1e-16, 1e-32, 1e-64, 1e-128, 1e-256};
+#else
+_CONST double bigtens[] =
+{1e16, 1e32};
+
+_CONST double tinytens[] =
+{1e-16, 1e-32};
+#endif
+
+
diff --git a/libjava/java/lang/mprec.h b/libjava/java/lang/mprec.h
new file mode 100644
index 00000000000..192243157df
--- /dev/null
+++ b/libjava/java/lang/mprec.h
@@ -0,0 +1,374 @@
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991 by AT&T.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* Please send bug reports to
+ David M. Gay
+ AT&T Bell Laboratories, Room 2C-463
+ 600 Mountain Avenue
+ Murray Hill, NJ 07974-2070
+ U.S.A.
+ dmg@research.att.com or research!dmg
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <config.h>
+#include "ieeefp.h"
+
+#include <math.h>
+// #include <float.h>
+// #include <errno.h>
+
+/* These typedefs are true for the targets running Java. */
+
+#ifndef HAVE_INT32_DEFINED
+typedef int __int32_t;
+typedef unsigned int __uint32_t;
+#endif
+
+#ifdef __IEEE_LITTLE_ENDIAN
+#define IEEE_8087
+#endif
+
+#ifdef __IEEE_BIG_ENDIAN
+#define IEEE_MC68k
+#endif
+
+#ifdef __Z8000__
+#define Just_16
+#endif
+
+#ifdef DEBUG
+#include "stdio.h"
+#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
+#endif
+
+
+#ifdef Unsigned_Shifts
+#define Sign_Extend(a,b) if (b < 0) a |= (__uint32_t)0xffff0000;
+#else
+#define Sign_Extend(a,b) /*no-op*/
+#endif
+
+#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1
+Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
+#endif
+
+/* If we are going to examine or modify specific bits in a double using
+ the word0 and/or word1 macros, then we must wrap the double inside
+ a union. This is necessary to avoid undefined behavior according to
+ the ANSI C spec. */
+union double_union
+{
+ double d;
+ // FIXME: This should be some well-defined 32 bit type.
+ __uint32_t i[2];
+};
+
+#ifdef IEEE_8087
+#define word0(x) (x.i[1])
+#define word1(x) (x.i[0])
+#else
+#define word0(x) (x.i[0])
+#define word1(x) (x.i[1])
+#endif
+
+/* The following definition of Storeinc is appropriate for MIPS processors.
+ * An alternative that might be better on some machines is
+ * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
+ */
+#if defined(IEEE_8087) + defined(VAX)
+#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
+((unsigned short *)a)[0] = (unsigned short)c, a++)
+#else
+#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
+((unsigned short *)a)[1] = (unsigned short)c, a++)
+#endif
+
+/* #define P DBL_MANT_DIG */
+/* Ten_pmax = floor(P*log(2)/log(5)) */
+/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
+/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
+/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
+
+#if defined(IEEE_8087) + defined(IEEE_MC68k)
+#if defined (_DOUBLE_IS_32BITS)
+#define Exp_shift 23
+#define Exp_shift1 23
+#define Exp_msk1 ((__uint32_t)0x00800000L)
+#define Exp_msk11 ((__uint32_t)0x00800000L)
+#define Exp_mask ((__uint32_t)0x7f800000L)
+#define P 24
+#define Bias 127
+#if 0
+#define IEEE_Arith /* it is, but the code doesn't handle IEEE singles yet */
+#endif
+#define Emin (-126)
+#define Exp_1 ((__uint32_t)0x3f800000L)
+#define Exp_11 ((__uint32_t)0x3f800000L)
+#define Ebits 8
+#define Frac_mask ((__uint32_t)0x007fffffL)
+#define Frac_mask1 ((__uint32_t)0x007fffffL)
+#define Ten_pmax 10
+#define Sign_bit ((__uint32_t)0x80000000L)
+#define Ten_pmax 10
+#define Bletch 2
+#define Bndry_mask ((__uint32_t)0x007fffffL)
+#define Bndry_mask1 ((__uint32_t)0x007fffffL)
+#define LSB 1
+#define Sign_bit ((__uint32_t)0x80000000L)
+#define Log2P 1
+#define Tiny0 0
+#define Tiny1 1
+#define Quick_max 5
+#define Int_max 6
+#define Infinite(x) (word0(x) == ((__uint32_t)0x7f800000L))
+#undef word0
+#undef word1
+
+#define word0(x) (x.i[0])
+#define word1(x) 0
+#else
+
+#define Exp_shift 20
+#define Exp_shift1 20
+#define Exp_msk1 ((__uint32_t)0x100000L)
+#define Exp_msk11 ((__uint32_t)0x100000L)
+#define Exp_mask ((__uint32_t)0x7ff00000L)
+#define P 53
+#define Bias 1023
+#define IEEE_Arith
+#define Emin (-1022)
+#define Exp_1 ((__uint32_t)0x3ff00000L)
+#define Exp_11 ((__uint32_t)0x3ff00000L)
+#define Ebits 11
+#define Frac_mask ((__uint32_t)0xfffffL)
+#define Frac_mask1 ((__uint32_t)0xfffffL)
+#define Ten_pmax 22
+#define Bletch 0x10
+#define Bndry_mask ((__uint32_t)0xfffffL)
+#define Bndry_mask1 ((__uint32_t)0xfffffL)
+#define LSB 1
+#define Sign_bit ((__uint32_t)0x80000000L)
+#define Log2P 1
+#define Tiny0 0
+#define Tiny1 1
+#define Quick_max 14
+#define Int_max 14
+#define Infinite(x) (word0(x) == ((__uint32_t)0x7ff00000L)) /* sufficient test for here */
+#endif
+
+#else
+#undef Sudden_Underflow
+#define Sudden_Underflow
+#ifdef IBM
+#define Exp_shift 24
+#define Exp_shift1 24
+#define Exp_msk1 ((__uint32_t)0x1000000L)
+#define Exp_msk11 ((__uint32_t)0x1000000L)
+#define Exp_mask ((__uint32_t)0x7f000000L)
+#define P 14
+#define Bias 65
+#define Exp_1 ((__uint32_t)0x41000000L)
+#define Exp_11 ((__uint32_t)0x41000000L)
+#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
+#define Frac_mask ((__uint32_t)0xffffffL)
+#define Frac_mask1 ((__uint32_t)0xffffffL)
+#define Bletch 4
+#define Ten_pmax 22
+#define Bndry_mask ((__uint32_t)0xefffffL)
+#define Bndry_mask1 ((__uint32_t)0xffffffL)
+#define LSB 1
+#define Sign_bit ((__uint32_t)0x80000000L)
+#define Log2P 4
+#define Tiny0 ((__uint32_t)0x100000L)
+#define Tiny1 0
+#define Quick_max 14
+#define Int_max 15
+#else /* VAX */
+#define Exp_shift 23
+#define Exp_shift1 7
+#define Exp_msk1 0x80
+#define Exp_msk11 ((__uint32_t)0x800000L)
+#define Exp_mask ((__uint32_t)0x7f80L)
+#define P 56
+#define Bias 129
+#define Exp_1 ((__uint32_t)0x40800000L)
+#define Exp_11 ((__uint32_t)0x4080L)
+#define Ebits 8
+#define Frac_mask ((__uint32_t)0x7fffffL)
+#define Frac_mask1 ((__uint32_t)0xffff007fL)
+#define Ten_pmax 24
+#define Bletch 2
+#define Bndry_mask ((__uint32_t)0xffff007fL)
+#define Bndry_mask1 ((__uint32_t)0xffff007fL)
+#define LSB ((__uint32_t)0x10000L)
+#define Sign_bit ((__uint32_t)0x8000L)
+#define Log2P 1
+#define Tiny0 0x80
+#define Tiny1 0
+#define Quick_max 15
+#define Int_max 15
+#endif
+#endif
+
+#ifndef IEEE_Arith
+#define ROUND_BIASED
+#endif
+
+#ifdef RND_PRODQUOT
+#define rounded_product(a,b) a = rnd_prod(a, b)
+#define rounded_quotient(a,b) a = rnd_quot(a, b)
+#ifdef KR_headers
+extern double rnd_prod(), rnd_quot();
+#else
+extern double rnd_prod(double, double), rnd_quot(double, double);
+#endif
+#else
+#define rounded_product(a,b) a *= b
+#define rounded_quotient(a,b) a /= b
+#endif
+
+#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
+#define Big1 ((__uint32_t)0xffffffffL)
+
+#ifndef Just_16
+/* When Pack_32 is not defined, we store 16 bits per 32-bit long.
+ * This makes some inner loops simpler and sometimes saves work
+ * during multiplications, but it often seems to make things slightly
+ * slower. Hence the default is now to store 32 bits per long.
+ */
+
+#ifndef Pack_32
+#define Pack_32
+#endif
+#endif
+
+
+#define MAX_BIGNUMS 16
+#define MAX_BIGNUM_WDS 32
+
+struct _Jv_Bigint
+{
+ struct _Jv_Bigint *_next;
+ int _k, _maxwds, _sign, _wds;
+ unsigned long _x[MAX_BIGNUM_WDS];
+};
+
+
+#define _PTR void *
+#define _AND ,
+#define _NOARGS void
+#define _CONST const
+#define _VOLATILE volatile
+#define _SIGNED signed
+#define _DOTS , ...
+#define _VOID void
+#define _EXFUN(name, proto) name proto
+#define _DEFUN(name, arglist, args) name(args)
+#define _DEFUN_VOID(name) name(_NOARGS)
+#define _CAST_VOID (void)
+
+
+struct _Jv_reent
+{
+ /* local copy of errno */
+ int _errno;
+
+ /* used by mprec routines */
+ struct _Jv_Bigint *_result;
+ int _result_k;
+ struct _Jv_Bigint *_p5s;
+
+ struct _Jv_Bigint _freelist[MAX_BIGNUMS];
+ int _allocation_map;
+
+ int num;
+};
+
+
+typedef struct _Jv_Bigint _Jv_Bigint;
+
+#define Balloc _Jv_Balloc
+#define Bfree _Jv_Bfree
+#define multadd _Jv_multadd
+#define s2b _Jv_s2b
+#define lo0bits _Jv_lo0bits
+#define hi0bits _Jv_hi0bits
+#define i2b _Jv_i2b
+#define mult _Jv_mult
+#define pow5mult _Jv_pow5mult
+#define lshift _Jv_lshift
+#define cmp _Jv__mcmp
+#define diff _Jv__mdiff
+#define ulp _Jv_ulp
+#define b2d _Jv_b2d
+#define d2b _Jv_d2b
+#define ratio _Jv_ratio
+
+#define tens _Jv__mprec_tens
+#define bigtens _Jv__mprec_bigtens
+#define tinytens _Jv__mprec_tinytens
+
+#define _dtoa _Jv_dtoa
+#define _dtoa_r _Jv_dtoa_r
+#define _strtod_r _Jv_strtod_r
+
+extern double _EXFUN(_strtod_r, (struct _Jv_reent *ptr, const char *s00, char **se));
+extern char* _EXFUN(_dtoa_r, (struct _Jv_reent *ptr, double d,
+ int mode, int ndigits, int *decpt, int *sign,
+ char **rve, int float_type));
+void _EXFUN(_dtoa, (double d, int mode, int ndigits, int *decpt, int *sign,
+ char **rve, char *buf, int float_type));
+
+double _EXFUN(ulp,(double x));
+double _EXFUN(b2d,(_Jv_Bigint *a , int *e));
+_Jv_Bigint * _EXFUN(Balloc,(struct _Jv_reent *p, int k));
+void _EXFUN(Bfree,(struct _Jv_reent *p, _Jv_Bigint *v));
+_Jv_Bigint * _EXFUN(multadd,(struct _Jv_reent *p, _Jv_Bigint *, int, int));
+_Jv_Bigint * _EXFUN(s2b,(struct _Jv_reent *, const char*, int, int, unsigned long));
+_Jv_Bigint * _EXFUN(i2b,(struct _Jv_reent *,int));
+_Jv_Bigint * _EXFUN(mult, (struct _Jv_reent *, _Jv_Bigint *, _Jv_Bigint *));
+_Jv_Bigint * _EXFUN(pow5mult, (struct _Jv_reent *, _Jv_Bigint *, int k));
+int _EXFUN(hi0bits,(unsigned long));
+int _EXFUN(lo0bits,(unsigned long *));
+_Jv_Bigint * _EXFUN(d2b,(struct _Jv_reent *p, double d, int *e, int *bits));
+_Jv_Bigint * _EXFUN(lshift,(struct _Jv_reent *p, _Jv_Bigint *b, int k));
+_Jv_Bigint * _EXFUN(diff,(struct _Jv_reent *p, _Jv_Bigint *a, _Jv_Bigint *b));
+int _EXFUN(cmp,(_Jv_Bigint *a, _Jv_Bigint *b));
+
+double _EXFUN(ratio,(_Jv_Bigint *a, _Jv_Bigint *b));
+#define Bcopy(x,y) memcpy((char *)&x->_sign, (char *)&y->_sign, y->_wds*sizeof(long) + 2*sizeof(int))
+
+#if defined(_DOUBLE_IS_32BITS) && defined(__v800)
+#define n_bigtens 2
+#else
+#define n_bigtens 5
+#endif
+
+extern _CONST double tinytens[];
+extern _CONST double bigtens[];
+extern _CONST double tens[];
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/libjava/java/lang/natCharacter.cc b/libjava/java/lang/natCharacter.cc
new file mode 100644
index 00000000000..36cf5700fe5
--- /dev/null
+++ b/libjava/java/lang/natCharacter.cc
@@ -0,0 +1,269 @@
+// natCharacter.cc - Native part of Character class.
+
+/* 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 <cni.h>
+#include <jvm.h>
+#include <java/lang/Character.h>
+
+#include <java-chartables.h>
+
+
+
+#define asize(x) ((sizeof (x)) / sizeof (x[0]))
+
+static jchar
+to_lower_title (jchar ch)
+{
+ for (unsigned int i = 0; i < asize (title_to_upper_table); ++i)
+ {
+ // We can assume that the entries in the two tables are
+ // parallel. This is checked in the script.
+ if (title_to_upper_table[i][1] == ch
+ || title_to_upper_table[i][0] == ch)
+ return title_to_lower_table[i][1];
+ }
+ return ch;
+}
+
+static jchar
+to_upper_title (jchar ch)
+{
+ for (unsigned int i = 0; i < asize (title_to_lower_table); ++i)
+ {
+ // We can assume that the entries in the two tables are
+ // parallel. This is checked in the script.
+ if (title_to_lower_table[i][1] == ch
+ || title_to_lower_table[i][0] == ch)
+ return title_to_upper_table[i][1];
+ }
+ return ch;
+}
+
+jboolean
+java::lang::Character::isTitleCase (jchar ch)
+{
+ for (unsigned int i = 0; i < asize (title_to_lower_table); ++i)
+ {
+ if (title_to_lower_table[i][0] == ch)
+ return true;
+ }
+ return false;
+}
+
+jchar
+java::lang::Character::toTitleCase (jchar ch)
+{
+ // Both titlecase mapping tables have the same length. This is
+ // checked in the chartables script.
+ for (unsigned int i = 0; i < asize (title_to_lower_table); ++i)
+ {
+ if (title_to_lower_table[i][0] == ch)
+ return ch;
+ if (title_to_lower_table[i][1] == ch)
+ return title_to_lower_table[i][0];
+ if (title_to_upper_table[i][1] == ch)
+ return title_to_upper_table[i][0];
+ }
+ return toUpperCase (ch);
+}
+
+#ifdef COMPACT_CHARACTER
+
+static int
+table_search (const jchar table[][2], int table_len, jchar ch)
+{
+ int low, high, i, old;
+
+ low = 0;
+ high = table_len;
+ i = high / 2;
+
+ while (true)
+ {
+ if (ch < table[i][0])
+ high = i;
+ else if (ch > table[i][1])
+ low = i;
+ else
+ return i;
+
+ old = i;
+ i = (high + low) / 2;
+ if (i == old)
+ break;
+ }
+
+ return -1;
+}
+
+jint
+java::lang::Character::digit_value (jchar ch)
+{
+ int index = table_search (digit_table, asize (digit_table), ch);
+ if (index == -1)
+ return -1;
+
+ jchar base = digit_table[index][0];
+ // Tamil doesn't have a digit `0'. So we special-case it here.
+ if (base == TAMIL_DIGIT_ONE)
+ return ch - base + 1;
+ return ch - base;
+}
+
+jint
+java::lang::Character::getNumericValue (jchar ch)
+{
+ jint d = digit (ch, 36);
+ if (d != -1)
+ return d;
+
+ for (unsigned int i = 0; i < asize (numeric_table); ++i)
+ {
+ if (numeric_table[i] == ch)
+ return numeric_value[i];
+ }
+
+ return -1;
+}
+
+jint
+java::lang::Character::getType (jchar ch)
+{
+ int index = table_search (all_table, asize (all_table), ch);
+ if (index != -1)
+ return category_table[index];
+ return UNASSIGNED;
+}
+
+jboolean
+java::lang::Character::isLowerCase (jchar ch)
+{
+ if (ch >= 0x2000 && ch <= 0x2fff)
+ return false;
+ if (table_search (lower_case_table, asize (lower_case_table), ch) != -1)
+ return true;
+
+ // FIXME: use a binary search.
+ for (unsigned int i = 0; i < asize (lower_anomalous_table); ++i)
+ {
+ if (lower_anomalous_table[i] == ch)
+ return true;
+ }
+ return false;
+}
+
+jboolean
+java::lang::Character::isSpaceChar (jchar ch)
+{
+ return table_search (space_table, asize (space_table), ch) != -1;
+}
+
+jboolean
+java::lang::Character::isUpperCase (jchar ch)
+{
+ if (ch >= 0x2000 && ch <= 0x2fff)
+ return false;
+ return table_search (upper_case_table, asize (upper_case_table), ch) != -1;
+}
+
+jchar
+java::lang::Character::toLowerCase (jchar ch)
+{
+ int index = table_search (upper_case_table, asize (upper_case_table), ch);
+ if (index == -1)
+ return to_lower_title (ch);
+ return (jchar) (ch - upper_case_table[index][0]
+ + upper_case_map_table[index]);
+}
+
+jchar
+java::lang::Character::toUpperCase (jchar ch)
+{
+ int index = table_search (lower_case_table, asize (lower_case_table), ch);
+ if (index == -1)
+ return to_upper_title (ch);
+ return (jchar) (ch - lower_case_table[index][0]
+ + lower_case_map_table[index]);
+}
+
+#else /* COMPACT_CHARACTER */
+
+jint
+java::lang::Character::digit_value (jchar ch)
+{
+ if (type_table[ch] == DECIMAL_DIGIT_NUMBER)
+ return attribute_table[ch];
+ return -1;
+}
+
+jint
+java::lang::Character::getNumericValue (jchar ch)
+{
+ jint d = digit (ch, 36);
+ if (d != -1)
+ return d;
+
+ // Some characters require two attributes. We special-case them here.
+ if (ch >= ROMAN_START && ch <= ROMAN_END)
+ return secondary_attribute_table[ch - ROMAN_START];
+ if (type_table[ch] == LETTER_NUMBER || type_table[ch] == OTHER_NUMBER)
+ return attribute_table[ch];
+ return -1;
+}
+
+jint
+java::lang::Character::getType (jchar ch)
+{
+ return type_table[ch];
+}
+
+jboolean
+java::lang::Character::isLowerCase (jchar ch)
+{
+ if (ch >= 0x2000 && ch <= 0x2fff)
+ return false;
+ return type_table[ch] == LOWERCASE_LETTER;
+}
+
+jboolean
+java::lang::Character::isSpaceChar (jchar ch)
+{
+ return (type_table[ch] == SPACE_SEPARATOR
+ || type_table[ch] == LINE_SEPARATOR
+ || type_table[ch] == PARAGRAPH_SEPARATOR);
+}
+
+jboolean
+java::lang::Character::isUpperCase (jchar ch)
+{
+ if (ch >= 0x2000 && ch <= 0x2fff)
+ return false;
+ return type_table[ch] == UPPERCASE_LETTER;
+}
+
+jchar
+java::lang::Character::toLowerCase (jchar ch)
+{
+ if (type_table[ch] == UPPERCASE_LETTER)
+ return attribute_table[ch];
+ return to_lower_title (ch);
+}
+
+jchar
+java::lang::Character::toUpperCase (jchar ch)
+{
+ if (type_table[ch] == LOWERCASE_LETTER)
+ return attribute_table[ch];
+ return to_upper_title (ch);
+}
+
+#endif /* COMPACT_CHARACTER */
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
new file mode 100644
index 00000000000..1768df5ecb2
--- /dev/null
+++ b/libjava/java/lang/natClass.cc
@@ -0,0 +1,785 @@
+// natClass.cc - Implementation of java.lang.Class native methods.
+
+/* 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 <stdlib.h>
+#include <string.h>
+
+#pragma implementation "Class.h"
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/lang/Class.h>
+#include <java/lang/ClassLoader.h>
+#include <java/lang/String.h>
+#include <java/lang/reflect/Modifier.h>
+#include <java/lang/reflect/Member.h>
+#include <java/lang/reflect/Method.h>
+#include <java/lang/reflect/Field.h>
+#include <java/lang/reflect/Constructor.h>
+#include <java/lang/AbstractMethodError.h>
+#include <java/lang/ClassNotFoundException.h>
+#include <java/lang/IllegalAccessException.h>
+#include <java/lang/IllegalAccessError.h>
+#include <java/lang/IncompatibleClassChangeError.h>
+#include <java/lang/InstantiationException.h>
+#include <java/lang/NoClassDefFoundError.h>
+#include <java/lang/NoSuchFieldException.h>
+#include <java/lang/NoSuchMethodException.h>
+#include <java/lang/Thread.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/System.h>
+#include <java/lang/SecurityManager.h>
+
+
+
+#define CloneableClass _CL_Q34java4lang9Cloneable
+extern java::lang::Class CloneableClass;
+#define ObjectClass _CL_Q34java4lang6Object
+extern java::lang::Class ObjectClass;
+#define ErrorClass _CL_Q34java4lang5Error
+extern java::lang::Class ErrorClass;
+#define ClassClass _CL_Q34java4lang5Class
+extern java::lang::Class ClassClass;
+#define MethodClass _CL_Q44java4lang7reflect6Method
+extern java::lang::Class MethodClass;
+#define FieldClass _CL_Q44java4lang7reflect5Field
+extern java::lang::Class FieldClass;
+
+// Some constants we use to look up the class initializer.
+static _Jv_Utf8Const *void_signature = _Jv_makeUtf8Const ("()V", 3);
+static _Jv_Utf8Const *clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
+static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
+
+// These are the possible values for the `state' field. They more or
+// less follow the section numbers in the Java Language Spec. Right
+// now we don't bother to represent other interesting states, e.g. the
+// states a class might inhabit before it is prepared. Note that
+// ordering is important here; in particular `resolved' must come
+// between `nothing' and the other states.
+#define STATE_NOTHING 0
+#define STATE_RESOLVED 1
+#define STATE_IN_PROGRESS 6
+#define STATE_DONE 9
+#define STATE_ERROR 10
+
+// Size of local hash table.
+#define HASH_LEN 256
+
+// Hash function for Utf8Consts.
+#define HASH_UTF(Utf) (((Utf)->hash) % HASH_LEN)
+
+// This is the table we use to keep track of loaded classes. See Spec
+// section 12.2.
+static jclass loaded_classes[HASH_LEN];
+
+
+
+jclass
+java::lang::Class::forName (jstring className)
+{
+ if (! className)
+ JvThrow (new java::lang::NullPointerException);
+
+#if 0
+ // FIXME: should check syntax of CLASSNAME and throw
+ // IllegalArgumentException on failure.
+
+ // FIXME: should use class loader from calling method.
+ jclass klass = _Jv_FindClass (className, NULL);
+#else
+ jsize length = _Jv_GetStringUTFLength (className);
+ char buffer[length];
+ _Jv_GetStringUTFRegion (className, 0, length, buffer);
+
+ // FIXME: should check syntax of CLASSNAME and throw
+ // IllegalArgumentException on failure.
+ _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
+
+ // FIXME: should use class loader from calling method.
+ jclass klass = (buffer[0] == '['
+ ? _Jv_FindClassFromSignature (name->data, NULL)
+ : _Jv_FindClass (name, NULL));
+#endif
+ if (! klass)
+ JvThrow (new java::lang::ClassNotFoundException (className));
+ return klass;
+}
+
+java::lang::reflect::Constructor *
+java::lang::Class::getConstructor (JArray<jclass> *)
+{
+ JvFail ("java::lang::Class::getConstructor not implemented");
+}
+
+JArray<java::lang::reflect::Constructor *> *
+java::lang::Class::getConstructors (void)
+{
+ JvFail ("java::lang::Class::getConstructors not implemented");
+}
+
+java::lang::reflect::Constructor *
+java::lang::Class::getDeclaredConstructor (JArray<jclass> *)
+{
+ JvFail ("java::lang::Class::getDeclaredConstructor not implemented");
+}
+
+JArray<java::lang::reflect::Constructor *> *
+java::lang::Class::getDeclaredConstructors (void)
+{
+ JvFail ("java::lang::Class::getDeclaredConstructors not implemented");
+}
+
+java::lang::reflect::Field *
+java::lang::Class::getField (jstring name, jint hash)
+{
+ java::lang::reflect::Field* rfield;
+ for (int i = 0; i < field_count; i++)
+ {
+ _Jv_Field *field = &fields[i];
+ if (! _Jv_equal (field->name, name, hash))
+ continue;
+ if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
+ continue;
+ rfield = new java::lang::reflect::Field ();
+ rfield->offset = (char*) field - (char*) fields;
+ rfield->declaringClass = this;
+ rfield->name = name;
+ return rfield;
+ }
+ jclass superclass = getSuperclass();
+ if (superclass == NULL)
+ return NULL;
+ rfield = superclass->getField(name, hash);
+ for (int i = 0; i < interface_count && rfield == NULL; ++i)
+ rfield = interfaces[i]->getField (name, hash);
+ return rfield;
+}
+
+java::lang::reflect::Field *
+java::lang::Class::getDeclaredField (jstring name)
+{
+ java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
+ if (s != NULL)
+ s->checkMemberAccess (this, java::lang::reflect::Member::DECLARED);
+ int hash = name->hashCode();
+ for (int i = 0; i < field_count; i++)
+ {
+ _Jv_Field *field = &fields[i];
+ if (! _Jv_equal (field->name, name, hash))
+ continue;
+ java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
+ rfield->offset = (char*) field - (char*) fields;
+ rfield->declaringClass = this;
+ rfield->name = name;
+ return rfield;
+ }
+ JvThrow (new java::lang::NoSuchFieldException (name));
+}
+
+JArray<java::lang::reflect::Field *> *
+java::lang::Class::getDeclaredFields (void)
+{
+ java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
+ if (s != NULL)
+ s->checkMemberAccess (this, java::lang::reflect::Member::DECLARED);
+ JArray<java::lang::reflect::Field *> *result
+ = (JArray<java::lang::reflect::Field *> *)
+ JvNewObjectArray (field_count, &FieldClass, NULL);
+ java::lang::reflect::Field** fptr = elements (result);
+ for (int i = 0; i < field_count; i++)
+ {
+ _Jv_Field *field = &fields[i];
+ java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
+ rfield->offset = (char*) field - (char*) fields;
+ rfield->declaringClass = this;
+ *fptr++ = rfield;
+ }
+ return result;
+}
+
+java::lang::reflect::Method *
+java::lang::Class::getDeclaredMethod (jstring, JArray<jclass> *)
+{
+ JvFail ("java::lang::Class::getDeclaredMethod not implemented");
+}
+
+JArray<java::lang::reflect::Method *> *
+java::lang::Class::getDeclaredMethods (void)
+{
+ int numMethods = 0;
+ int i;
+ for (i = method_count; --i >= 0; )
+ {
+ _Jv_Method *method = &methods[i];
+ if (method->name == NULL
+ || _Jv_equalUtf8Consts (method->name, clinit_name)
+ || _Jv_equalUtf8Consts (method->name, init_name))
+ continue;
+ numMethods++;
+ }
+ JArray<java::lang::reflect::Method *> *result
+ = (JArray<java::lang::reflect::Method *> *)
+ JvNewObjectArray (numMethods, &MethodClass, NULL);
+ java::lang::reflect::Method** mptr = elements (result);
+ for (i = 0; i < method_count; i++)
+ {
+ _Jv_Method *method = &methods[i];
+ if (method->name == NULL
+ || _Jv_equalUtf8Consts (method->name, clinit_name)
+ || _Jv_equalUtf8Consts (method->name, init_name))
+ continue;
+ java::lang::reflect::Method* rmethod = new java::lang::reflect::Method ();
+ rmethod->offset = (char*) mptr - (char*) elements (result);
+ rmethod->declaringClass = this;
+ *mptr++ = rmethod;
+ }
+ return result;
+}
+
+jstring
+java::lang::Class::getName (void)
+{
+ char buffer[name->length + 1];
+ memcpy (buffer, name->data, name->length);
+ buffer[name->length] = '\0';
+ return _Jv_NewStringUTF (buffer);
+}
+
+JArray<jclass> *
+java::lang::Class::getClasses (void)
+{
+ // FIXME: implement.
+ return NULL;
+}
+
+JArray<jclass> *
+java::lang::Class::getDeclaredClasses (void)
+{
+ checkMemberAccess (java::lang::reflect::Member::DECLARED);
+ JvFail ("java::lang::Class::getDeclaredClasses not implemented");
+ return NULL; // Placate compiler.
+}
+
+// This is marked as unimplemented in the JCL book.
+jclass
+java::lang::Class::getDeclaringClass (void)
+{
+ JvFail ("java::lang::Class::getDeclaringClass unimplemented");
+ return NULL; // Placate compiler.
+}
+
+JArray<java::lang::reflect::Field *> *
+java::lang::Class::getFields (void)
+{
+ JvFail ("java::lang::Class::getFields not implemented");
+}
+
+JArray<jclass> *
+java::lang::Class::getInterfaces (void)
+{
+ jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL);
+ jobject *data = elements (r);
+ for (int i = 0; i < interface_count; ++i)
+ data[i] = interfaces[i];
+ return reinterpret_cast<JArray<jclass> *> (r);
+}
+
+java::lang::reflect::Method *
+java::lang::Class::getMethod (jstring, JArray<jclass> *)
+{
+ JvFail ("java::lang::Class::getMethod not implemented");
+}
+
+JArray<java::lang::reflect::Method *> *
+java::lang::Class::getMethods (void)
+{
+ JvFail ("java::lang::Class::getMethods not implemented");
+}
+
+jboolean
+java::lang::Class::isAssignableFrom (jclass klass)
+{
+ if (this == klass)
+ return true;
+ // Primitive types must be equal, which we just tested for.
+ if (isPrimitive () || ! klass || klass->isPrimitive())
+ return false;
+
+ // If target is array, so must source be.
+ if (isArray ())
+ {
+ if (! klass->isArray())
+ return false;
+ return getComponentType()->isAssignableFrom(klass->getComponentType());
+ }
+
+ if (isAssignableFrom (klass->getSuperclass()))
+ return true;
+
+ if (isInterface())
+ {
+ // See if source implements this interface.
+ for (int i = 0; i < klass->interface_count; ++i)
+ {
+ jclass interface = klass->interfaces[i];
+ // FIXME: ensure that class is prepared here.
+ // See Spec 12.3.2.
+ if (isAssignableFrom (interface))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+jboolean
+java::lang::Class::isInstance (jobject obj)
+{
+ if (! obj || isPrimitive ())
+ return false;
+ return isAssignableFrom (obj->getClass());
+}
+
+jboolean
+java::lang::Class::isInterface (void)
+{
+ return (accflags & java::lang::reflect::Modifier::INTERFACE) != 0;
+}
+
+jobject
+java::lang::Class::newInstance (void)
+{
+ // FIXME: do accessibility checks here. There currently doesn't
+ // seem to be any way to do these.
+ // FIXME: we special-case one check here just to pass a Plum Hall
+ // test. Once access checking is implemented, remove this.
+ if (this == &ClassClass)
+ JvThrow (new java::lang::IllegalAccessException);
+
+ if (isPrimitive ()
+ || isInterface ()
+ || isArray ()
+ || java::lang::reflect::Modifier::isAbstract(accflags))
+ JvThrow (new java::lang::InstantiationException);
+
+ _Jv_Method *meth = _Jv_GetMethodLocal (this, init_name, void_signature);
+ if (! meth)
+ JvThrow (new java::lang::NoSuchMethodException);
+
+ jobject r = JvAllocObject (this);
+ ((void (*) (jobject)) meth->ncode) (r);
+ return r;
+}
+
+// Initialize the constants.
+void
+java::lang::Class::resolveConstants (void)
+{
+ for (int i = 0; i < constants.size; ++i)
+ {
+ if (constants.tags[i] == CONSTANT_String)
+ {
+ jstring str;
+ str = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) constants.data[i]);
+ constants.data[i] = (void *) str;
+ constants.tags[i] = CONSTANT_ResolvedString;
+ }
+ else if (constants.tags[i] == CONSTANT_Class)
+ {
+ _Jv_Utf8Const *name = (_Jv_Utf8Const *) constants.data[i];
+ jclass klass = _Jv_FindClassFromSignature (name->data, loader);
+ if (! klass)
+ {
+ jstring str = _Jv_NewStringUtf8Const (name);
+ JvThrow (new java::lang::ClassNotFoundException (str));
+ }
+
+ constants.data[i] = (void *) klass;
+ constants.tags[i] = CONSTANT_ResolvedClass;
+ }
+ }
+}
+
+// FIXME.
+void
+java::lang::Class::hackRunInitializers (void)
+{
+ _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name, void_signature);
+ if (meth)
+ ((void (*) (void)) meth->ncode) ();
+}
+
+// This implements the initialization process for a class. From Spec
+// section 12.4.2.
+void
+java::lang::Class::initializeClass (void)
+{
+ // Short-circuit to avoid needless locking.
+ if (state == STATE_DONE)
+ return;
+
+ // Step 1.
+ _Jv_MonitorEnter (this);
+
+ // FIXME: This should actually be handled by calling into the class
+ // loader. For now we put it here.
+ if (state < STATE_RESOLVED)
+ {
+ // We set the state before calling resolveConstants to avoid
+ // infinite recursion when processing String or Class.
+ state = STATE_RESOLVED;
+ resolveConstants ();
+ }
+
+ // Step 2.
+ java::lang::Thread *self = java::lang::Thread::currentThread();
+ // FIXME: `self' can be null at startup. Hence this nasty trick.
+ self = (java::lang::Thread *) ((long) self | 1);
+ while (state == STATE_IN_PROGRESS && thread && thread != self)
+ wait ();
+
+ // Steps 3 & 4.
+ if (state == STATE_DONE || state == STATE_IN_PROGRESS || thread == self)
+ {
+ _Jv_MonitorExit (this);
+ return;
+ }
+
+ // Step 5.
+ if (state == STATE_ERROR)
+ {
+ _Jv_MonitorExit (this);
+ JvThrow (new java::lang::NoClassDefFoundError);
+ }
+
+ // Step 6.
+ thread = self;
+ state = STATE_IN_PROGRESS;
+ _Jv_MonitorExit (this);
+
+ // Step 7.
+ if (! isInterface () && superclass)
+ {
+ // FIXME: We can't currently catch a Java exception in C++ code.
+ // So instead we call a Java trampoline. It returns an
+ // exception, or null.
+ jobject except = superclass->hackTrampoline(0, NULL);
+ if (except)
+ {
+ // Caught an exception.
+ _Jv_MonitorEnter (this);
+ state = STATE_ERROR;
+ notify ();
+ _Jv_MonitorExit (this);
+ JvThrow (except);
+ }
+ }
+
+ // Step 8.
+ // FIXME: once again we have to go through a trampoline.
+ java::lang::Throwable *except = hackTrampoline (1, NULL);
+
+ // Steps 9, 10, 11.
+ if (! except)
+ {
+ _Jv_MonitorEnter (this);
+ state = STATE_DONE;
+ }
+ else
+ {
+ if (! ErrorClass.isInstance(except))
+ {
+ // Once again we must use the trampoline. In this case we
+ // have to detect an OutOfMemoryError.
+ except = hackTrampoline(2, except);
+ }
+ _Jv_MonitorEnter (this);
+ state = STATE_ERROR;
+ }
+ notify ();
+ _Jv_MonitorExit (this);
+ if (except)
+ JvThrow (except);
+}
+
+
+
+//
+// Some class-related convenience functions.
+//
+
+_Jv_Method *
+_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
+ _Jv_Utf8Const *signature)
+{
+ for (int i = 0; i < klass->method_count; ++i)
+ {
+ if (_Jv_equalUtf8Consts (name, klass->methods[i].name)
+ && _Jv_equalUtf8Consts (signature, klass->methods[i].signature))
+ return &klass->methods[i];
+ }
+ return NULL;
+}
+
+void *
+_Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
+ _Jv_Utf8Const *signature)
+{
+ // FIXME: can't do this until we have a working class loader.
+ // This probably isn't the right thing to do anyway, since we can't
+ // call a method of a class until the class is linked. But this
+ // captures the general idea.
+ // klass->getClassLoader()->resolveClass(klass);
+
+ for (; klass; klass = klass->getSuperclass())
+ {
+ _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
+ if (! meth)
+ continue;
+
+ if (java::lang::reflect::Modifier::isStatic(meth->accflags))
+ JvThrow (new java::lang::IncompatibleClassChangeError);
+ if (java::lang::reflect::Modifier::isAbstract(meth->accflags))
+ JvThrow (new java::lang::AbstractMethodError);
+ if (! java::lang::reflect::Modifier::isPublic(meth->accflags))
+ JvThrow (new java::lang::IllegalAccessError);
+
+ return meth->ncode;
+ }
+ JvThrow (new java::lang::IncompatibleClassChangeError);
+ return NULL; // Placate compiler.
+}
+
+void
+_Jv_InitClass (jclass klass)
+{
+ klass->initializeClass();
+}
+
+// This function is called many times during startup, before main() is
+// run. We do our runtime initialization here the very first time we
+// are called. At that point in time we know for certain we are
+// running single-threaded, so we don't need to lock when modifying
+// `init'. CLASSES is NULL-terminated.
+void
+_Jv_RegisterClasses (jclass *classes)
+{
+ static bool init = false;
+
+ if (! init)
+ {
+ init = true;
+ _Jv_InitThreads ();
+ _Jv_InitGC ();
+ _Jv_InitializeSyncMutex ();
+ }
+
+ JvSynchronize sync (&ClassClass);
+ for (; *classes; ++classes)
+ {
+ jclass klass = *classes;
+ jint hash = HASH_UTF (klass->name);
+ klass->next = loaded_classes[hash];
+ loaded_classes[hash] = klass;
+ }
+}
+
+void
+_Jv_RegisterClass (jclass klass)
+{
+ jclass classes[2];
+ classes[0] = klass;
+ classes[1] = NULL;
+ _Jv_RegisterClasses (classes);
+}
+
+jclass
+_Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
+{
+ JvSynchronize sync (&ClassClass);
+ jint hash = HASH_UTF (name);
+ jclass klass;
+ for (klass = loaded_classes[hash]; klass; klass = klass->next)
+ {
+ if (loader == klass->loader && _Jv_equalUtf8Consts (name, klass->name))
+ break;
+ }
+ return klass;
+}
+
+#if 0
+jclass
+_Jv_FindClassInCache (jstring name, java::lang::ClassLoader *loader)
+{
+ JvSynchronize sync (&ClassClass);
+ jint hash = name->hashCode();
+ jclass klass = loaded_classes[(_Jv_ushort) hash % HASH_LEN];
+ for ( ; klass; klass = klass->next)
+ {
+ if (loader == klass->loader
+ && _Jv_equalUtf8Consts (klass->name, name, hash))
+ break;
+ }
+ return klass;
+}
+#endif
+
+jclass
+_Jv_FindClass (_Jv_Utf8Const* name, java::lang::ClassLoader *loader)
+{
+ jclass klass = _Jv_FindClassInCache (name, loader);
+ if (loader && ! klass)
+ {
+ klass = loader->loadClass(_Jv_NewStringUtf8Const (name));
+ if (klass)
+ _Jv_RegisterClass (klass);
+ }
+ return klass;
+}
+
+#if 0
+jclass
+_Jv_FindClass (jstring name, java::lang::ClassLoader *loader)
+{
+ jclass klass = _Jv_FindClassInCache (name, loader);
+ if (loader && ! klass)
+ {
+ klass = loader->loadClass(name);
+ if (klass)
+ _Jv_RegisterClass (klass);
+ }
+ return klass;
+}
+#endif
+
+jclass
+_Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
+ java::lang::ClassLoader *loader)
+{
+ jclass ret = (jclass) JvAllocObject (&ClassClass);
+
+ ret->next = NULL;
+ ret->name = name;
+ ret->accflags = 0;
+ ret->superclass = superclass;
+ ret->constants.size = 0;
+ ret->constants.tags = NULL;
+ ret->constants.data = NULL;
+ ret->methods = NULL;
+ ret->method_count = 0;
+ ret->vtable_method_count = 0;
+ ret->fields = NULL;
+ ret->size_in_bytes = 0;
+ ret->field_count = 0;
+ ret->static_field_count = 0;
+ ret->vtable = NULL;
+ ret->interfaces = NULL;
+ ret->loader = loader;
+ ret->interface_count = 0;
+ ret->state = 0;
+ ret->thread = NULL;
+
+ _Jv_RegisterClass (ret);
+
+ return ret;
+}
+
+jclass
+_Jv_FindArrayClass (jclass element)
+{
+ _Jv_Utf8Const *array_name;
+ int len;
+ if (element->isPrimitive())
+ {
+ // For primitive types the array is cached in the class.
+ jclass ret = (jclass) element->methods;
+ if (ret)
+ return ret;
+ len = 3;
+ }
+ else
+ len = element->name->length + 5;
+
+ {
+ char signature[len];
+ int index = 0;
+ signature[index++] = '[';
+ // Compute name of array class to see if we've already cached it.
+ if (element->isPrimitive())
+ {
+ signature[index++] = (char) element->method_count;
+ }
+ else
+ {
+ size_t length = element->name->length;
+ const char *const name = element->name->data;
+ if (name[0] != '[')
+ signature[index++] = 'L';
+ memcpy (&signature[index], name, length);
+ index += length;
+ if (name[0] != '[')
+ signature[index++] = ';';
+ }
+ array_name = _Jv_makeUtf8Const (signature, index);
+ }
+
+ jclass array_class = _Jv_FindClassInCache (array_name, element->loader);
+
+ if (! array_class)
+ {
+ // Create new array class.
+ array_class = _Jv_NewClass (array_name, &ObjectClass, element->loader);
+
+ // Note that `vtable_method_count' doesn't include the initial
+ // NULL slot.
+ int dm_count = ObjectClass.vtable_method_count + 1;
+
+ // Create a new vtable by copying Object's vtable (except the
+ // class pointer, of course). Note that we allocate this as
+ // unscanned memory -- the vtables are handled specially by the
+ // GC.
+ int size = (sizeof (_Jv_VTable) +
+ ((dm_count - 1) * sizeof (void *)));
+ _Jv_VTable *vtable = (_Jv_VTable *) _Jv_AllocBytes (size);
+ vtable->clas = array_class;
+ memcpy (vtable->method, ObjectClass.vtable->method,
+ dm_count * sizeof (void *));
+ array_class->vtable = vtable;
+ array_class->vtable_method_count = ObjectClass.vtable_method_count;
+
+ // Stash the pointer to the element type.
+ array_class->methods = (_Jv_Method *) element;
+
+ // Register our interfaces.
+ // FIXME: for JDK 1.2 we need Serializable.
+ static jclass interfaces[] = { &CloneableClass };
+ array_class->interfaces = interfaces;
+ array_class->interface_count = 1;
+
+ // FIXME: initialize other Class instance variables,
+ // e.g. `fields'.
+
+ array_class->state = STATE_DONE;
+ }
+
+ // For primitive types, point back at this array.
+ if (element->isPrimitive())
+ element->methods = (_Jv_Method *) array_class;
+
+ return array_class;
+}
+
+jboolean
+_Jv_IsInstanceOf(jobject obj, jclass cl)
+{
+ return cl->isInstance(obj);
+}
diff --git a/libjava/java/lang/natDouble.cc b/libjava/java/lang/natDouble.cc
new file mode 100644
index 00000000000..17990884751
--- /dev/null
+++ b/libjava/java/lang/natDouble.cc
@@ -0,0 +1,180 @@
+// natDouble.cc - Implementation of java.lang.Double native methods.
+
+/* 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. */
+
+/* AIX requires this to be the first thing in the file. */
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+#endif
+
+#include <stdlib.h>
+
+#include <cni.h>
+#include <java/lang/String.h>
+#include <java/lang/Double.h>
+#include <java/lang/NumberFormatException.h>
+#include <jvm.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "mprec.h"
+
+union u
+{
+ jlong l;
+ jdouble d;
+};
+
+jlong
+java::lang::Double::doubleToLongBits(jdouble value)
+{
+ union u u;
+ u.d = value;
+ return u.l;
+}
+
+jdouble
+java::lang::Double::longBitsToDouble(jlong bits)
+{
+ union u u;
+ u.l = bits;
+ return u.d;
+}
+
+jstring
+java::lang::Double::toString(jdouble value, jboolean isFloat)
+{
+ if (isNaN (value))
+ return JvNewStringLatin1 ("NaN", sizeof ("NaN") - 1);
+
+ if (value == POSITIVE_INFINITY)
+ return JvNewStringLatin1 ("Infinity", sizeof ("Infinity") - 1);
+
+ if (value == NEGATIVE_INFINITY)
+ return JvNewStringLatin1 ("-Infinity", sizeof ("-Infinity") - 1);
+
+ char buffer[50], result[50];
+ int decpt, sign;
+
+ _dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int)isFloat);
+
+ value = fabs (value);
+
+ char *s = buffer;
+ char *d = result;
+
+ if (sign)
+ *d++ = '-';
+
+ if (value >= 1e-3 && value < 1e7 || value == 0)
+ {
+ if (decpt <= 0)
+ *d++ = '0';
+ else
+ {
+ for (int i = 0; i < decpt; i++)
+ if (*s)
+ *d++ = *s++;
+ else
+ *d++ = '0';
+ }
+
+ *d++ = '.';
+
+ if (*s == 0)
+ {
+ *d++ = '0';
+ decpt++;
+ }
+
+ while (decpt++ < 0)
+ *d++ = '0';
+
+ while (*s)
+ *d++ = *s++;
+
+ *d = 0;
+
+ return JvNewStringLatin1 (result, strlen (result));
+ }
+
+ *d++ = *s++;
+ decpt--;
+ *d++ = '.';
+
+ if (*s == 0)
+ *d++ = '0';
+
+ while (*s)
+ *d++ = *s++;
+
+ *d++ = 'E';
+
+ if (decpt < 0)
+ {
+ *d++ = '-';
+ decpt = -decpt;
+ }
+
+ {
+ char exp[4];
+ char *e = exp + sizeof exp;
+
+ *--e = 0;
+ do
+ {
+ *--e = '0' + decpt % 10;
+ decpt /= 10;
+ }
+ while (decpt > 0);
+
+ while (*e)
+ *d++ = *e++;
+ }
+
+ *d = 0;
+
+ return JvNewStringLatin1 (result, strlen (result));
+}
+
+jdouble
+java::lang::Double::doubleValueOf(jstring str)
+{
+ int length = str->length();
+ // Note that UTF can expand 3x.
+
+#ifdef HAVE_ALLOCA
+ char *data = (char *) alloca (3 * length + 1);
+#else
+#error --- need an alternate implementation here ---
+#endif
+
+ data[_Jv_GetStringUTFRegion (str, 0, length, data)] = 0;
+
+ struct _Jv_reent reent;
+ memset (&reent, 0, sizeof reent);
+
+ double val = _strtod_r (&reent, data, NULL);
+
+ if (reent._errno)
+ _Jv_Throw (new NumberFormatException);
+
+ return val;
+}
diff --git a/libjava/java/lang/natFirstThread.cc b/libjava/java/lang/natFirstThread.cc
new file mode 100644
index 00000000000..d47446be4a8
--- /dev/null
+++ b/libjava/java/lang/natFirstThread.cc
@@ -0,0 +1,56 @@
+// natFirstThread.cc - Implementation of FirstThread native methods.
+
+/* 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 <stdlib.h>
+
+#include <cni.h>
+#include <jvm.h>
+
+#include <java/lang/FirstThread.h>
+#include <java/lang/Class.h>
+#include <java/lang/String.h>
+#include <java/lang/System.h>
+#include <java/lang/reflect/Modifier.h>
+#include <java/io/PrintStream.h>
+
+#define DIE(Message) die (JvNewStringLatin1 (Message))
+
+typedef void main_func (jobject);
+
+void
+java::lang::FirstThread::run (void)
+{
+ Utf8Const* main_signature = _Jv_makeUtf8Const ("([Ljava.lang.String;)V", 22);
+ Utf8Const* main_name = _Jv_makeUtf8Const ("main", 4);
+
+#if 0
+ // Note: this turns out to be more painful than useful. Apparently
+ // many people rely on being able to have main in a non-public
+ // class.
+ // This is based on my reading of 12.3.3.
+ if (! java::lang::reflect::Modifier::isPublic(klass->getModifiers()))
+ DIE ("class must be public");
+#endif
+
+ _Jv_Method *meth = _Jv_GetMethodLocal (klass, main_name, main_signature);
+
+ // Some checks from Java Spec section 12.1.4.
+ if (meth == NULL)
+ DIE ("no suitable method `main' in class");
+ if (! java::lang::reflect::Modifier::isStatic(meth->accflags))
+ DIE ("`main' must be static");
+ if (! java::lang::reflect::Modifier::isPublic(meth->accflags))
+ DIE ("`main' must be public");
+
+ main_func *real_main = (main_func *) meth->ncode;
+ (*real_main) (args);
+}
diff --git a/libjava/java/lang/natFloat.cc b/libjava/java/lang/natFloat.cc
new file mode 100644
index 00000000000..e3189bebc2d
--- /dev/null
+++ b/libjava/java/lang/natFloat.cc
@@ -0,0 +1,37 @@
+// natFloat.cc - Implementation of java.lang.Float native methods.
+
+/* 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 <java/lang/Float.h>
+#include <jvm.h>
+
+union u
+{
+ jint l;
+ jfloat d;
+};
+
+jint
+java::lang::Float::floatToIntBits(jfloat value)
+{
+ union u u;
+ u.d = value;
+ return u.l;
+}
+
+jfloat
+java::lang::Float::intBitsToFloat(jint bits)
+{
+ union u u;
+ u.l = bits;
+ return u.d;
+}
+
diff --git a/libjava/java/lang/natMath.cc b/libjava/java/lang/natMath.cc
new file mode 100644
index 00000000000..66382473eed
--- /dev/null
+++ b/libjava/java/lang/natMath.cc
@@ -0,0 +1,263 @@
+/* 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. */
+
+/**
+ * @author Andrew Haley <aph@cygnus.com>
+ * @date Tue Sep 22 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.
+ */
+
+#include <config.h>
+
+#include <java/lang/String.h>
+#include <java/lang/Float.h>
+#include <java/lang/Double.h>
+#include <java/lang/Integer.h>
+#include <java/lang/Long.h>
+#include <java/lang/Math.h>
+#include <java-array.h>
+
+#include "fdlibm.h"
+
+jdouble java::lang::Math::cos(jdouble x)
+{
+ return (jdouble)::cos((double)x);
+}
+
+jdouble java::lang::Math::sin(jdouble x)
+{
+ return (jdouble)::sin((double)x);
+}
+
+jdouble java::lang::Math::tan(jdouble x)
+{
+ return (jdouble)::tan((double)x);
+}
+
+jdouble java::lang::Math::asin(jdouble x)
+{
+ return (jdouble)::asin((double)x);
+}
+
+jdouble java::lang::Math::acos(jdouble x)
+{
+ return (jdouble)::acos((double)x);
+}
+
+jdouble java::lang::Math::atan(jdouble x)
+{
+ return (jdouble)::atan((double)x);
+}
+
+jdouble java::lang::Math::atan2(jdouble y, jdouble x)
+{
+ return (jdouble)::atan2((jdouble)y, (jdouble)x);
+}
+
+jdouble java::lang::Math::log(jdouble x)
+{
+ return (jdouble)::log((double)x);
+}
+
+jdouble java::lang::Math::exp(jdouble x)
+{
+ return (jdouble)::exp((double)x);
+}
+
+jdouble java::lang::Math::sqrt(jdouble x)
+{
+ return (jdouble)::sqrt((double)x);
+}
+
+jdouble java::lang::Math::pow(jdouble y, jdouble x)
+{
+ return (jdouble)::pow((jdouble)y, (jdouble)x);
+}
+
+jdouble java::lang::Math::IEEEremainder(jdouble y, jdouble x)
+{
+ return (jdouble)::__ieee754_remainder((jdouble)y, (jdouble)x);
+}
+
+jdouble java::lang::Math::abs(jdouble x)
+{
+ return (jdouble)::fabs((double)x);
+}
+
+jfloat java::lang::Math::abs(jfloat x)
+{
+ return (jfloat)::fabsf((float)x);
+}
+
+jdouble java::lang::Math::rint(jdouble x)
+{
+ return (jdouble)::rint((double)x);
+}
+
+jint java::lang::Math::round(jfloat x)
+{
+ if (x != x)
+ return 0;
+ if (x <= (jfloat)java::lang::Integer::MIN_VALUE)
+ return java::lang::Integer::MIN_VALUE;
+ if (x >= (jfloat)java::lang::Integer::MAX_VALUE)
+ return java::lang::Integer::MAX_VALUE;
+
+ return (jint)::rintf((float)x);
+}
+
+jlong java::lang::Math::round(jdouble x)
+{
+ if (x != x)
+ return 0;
+ if (x <= (jdouble)java::lang::Long::MIN_VALUE)
+ return java::lang::Long::MIN_VALUE;
+ if (x >= (jdouble)java::lang::Long::MAX_VALUE)
+ return java::lang::Long::MAX_VALUE;
+
+ return (jlong)::rint((double)x);
+}
+
+jdouble java::lang::Math::floor(jdouble x)
+{
+ return (jdouble)::floor((double)x);
+}
+
+jdouble java::lang::Math::ceil(jdouble x)
+{
+ return (jdouble)::ceil((double)x);
+}
+
+static inline int
+floatToIntBits (jfloat value)
+{
+ union {
+ jint l;
+ jfloat d;
+ } u;
+ u.d = value;
+ return u.l;
+}
+
+static inline bool
+isNaN (jint bits)
+{
+ jint e = bits & 0x7f800000;
+ jint f = bits & 0x007fffff;
+
+ return e == 0x7f800000 && f != 0;
+}
+
+jfloat
+java::lang::Math::min(jfloat a, jfloat b)
+{
+ jint abits = floatToIntBits (a);
+ jint bbits = floatToIntBits (b);
+
+ if (isNaN (abits) || isNaN (bbits))
+ return java::lang::Float::NaN;
+
+ if (abits >= 0) // a is +ve
+ return bbits < 0 ? b // a is +ve, b is -ve.
+ // a and b are both +ve, so compare magnitudes: the number with
+ // the smallest magnitude is the smallest
+ : (abits < bbits ? a : b);
+ else // a is -ve
+ return bbits >= 0 ? a // a is -ve, b is +ve.
+ // a and b are both -ve, so compare magnitudes: the number with
+ // the biggest magnitude is the smallest
+ : (abits > bbits ? a : b);
+}
+
+jfloat
+java::lang::Math::max(jfloat a, jfloat b)
+{
+ jint abits = floatToIntBits (a);
+ jint bbits = floatToIntBits (b);
+
+ if (isNaN (abits) || isNaN (bbits))
+ return java::lang::Float::NaN;
+
+ if (abits >= 0) // a is +ve
+ return bbits < 0 ? a // a is +ve, b is -ve.
+ // a and b are both +ve, so compare magnitudes: the number with
+ // the smallest magnitude is the smallest
+ : (abits > bbits ? a : b);
+ else // a is -ve
+ return bbits >= 0 ? b // a is -ve, b is +ve.
+ // a and b are both -ve, so compare magnitudes: the number with
+ // the biggest magnitude is the smallest
+ : (abits < bbits ? a : b);
+}
+
+static inline jlong
+doubleToLongBits (jdouble value)
+{
+ union {
+ jlong l;
+ jdouble d;
+ } u;
+ u.d = value;
+ return u.l;
+}
+
+static inline bool
+isNaN (jlong bits)
+{
+ jlong e = bits & 0x7ff0000000000000LL;
+ jlong f = bits & 0x000fffffffffffffLL;
+
+ return e == 0x7ff0000000000000LL && f != 0LL;
+}
+
+
+jdouble
+java::lang::Math::min(jdouble a, jdouble b)
+{
+ jlong abits = doubleToLongBits (a);
+ jlong bbits = doubleToLongBits (b);
+
+ if (isNaN (abits) || isNaN (bbits))
+ return java::lang::Double::NaN;
+
+ if (abits >= 0LL) // a is +ve
+ return bbits < 0LL ? b // a is +ve, b is -ve.
+ // a and b are both +ve, so compare magnitudes: the number with
+ // the smallest magnitude is the smallest
+ : (abits < bbits ? a : b);
+ else // a is -ve
+ return bbits >= 0LL ? a // a is -ve, b is +ve.
+ // a and b are both -ve, so compare magnitudes: the number with
+ // the biggest magnitude is the smallest
+ : (abits > bbits ? a : b);
+}
+
+jdouble
+java::lang::Math::max(jdouble a, jdouble b)
+{
+ jlong abits = doubleToLongBits (a);
+ jlong bbits = doubleToLongBits (b);
+
+ if (isNaN (abits) || isNaN (bbits))
+ return java::lang::Double::NaN;
+
+ if (abits >= 0LL) // a is +ve
+ return bbits < 0LL ? a // a is +ve, b is -ve.
+ // a and b are both +ve, so compare magnitudes: the number with
+ // the smallest magnitude is the smallest
+ : (abits > bbits ? a : b);
+ else // a is -ve
+ return bbits >= 0LL ? b // a is -ve, b is +ve.
+ // a and b are both -ve, so compare magnitudes: the number with
+ // the biggest magnitude is the smallest
+ : (abits < bbits ? a : b);
+}
+
diff --git a/libjava/java/lang/natObject.cc b/libjava/java/lang/natObject.cc
new file mode 100644
index 00000000000..7b26769e351
--- /dev/null
+++ b/libjava/java/lang/natObject.cc
@@ -0,0 +1,241 @@
+// natObject.cc - Implementation of the Object class.
+
+/* 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 <string.h>
+
+#pragma implementation "Object.h"
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/lang/Object.h>
+#include <java-threads.h>
+#include <java/lang/CloneNotSupportedException.h>
+#include <java/lang/IllegalArgumentException.h>
+#include <java/lang/IllegalMonitorStateException.h>
+#include <java/lang/InterruptedException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/Class.h>
+#include <java/lang/Cloneable.h>
+#include <java/lang/Thread.h>
+
+#define CloneableClass _CL_Q34java4lang9Cloneable
+extern java::lang::Class CloneableClass;
+
+
+
+// This is used to represent synchronization information.
+struct _Jv_SyncInfo
+{
+#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
+ // We only need to keep track of initialization state if we can
+ // possibly finalize this object.
+ bool init;
+#endif
+ _Jv_ConditionVariable_t condition;
+ _Jv_Mutex_t mutex;
+};
+
+
+
+jclass
+java::lang::Object::getClass (void)
+{
+ _Jv_VTable **dt = (_Jv_VTable **) this;
+ return (*dt)->clas;
+}
+
+jint
+java::lang::Object::hashCode (void)
+{
+ return _Jv_HashCode (this);
+}
+
+jobject
+java::lang::Object::clone (void)
+{
+ jclass klass = getClass ();
+ jobject r;
+ jint size;
+
+ // We also clone arrays here. If we put the array code into
+ // __JArray, then we'd have to figure out a way to find the array
+ // vtbl when creating a new array class. This is easier, if uglier.
+ if (klass->isArray())
+ {
+ __JArray *array = (__JArray *) this;
+ jclass comp = getClass()->getComponentType();
+ jint eltsize;
+ if (comp->isPrimitive())
+ {
+ r = _Jv_NewPrimArray (comp, array->length);
+ eltsize = comp->size();
+ }
+ else
+ {
+ r = _Jv_NewObjectArray (array->length, comp, NULL);
+ eltsize = sizeof (jobject);
+ }
+ size = sizeof (__JArray) + array->length * eltsize;
+ }
+ else
+ {
+ if (! CloneableClass.isAssignableFrom(klass))
+ JvThrow (new CloneNotSupportedException);
+
+ size = klass->size();
+ r = JvAllocObject (klass, size);
+ }
+
+ memcpy ((void *) r, (void *) this, size);
+ return r;
+}
+
+
+//
+// Synchronization code.
+//
+
+// This global is used to make sure that only one thread sets an
+// object's `sync_info' field.
+static _Jv_Mutex_t sync_mutex;
+
+// This macro is used to see if synchronization initialization is
+// needed.
+#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
+# define INIT_NEEDED(Obj) (! (Obj)->sync_info \
+ || ! ((_Jv_SyncInfo *) ((Obj)->sync_info))->init)
+#else
+# define INIT_NEEDED(Obj) (! (Obj)->sync_info)
+#endif
+
+#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
+// If we have to run a destructor for a sync_info member, then this
+// function is registered as a finalizer for the sync_info.
+static void
+finalize_sync_info (jobject obj)
+{
+ _Jv_SyncInfo *si = (_Jv_SyncInfo *) obj;
+#if defined (_Jv_HaveCondDestroy)
+ _Jv_CondDestroy (&si->condition);
+#endif
+#if defined (_Jv_HaveMutexDestroy)
+ _Jv_MutexDestroy (&si->mutex);
+#endif
+ si->init = false;
+}
+#endif
+
+// This is called to initialize the sync_info element of an object.
+void
+java::lang::Object::sync_init (void)
+{
+ _Jv_MutexLock (&sync_mutex);
+ // Check again to see if initialization is needed now that we have
+ // the lock.
+ if (INIT_NEEDED (this))
+ {
+ // We assume there are no pointers in the sync_info
+ // representation.
+ _Jv_SyncInfo *si;
+ // We always create a new sync_info, even if there is already
+ // one available. Any given object can only be finalized once.
+ // If we get here and sync_info is not null, then it has already
+ // been finalized. So if we just reinitialize the old one,
+ // we'll never be able to (re-)destroy the mutex and/or
+ // condition variable.
+ si = (_Jv_SyncInfo *) _Jv_AllocBytes (sizeof (_Jv_SyncInfo));
+ // FIXME: what if si == NULL?
+ _Jv_MutexInit (&si->mutex);
+ _Jv_CondInit (&si->condition);
+#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
+ // Register a finalizer.
+ si->init = true;
+ _Jv_RegisterFinalizer (si, finalize_sync_info);
+#endif
+ sync_info = (jobject) si;
+ }
+ _Jv_MutexUnlock (&sync_mutex);
+}
+
+void
+java::lang::Object::notify (void)
+{
+ if (INIT_NEEDED (this))
+ sync_init ();
+ _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
+ if (_Jv_CondNotify (&si->condition, &si->mutex))
+ JvThrow (new IllegalMonitorStateException);
+}
+
+void
+java::lang::Object::notifyAll (void)
+{
+ if (INIT_NEEDED (this))
+ sync_init ();
+ _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
+ if (_Jv_CondNotifyAll (&si->condition, &si->mutex))
+ JvThrow (new IllegalMonitorStateException);
+}
+
+void
+java::lang::Object::wait (jlong timeout, jint nanos)
+{
+ if (INIT_NEEDED (this))
+ sync_init ();
+ if (timeout < 0 || nanos < 0 || nanos > 999999)
+ JvThrow (new IllegalArgumentException);
+ _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
+ if (_Jv_CondWait (&si->condition, &si->mutex, timeout, nanos))
+ JvThrow (new IllegalMonitorStateException);
+ if (Thread::interrupted())
+ JvThrow (new InterruptedException);
+}
+
+//
+// Some runtime code.
+//
+
+// This function is called at system startup to initialize the
+// `sync_mutex'.
+void
+_Jv_InitializeSyncMutex (void)
+{
+ _Jv_MutexInit (&sync_mutex);
+}
+
+jint
+_Jv_MonitorEnter (jobject obj)
+{
+ if (! obj)
+ JvThrow (new java::lang::NullPointerException);
+ if (INIT_NEEDED (obj))
+ obj->sync_init ();
+ _Jv_SyncInfo *si = (_Jv_SyncInfo *) obj->sync_info;
+ return _Jv_MutexLock (&si->mutex);
+}
+
+jint
+_Jv_MonitorExit (jobject obj)
+{
+ JvAssert (obj);
+ JvAssert (! INIT_NEEDED (obj));
+ _Jv_SyncInfo *si = (_Jv_SyncInfo *) obj->sync_info;
+ if (_Jv_MutexUnlock (&si->mutex))
+ JvThrow (new java::lang::IllegalMonitorStateException);
+ return 0;
+}
+
+void
+_Jv_FinalizeObject (jobject obj)
+{
+ java::lang::Object::hack12_6(obj);
+}
diff --git a/libjava/java/lang/natRuntime.cc b/libjava/java/lang/natRuntime.cc
new file mode 100644
index 00000000000..d89ab18bd9c
--- /dev/null
+++ b/libjava/java/lang/natRuntime.cc
@@ -0,0 +1,68 @@
+// natRuntime.cc - Implementation of native side of Runtime class.
+
+/* 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 <stdlib.h>
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/lang/Runtime.h>
+
+void
+java::lang::Runtime::exit (jint status)
+{
+ checkExit (status);
+
+ // Make status right for Unix. This is perhaps strange.
+ if (status < 0 || status > 255)
+ status = 255;
+
+ if (finalize_on_exit)
+ _Jv_RunAllFinalizers ();
+
+ ::exit (status);
+}
+
+jlong
+java::lang::Runtime::freeMemory (void)
+{
+ return _Jv_GCFreeMemory ();
+}
+
+void
+java::lang::Runtime::gc (void)
+{
+ _Jv_RunGC ();
+}
+
+void
+java::lang::Runtime::runFinalization (void)
+{
+ _Jv_RunFinalizers ();
+}
+
+jlong
+java::lang::Runtime::totalMemory (void)
+{
+ return _Jv_GCTotalMemory ();
+}
+
+void
+java::lang::Runtime::traceInstructions (jboolean)
+{
+ // Do nothing.
+}
+
+void
+java::lang::Runtime::traceMethodCalls (jboolean)
+{
+ // Do nothing.
+}
diff --git a/libjava/java/lang/natString.cc b/libjava/java/lang/natString.cc
new file mode 100644
index 00000000000..5cb7b2c72b4
--- /dev/null
+++ b/libjava/java/lang/natString.cc
@@ -0,0 +1,800 @@
+// natString.cc - Implementation of java.lang.String native methods.
+
+/* 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 <string.h>
+#include <stdlib.h>
+
+#include <cni.h>
+#include <java/lang/Character.h>
+#include <java/lang/String.h>
+#include <java/lang/IndexOutOfBoundsException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/StringIndexOutOfBoundsException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/io/ByteArrayOutputStream.h>
+#include <java/io/OutputStreamWriter.h>
+#include <java/io/ByteArrayInputStream.h>
+#include <java/io/InputStreamReader.h>
+#include <jvm.h>
+
+static jstring* strhash = NULL;
+static int strhash_count = 0; /* Number of slots used in strhash. */
+static int strhash_size = 0; /* Number of slots available in strhash.
+ * Assumed be power of 2! */
+
+#define DELETED_STRING ((jstring)(~0))
+#define SET_STRING_IS_INTERNED(STR) /* nothing */
+
+/* Find a slot where the string with elements DATA, length LEN,
+ and hash HASH should go in the strhash table of interned strings. */
+jstring*
+_Jv_StringFindSlot (jchar* data, jint len, jint hash)
+{
+ JvSynchronize sync (&StringClass);
+
+ int start_index = hash & (strhash_size - 1);
+ int deleted_index = -1;
+
+ register int index = start_index;
+ /* step must be non-zero, and relatively prime with strhash_size. */
+ int step = 8 * hash + 7;
+ for (;;)
+ {
+ register jstring* ptr = &strhash[index];
+ if (*ptr == NULL)
+ {
+ if (deleted_index >= 0)
+ return (&strhash[deleted_index]);
+ else
+ return ptr;
+ }
+ else if (*ptr == DELETED_STRING)
+ deleted_index = index;
+ else if ((*ptr)->length() == len
+ && memcmp(JvGetStringChars(*ptr), data, 2*len) == 0)
+ return (ptr);
+ index = (index + step) & (strhash_size - 1);
+ JvAssert (index != start_index);
+ }
+}
+
+/* Calculate a hash code for the string starting at PTR at given LENGTH.
+ This uses the same formula as specified for java.lang.String.hash. */
+
+static jint
+hashChars (jchar* ptr, jint length)
+{
+ register jchar* limit = ptr + length;
+ jint hash = 0;
+ // Updated specification from
+ // http://www.javasoft.com/docs/books/jls/clarify.html.
+ while (ptr < limit)
+ hash = (31 * hash) + *ptr++;
+ return hash;
+}
+
+jint
+java::lang::String::hashCode()
+{
+ return hashChars(JvGetStringChars(this), length());
+}
+
+jstring*
+_Jv_StringGetSlot (jstring str)
+{
+ jchar* data = JvGetStringChars(str);
+ int length = str->length();
+ return _Jv_StringFindSlot(data, length, hashChars (data, length));
+}
+
+void
+java::lang::String::rehash()
+{
+ JvSynchronize sync (&StringClass);
+
+ if (strhash == NULL)
+ {
+ strhash_size = 1024;
+ strhash = (jstring *) _Jv_AllocBytes (strhash_size * sizeof (jstring));
+ memset (strhash, 0, strhash_size * sizeof (jstring));
+ }
+ else
+ {
+ register int i = strhash_size;
+ register jstring* ptr = strhash + i;
+ strhash_size *= 2;
+ strhash = (jstring *) _Jv_AllocBytes (strhash_size * sizeof (jstring));
+ memset (strhash, 0, strhash_size * sizeof (jstring));
+
+ while (--i >= 0)
+ {
+ --ptr;
+ if (*ptr == NULL || *ptr == DELETED_STRING)
+ continue;
+
+ /* This is faster equivalent of
+ * *__JvGetInternSlot(*ptr) = *ptr; */
+ jint hash = (*ptr)->hashCode();
+ jint index = hash & (strhash_size - 1);
+ jint step = 8 * hash + 7;
+ for (;;)
+ {
+ if (strhash[index] == NULL)
+ {
+ strhash[index] = *ptr;
+ break;
+ }
+ index = (index + step) & (strhash_size - 1);
+ }
+ }
+ }
+}
+
+jstring
+java::lang::String::intern()
+{
+ JvSynchronize sync (&StringClass);
+ if (4 * strhash_count >= 3 * strhash_size)
+ rehash();
+ jstring* ptr = _Jv_StringGetSlot(this);
+ if (*ptr != NULL && *ptr != DELETED_STRING)
+ return *ptr;
+ SET_STRING_IS_INTERNED(this);
+ strhash_count++;
+ *ptr = this;
+ return this;
+}
+
+/* Called by String fake finalizer. */
+void
+java::lang::String::unintern()
+{
+ JvSynchronize sync (&StringClass);
+ jstring* ptr = _Jv_StringGetSlot(this);
+ if (*ptr == NULL || *ptr == DELETED_STRING)
+ return;
+ *ptr = DELETED_STRING;
+ strhash_count--;
+}
+
+jstring
+_Jv_NewStringUTF (const char *bytes)
+{
+ int size = strlen (bytes);
+ unsigned char *p = (unsigned char *) bytes;
+
+ int length = _Jv_strLengthUtf8 ((char *) p, size);
+ if (length < 0)
+ return NULL;
+
+ jstring jstr = JvAllocString (length);
+ jchar *chrs = JvGetStringChars (jstr);
+
+ p = (unsigned char *) bytes;
+ unsigned char *limit = p + size;
+ while (p < limit)
+ *chrs++ = UTF8_GET (p, limit);
+
+ return jstr;
+}
+
+jstring
+_Jv_NewStringUtf8Const (Utf8Const* str)
+{
+ jchar *chrs;
+ jchar buffer[100];
+ jstring jstr;
+ register unsigned char* data = (unsigned char*) str->data;
+ register unsigned char* limit = data + str->length;
+ int length = _Jv_strLengthUtf8(str->data, str->length);
+
+ if (length <= (int) (sizeof(buffer) / sizeof(jchar)))
+ {
+ jstr = NULL;
+ chrs = buffer;
+ }
+ else
+ {
+ jstr = JvAllocString(length);
+ chrs = JvGetStringChars(jstr);
+ }
+
+ while (data < limit)
+ *chrs++ = UTF8_GET(data, limit);
+ chrs -= length;
+
+ JvSynchronize sync (&StringClass);
+ if (4 * strhash_count >= 3 * strhash_size)
+ java::lang::String::rehash();
+ int hash = str->hash;
+ jstring* ptr = _Jv_StringFindSlot (chrs, length, hash);
+ if (*ptr != NULL && *ptr != DELETED_STRING)
+ return *ptr;
+ strhash_count++;
+ if (jstr == NULL)
+ {
+ jstr = JvAllocString(length);
+ chrs = JvGetStringChars(jstr);
+ memcpy (chrs, buffer, sizeof(jchar)*length);
+ }
+ *ptr = jstr;
+ SET_STRING_IS_INTERNED(jstr);
+ return jstr;
+}
+
+jsize
+_Jv_GetStringUTFLength (jstring string)
+{
+ register jsize len = 0;
+ register jchar *ptr = JvGetStringChars (string);
+ register jsize i = string->length();
+ while (--i >= 0)
+ {
+ register jchar ch = *ptr++;
+ if (ch > 0 && ch <= 0x7F)
+ len += 1;
+ else if (ch <= 0x7FF)
+ len += 2;
+ else
+ len += 3;
+ }
+ return len;
+}
+
+// Not sure this quite matches GetStringUTFRegion.
+// null-termination of result? len? throw exception?
+jsize
+_Jv_GetStringUTFRegion (jstring str, jsize start, jsize len, char *buf)
+{
+ register jchar *sptr = JvGetStringChars (str) + start;
+ register jsize i = len;
+ register char *dptr = buf;
+ while (--i >= 0)
+ {
+ jchar ch = *sptr++;
+ if (ch > 0 && ch <= 0x7F)
+ *dptr++ = (char) ch;
+ else if (ch <= 0x7FF)
+ {
+ *dptr++ = (char) (0xC0 + ((ch >> 6) & 0x1F));
+ *dptr++ = (char) (0x80 + (ch & 0x3F));
+ }
+ else
+ {
+ *dptr++ = (char) (0xE0 + ((ch >> 12) & 0xF));
+ *dptr++ = (char) (0x80 + ((ch >> 6) & 0x3F));
+ *dptr++ = (char) (0x80 + (ch & 0x3F));
+ }
+ }
+ return dptr - buf;
+}
+
+jstring
+_Jv_AllocString(jsize len)
+{
+ jsize sz = sizeof(java::lang::String) + len * sizeof(jchar);
+
+ jstring obj = (jstring) JvAllocObject(&StringClass, sz);
+
+ obj->data = obj;
+ obj->boffset = sizeof(java::lang::String);
+ obj->count = len;
+ return obj;
+}
+
+jstring
+_Jv_NewString(const jchar *chars, jsize len)
+{
+ jstring str = _Jv_AllocString(len);
+ jchar* data = JvGetStringChars (str);
+ while (--len >= 0)
+ *data++ = *chars++;
+ return str;
+}
+
+jstring
+_Jv_NewStringLatin1(const char *bytes, jsize len)
+{
+ jstring str = JvAllocString(len);
+ jchar* data = JvGetStringChars (str);
+ while (--len >= 0)
+ *data++ = *(unsigned char*)bytes++;
+ return str;
+}
+
+void
+java::lang::String::init ()
+{
+ count = 0;
+ boffset = sizeof(java::lang::String);
+ data = this;
+}
+
+void
+java::lang::String::init(jcharArray chars, jint offset, jint count,
+ jboolean dont_copy)
+{
+ if (! chars)
+ JvThrow (new NullPointerException);
+ jsize data_size = JvGetArrayLength (chars);
+ if (offset < 0 || count < 0 || offset + count > data_size)
+ JvThrow (new StringIndexOutOfBoundsException());
+ jcharArray array;
+ jchar *pdst;
+ if (! dont_copy)
+ {
+ array = JvNewCharArray(count);
+ pdst = elements (array);
+ memcpy (pdst, elements (chars) + offset, count * sizeof (jchar));
+ }
+ else
+ {
+ JvAssert (offset == 0);
+ array = chars;
+ pdst = elements (array);
+ }
+
+ data = array;
+ boffset = (char *) pdst - (char *) array;
+ this->count = count;
+}
+
+void
+java::lang::String::init(jbyteArray ascii, jint hibyte, jint offset,
+ jint count)
+{
+ if (! ascii)
+ JvThrow (new NullPointerException);
+ jsize data_size = JvGetArrayLength (ascii);
+ if (offset < 0 || count < 0 || offset + count < 0
+ || offset + count > data_size)
+ JvThrow (new java::lang::StringIndexOutOfBoundsException());
+ jcharArray array = JvNewCharArray(count);
+ jbyte *psrc = elements (ascii) + offset;
+ jchar *pdst = elements (array);
+ data = array;
+ boffset = (char *) pdst - (char *) array;
+ this->count = count;
+ hibyte = (hibyte & 0xff) << 8;
+ while (-- count >= 0)
+ {
+ *pdst++ = hibyte | (*psrc++ & 0xff);
+ }
+}
+
+void
+java::lang::String::init (jbyteArray bytes, jint offset, jint count,
+ jstring encoding)
+{
+ if (! bytes)
+ JvThrow (new NullPointerException);
+ jsize data_size = JvGetArrayLength (bytes);
+ if (offset < 0 || count < 0 || offset + count < 0
+ || offset + count > data_size)
+ JvThrow (new StringIndexOutOfBoundsException);
+
+ java::io::ByteArrayInputStream *b
+ = new java::io::ByteArrayInputStream (bytes, offset, count);
+ java::io::InputStreamReader *ir
+ = new java::io::InputStreamReader (b, encoding);
+ // FIXME: we allocate too much here in some cases.
+ jcharArray array = JvNewCharArray (count);
+ data = array;
+ boffset = (char *) elements (array) - (char *) array;
+ // FIXME: this can throw IOException.
+ this->count = ir->read(array, 0, count);
+}
+
+jboolean
+java::lang::String::equals(jobject anObject)
+{
+ if (anObject == NULL)
+ return false;
+ if (anObject == this)
+ return true;
+ if (anObject->getClass() != &StringClass)
+ return false;
+ jstring other = (jstring) anObject;
+ if (count != other->count)
+ return false;
+ /* if both are interned, return false. */
+ register jint i = count;
+ register jchar *xptr = JvGetStringChars (this);
+ register jchar *yptr = JvGetStringChars (other);
+ while (--i >= 0)
+ {
+ if (*xptr++ != *yptr++)
+ return false;
+ }
+ return true;
+}
+
+jchar
+java::lang::String::charAt(jint i)
+{
+ if (i < 0 || i >= count)
+ JvThrow (new java::lang::StringIndexOutOfBoundsException());
+ return JvGetStringChars(this)[i];
+}
+
+void
+java::lang::String::getChars(jint srcBegin, jint srcEnd,
+ jcharArray dst, jint dstBegin)
+{
+ jint dst_length = JvGetArrayLength (dst);
+ if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count
+ || dstBegin < 0 || dstBegin + (srcEnd-srcBegin) > dst_length)
+ JvThrow (new java::lang::ArrayIndexOutOfBoundsException());
+ register jchar *dPtr = elements (dst) + dstBegin;
+ register jchar *sPtr = JvGetStringChars (this) + srcBegin;
+ register jint i = srcEnd-srcBegin;
+ while (--i >= 0)
+ *dPtr++ = *sPtr++;
+}
+
+jbyteArray
+java::lang::String::getBytes (jstring enc)
+{
+ java::io::ByteArrayOutputStream *os
+ = new java::io::ByteArrayOutputStream(length ());
+ java::io::OutputStreamWriter *ow
+ = new java::io::OutputStreamWriter(os, enc);
+
+ ow->write(this, 0, length ());
+ ow->flush();
+
+ return os->toByteArray();
+}
+
+void
+java::lang::String::getBytes(jint srcBegin, jint srcEnd,
+ jbyteArray dst, jint dstBegin)
+{
+ jint dst_length = JvGetArrayLength (dst);
+ if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count
+ || dstBegin < 0 || dstBegin + (srcEnd-srcBegin) > dst_length)
+ JvThrow (new java::lang::ArrayIndexOutOfBoundsException());
+ register jbyte *dPtr = elements (dst) + dstBegin;
+ register jchar *sPtr = JvGetStringChars (this) + srcBegin;
+ register jint i = srcEnd-srcBegin;
+ while (--i >= 0)
+ *dPtr++ = (jbyte) *sPtr++;
+}
+
+jcharArray
+java::lang::String::toCharArray()
+{
+ jcharArray array = JvNewCharArray(count);
+ register jchar *dPtr = elements (array);
+ register jchar *sPtr = JvGetStringChars (this);
+ register jint i = count;
+ while (--i >= 0)
+ *dPtr++ = *sPtr++;
+ return array;
+}
+
+jboolean
+java::lang::String::equalsIgnoreCase (jstring anotherString)
+{
+ if (count != anotherString->count)
+ return false;
+ register jchar *tptr = JvGetStringChars (this);
+ register jchar *optr = JvGetStringChars (anotherString);
+ register jint i = count;
+ while (--i >= 0)
+ {
+ jchar tch = *tptr++;
+ jchar och = *optr++;
+ if (tch != och
+ && (java::lang::Character::toLowerCase (tch)
+ != java::lang::Character::toLowerCase (och))
+ && (java::lang::Character::toUpperCase (tch)
+ != java::lang::Character::toUpperCase (och)))
+ return false;
+ }
+ return true;
+}
+
+jboolean
+java::lang::String::regionMatches (jint toffset,
+ jstring other, jint ooffset, jint len)
+{
+ if (toffset < 0 || ooffset < 0
+ || toffset + len > count
+ || ooffset + len > other->count)
+ return false;
+ register jchar *tptr = JvGetStringChars (this) + toffset;
+ register jchar *optr = JvGetStringChars (other) + ooffset;
+ register jint i = len;
+ while (--i >= 0)
+ {
+ if (*tptr++ != *optr++)
+ return false;
+ }
+ return true;
+}
+
+jint
+java::lang::String::compareTo (jstring anotherString)
+{
+ register jchar *tptr = JvGetStringChars (this);
+ register jchar *optr = JvGetStringChars (anotherString);
+ jint tlen = this->count;
+ jint olen = anotherString->count;
+ register jint i = tlen > olen ? olen : tlen;
+ while (--i >= 0)
+ {
+ jchar tch = *tptr++;
+ jchar och = *optr++;
+ if (tch != och)
+ return (jint) tch - (jint) och;
+ }
+ return tlen - olen;
+}
+
+jboolean
+java::lang::String::regionMatches (jboolean ignoreCase, jint toffset,
+ jstring other, jint ooffset, jint len)
+{
+ if (toffset < 0 || ooffset < 0
+ || toffset + len > count
+ || ooffset + len > other->count)
+ return false;
+ register jchar *tptr = JvGetStringChars (this) + toffset;
+ register jchar *optr = JvGetStringChars (other) + ooffset;
+ register jint i = len;
+ while (--i >= 0)
+ {
+ jchar tch = *tptr++;
+ jchar och = *optr++;
+ if (tch != och)
+ return false;
+ if (ignoreCase
+ && (java::lang::Character::toLowerCase (tch)
+ != java::lang::Character::toLowerCase (och))
+ && (java::lang::Character::toUpperCase (tch)
+ != java::lang::Character::toUpperCase (och)))
+ return false;
+ }
+ return true;
+}
+
+jboolean
+java::lang::String::startsWith (jstring prefix, jint toffset)
+{
+ register jint i = prefix->count;
+ if (toffset < 0 || toffset + i > count)
+ return false;
+ register jchar *xptr = JvGetStringChars (this) + toffset;
+ register jchar *yptr = JvGetStringChars (prefix);
+ while (--i >= 0)
+ {
+ if (*xptr++ != *yptr++)
+ return false;
+ }
+ return true;
+}
+
+jint
+java::lang::String::indexOf (jint ch, jint fromIndex)
+{
+ if (fromIndex < 0)
+ fromIndex = 0;
+ register jchar *ptr = JvGetStringChars(this);
+ for (;; ++fromIndex)
+ {
+ if (fromIndex >= count)
+ return -1;
+ if (ptr[fromIndex] == ch)
+ return fromIndex;
+ }
+}
+
+jint
+java::lang::String::indexOf (jstring s, jint fromIndex)
+{
+ const jchar *const xchars = JvGetStringChars(s);
+ const jchar *const ychars = JvGetStringChars(this) + fromIndex;
+
+ const int xlength = s->length ();
+ const int ylength = length () - fromIndex;
+
+ int i = 0;
+ int j = 0;
+
+ while (i < ylength && j < xlength)
+ {
+ if (xchars[j] != ychars[i])
+ {
+ i = i - j + 1;
+ j = 0;
+ }
+ else
+ i++, j++;
+ }
+
+ if (j >= xlength)
+ return fromIndex + i - xlength;
+ else
+ return -1;
+}
+
+jint
+java::lang::String::lastIndexOf (jint ch, jint fromIndex)
+{
+ if (fromIndex >= count)
+ fromIndex = count - 1;
+ register jchar *ptr = JvGetStringChars(this);
+ for (;; --fromIndex)
+ {
+ if (fromIndex < 0)
+ return -1;
+ if (ptr[fromIndex] == ch)
+ return fromIndex;
+ }
+}
+
+jstring
+java::lang::String::substring (jint beginIndex, jint endIndex)
+{
+ if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)
+ JvThrow (new StringIndexOutOfBoundsException());
+ jint newCount = endIndex - beginIndex;
+ if (newCount <= 8) // Optimization, mainly for GC.
+ return JvNewString(JvGetStringChars(this) + beginIndex, newCount);
+ jstring s = new String();
+ s->data = data;
+ s->count = newCount;
+ s->boffset = boffset + sizeof(jchar) * beginIndex;
+ return s;
+}
+
+jstring
+java::lang::String::concat(jstring str)
+{
+ jint str_count = str->count;
+ if (str_count == 0)
+ return this;
+ jstring result = JvAllocString(count + str_count);
+ register jchar *dstPtr = JvGetStringChars(result);
+ register jchar *srcPtr = JvGetStringChars(this);
+ register jint i = count;
+ while (--i >= 0)
+ *dstPtr++ = *srcPtr++;
+ srcPtr = JvGetStringChars(str);
+ i = str->count;
+ while (--i >= 0)
+ *dstPtr++ = *srcPtr++;
+ return result;
+}
+
+jstring
+java::lang::String::replace (jchar oldChar, jchar newChar)
+{
+ jint i;
+ jchar* chrs = JvGetStringChars (this);
+ for (i = 0; ; i++)
+ {
+ if (i == count)
+ return this;
+ if (chrs[i] == oldChar)
+ break;
+ }
+ jstring result = JvAllocString (count);
+ jchar *dPtr = JvGetStringChars (result);
+ for (int j = 0; j < i; j++)
+ *dPtr++ = chrs[j];
+ for (; i < count; i++)
+ {
+ jchar ch = chrs[i];
+ if (ch == oldChar)
+ ch = newChar;
+ *dPtr++ = ch;
+ }
+ return result;
+}
+
+jstring
+java::lang::String::toLowerCase ()
+{
+ jint i;
+ jchar* chrs = JvGetStringChars(this);
+ jchar ch;
+ for (i = 0; ; i++)
+ {
+ if (i == count)
+ return this;
+ jchar origChar = chrs[i];
+ ch = java::lang::Character::toLowerCase(origChar);
+ if (ch != origChar)
+ break;
+ }
+ jstring result = JvAllocString(count);
+ jchar *dPtr = JvGetStringChars (result);
+ for (int j = 0; j < i; j++)
+ *dPtr++ = chrs[j];
+ *dPtr++ = ch; i++;
+ for (; i < count; i++)
+ {
+ *dPtr++ = java::lang::Character::toLowerCase(chrs[i]);
+ }
+ return result;
+}
+
+jstring
+java::lang::String::toUpperCase ()
+{
+ jint i;
+ jchar* chrs = JvGetStringChars(this);
+ jchar ch;
+ for (i = 0; ; i++)
+ {
+ if (i == count)
+ return this;
+ jchar origChar = chrs[i];
+ ch = java::lang::Character::toUpperCase(origChar);
+ if (ch != origChar)
+ break;
+ }
+ jstring result = JvAllocString(count);
+ jchar *dPtr = JvGetStringChars (result);
+ for (int j = 0; j < i; j++)
+ *dPtr++ = chrs[j];
+ *dPtr++ = ch; i++;
+ for (; i < count; i++)
+ {
+ *dPtr++ = java::lang::Character::toUpperCase(chrs[i]);
+ }
+ return result;
+}
+
+jstring
+java::lang::String::trim ()
+{
+ jchar* chrs = JvGetStringChars(this);
+ if (count == 0 || (chrs[0] > ' ' && chrs[count-1] > ' '))
+ return this;
+ jint preTrim = 0;
+ for (;; preTrim++)
+ {
+ if (preTrim == count)
+ return new String();
+ if (chrs[preTrim] > ' ')
+ break;
+ }
+ jint endTrim = count;
+ while (chrs[endTrim-1] <= ' ')
+ endTrim--;
+ return substring(preTrim, endTrim);
+}
+
+jstring
+java::lang::String::valueOf(jcharArray data, jint offset, jint count)
+{
+ jint data_length = JvGetArrayLength (data);
+ if (offset < 0 || count < 0 || offset+count > data_length)
+ JvThrow (new java::lang::IndexOutOfBoundsException());
+ register jstring result = JvAllocString(count);
+ register jchar *sPtr = elements (data) + offset;
+ register jchar *dPtr = JvGetStringChars(result);
+ while (--count >= 0)
+ *dPtr++ = *sPtr++;
+ return result;
+}
+
+jstring
+java::lang::String::valueOf(jchar c)
+{
+ register jstring result = JvAllocString(1);
+ JvGetStringChars (result)[0] = c;
+ return result;
+}
diff --git a/libjava/java/lang/natSystem.cc b/libjava/java/lang/natSystem.cc
new file mode 100644
index 00000000000..5f613d53ead
--- /dev/null
+++ b/libjava/java/lang/natSystem.cc
@@ -0,0 +1,259 @@
+// natSystem.cc - Native code implementing System class.
+
+/* 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>
+
+#ifdef HAVE_GETPWUID_R
+#define _POSIX_PTHREAD_SEMANTICS
+#ifndef _REENTRANT
+#define _REENTRANT
+#endif
+#endif
+
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <errno.h>
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/lang/System.h>
+#include <java/lang/Class.h>
+#include <java/lang/ArrayStoreException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/util/Properties.h>
+#include <java/io/PrintStream.h>
+#include <java/io/InputStream.h>
+
+
+
+#if defined (ECOS)
+extern "C" unsigned long long _clock (void);
+#endif
+
+void
+java::lang::System::setErr (java::io::PrintStream *newErr)
+{
+ checkSetIO ();
+ // This violates `final' semantics. Oh well.
+ err = newErr;
+}
+
+void
+java::lang::System::setIn (java::io::InputStream *newIn)
+{
+ checkSetIO ();
+ // This violates `final' semantics. Oh well.
+ in = newIn;
+}
+
+void
+java::lang::System::setOut (java::io::PrintStream *newOut)
+{
+ checkSetIO ();
+ // This violates `final' semantics. Oh well.
+ out = newOut;
+}
+
+void
+java::lang::System::arraycopy (jobject src, jint src_offset,
+ jobject dst, jint dst_offset,
+ jint count)
+{
+ if (! src || ! dst)
+ _Jv_Throw (new NullPointerException);
+
+ jclass src_c = src->getClass();
+ jclass dst_c = dst->getClass();
+ jclass src_comp = src_c->getComponentType();
+ jclass dst_comp = dst_c->getComponentType();
+
+ if (! src_c->isArray() || ! dst_c->isArray()
+ || src_comp->isPrimitive() != dst_comp->isPrimitive()
+ || (src_comp->isPrimitive() && src_comp != dst_comp))
+ _Jv_Throw (new ArrayStoreException);
+
+ __JArray *src_a = (__JArray *) src;
+ __JArray *dst_a = (__JArray *) dst;
+ if (src_offset < 0 || dst_offset < 0 || count < 0
+ || src_offset + count > src_a->length
+ || dst_offset + count > dst_a->length)
+ _Jv_Throw (new ArrayIndexOutOfBoundsException);
+
+ // Do-nothing cases.
+ if ((src == dst && src_offset == dst_offset)
+ || ! count)
+ return;
+
+ // If both are primitive, we can optimize trivially. If DST
+ // components are always assignable from SRC components, then we
+ // will never need to raise an error, and thus can do the
+ // optimization. If source and destinations are the same, then we
+ // know that the assignability premise always holds.
+ const bool prim = src_comp->isPrimitive();
+ if (prim || dst_comp->isAssignableFrom(src_comp) || src == dst)
+ {
+ const size_t size = prim ? src_comp->size()
+ : sizeof elements((jobjectArray)src)[0];
+
+ // We need a particular type to get the pointer to the data. So
+ // we choose bytes.
+ char *src_elts = (((char *) elements ((jbyteArray) src))
+ + src_offset * size);
+ char *dst_elts = (((char *) elements ((jbyteArray) dst))
+ + dst_offset * size);
+ // We don't bother trying memcpy. It can't be worth the cost of
+ // the check.
+ memmove ((void *) dst_elts, (void *) src_elts, count * size);
+ }
+ else
+ {
+ jobject *src_elts = elements ((jobjectArray) src_a) + src_offset;
+ jobject *dst_elts = elements ((jobjectArray) dst_a) + dst_offset;
+
+ for (int i = 0; i < count; ++i)
+ {
+ if (*src_elts
+ && ! dst_comp->isAssignableFrom((*src_elts)->getClass()))
+ _Jv_Throw (new ArrayStoreException);
+ *dst_elts++ = *src_elts++;
+ }
+ }
+}
+
+jlong
+java::lang::System::currentTimeMillis (void)
+{
+ jlong r;
+
+#if defined (HAVE_GETTIMEOFDAY)
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ r = (jlong) tv.tv_sec * 1000 + tv.tv_usec / 1000;
+#elif defined (HAVE_TIME)
+ r = time (NULL) * 1000;
+#elif defined (HAVE_FTIME)
+ struct timeb t;
+ ftime (&t);
+ r = t.time * 1000 + t.millitm;
+#elif defined (ECOS)
+ r = _clock();
+#else
+ // In the absence of any function, time remains forever fixed.
+ r = 23;
+#endif
+
+ return r;
+}
+
+jint
+java::lang::System::identityHashCode (jobject obj)
+{
+ return _Jv_HashCode (obj);
+}
+
+void
+java::lang::System::init_properties (void)
+{
+ if (prop_init)
+ return;
+ prop_init = true;
+
+ properties = new java::util::Properties ();
+ // A convenience define.
+#define SET(Prop,Val) \
+ properties->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
+ SET ("java.version", "FIXME");
+ SET ("java.vendor", "Cygnus Solutions");
+ SET ("java.vendor.url", "http://www.cygnus.com/");
+ // SET ("java.home", "FIXME");
+ // SET ("java.class.version", "FIXME");
+ // SET ("java.class.path", "FIXME");
+ SET ("os.name", "FIXME");
+ SET ("os.arch", "FIXME");
+ SET ("os.version", "FIXME");
+ SET ("file.encoding", "8859_1"); // FIXME
+#ifdef WIN32
+ SET ("file.separator", "\\");
+ SET ("path.separator", ";");
+ SET ("line.separator", "\r\n");
+#else
+ // Unix.
+ SET ("file.separator", "/");
+ SET ("path.separator", ":");
+ SET ("line.separator", "\n");
+#endif
+
+#ifdef HAVE_PWD_H
+ uid_t user_id = getuid ();
+ struct passwd *pwd_entry;
+
+#ifdef HAVE_GETPWUID_R
+ struct passwd pwd_r;
+ size_t len_r = 200;
+ char *buf_r = (char *) _Jv_AllocBytes (len_r);
+
+ while (buf_r != NULL)
+ {
+ int r = getpwuid_r (user_id, &pwd_r, buf_r, len_r, &pwd_entry);
+ if (r == 0)
+ break;
+ else if (r != ERANGE)
+ {
+ pwd_entry = NULL;
+ break;
+ }
+ len_r *= 2;
+ buf_r = (char *) _Jv_AllocBytes (len_r);
+ }
+#else
+ struct passwd *pwd_entry = getpwuid (user_id);
+#endif /* HAVE_GETPWUID_R */
+
+ if (pwd_entry != NULL)
+ {
+ SET ("user.name", pwd_entry->pw_name);
+ SET ("user.home", pwd_entry->pw_dir);
+ }
+#endif /* HAVE_PWD_H */
+
+#ifdef HAVE_UNISTD_H
+ /* Use getcwd to set "user.dir". */
+ int buflen = 250;
+ char *buffer = (char *) malloc (buflen);
+ while (buffer != NULL)
+ {
+ if (getcwd (buffer, buflen) != NULL)
+ {
+ SET ("user.dir", buffer);
+ break;
+ }
+ if (errno != ERANGE)
+ break;
+ buflen = 2 * buflen;
+ buffer = (char *) realloc (buffer, buflen);
+ }
+ if (buffer != NULL)
+ free (buffer);
+#endif
+}
diff --git a/libjava/java/lang/natThread.cc b/libjava/java/lang/natThread.cc
new file mode 100644
index 00000000000..117191133a8
--- /dev/null
+++ b/libjava/java/lang/natThread.cc
@@ -0,0 +1,295 @@
+// natThread.cc - Native part of Thread class.
+
+/* 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 <stdlib.h>
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/lang/Thread.h>
+#include <java/lang/ThreadGroup.h>
+#include <java/lang/IllegalArgumentException.h>
+#include <java/lang/IllegalThreadStateException.h>
+#include <java/lang/InterruptedException.h>
+#include <java/lang/NullPointerException.h>
+
+
+
+// This structure is used to represent all the data the native side
+// needs. An object of this type is assigned to the `data' member of
+// the Thread class.
+struct natThread
+{
+ // These are used to interrupt sleep and join calls. We can share a
+ // condition variable here since this thread can either be sleeping
+ // or waiting for a thread exit, but not both.
+ _Jv_Mutex_t interrupt_mutex;
+ _Jv_ConditionVariable_t interrupt_cond;
+
+ // This is private data for the thread system layer.
+ _Jv_Thread_t *thread;
+
+ // All threads waiting to join this thread are linked together and
+ // waiting on their respective `interrupt' condition variables.
+ // When this thread exits, it notifies each such thread by
+ // signalling the condition. In this case the `interrupt_flag' is
+ // not set; this is how the waiting thread knows whether the join
+ // has failed or whether it should throw an exception.
+ struct natThread *joiner;
+
+ // Chain for waiters.
+ struct natThread *next;
+};
+
+// This is called from the constructor to initialize the native side
+// of the Thread.
+void
+java::lang::Thread::initialize_native (void)
+{
+ // FIXME: this must interact with the GC in some logical way. At
+ // the very least we must register a finalizer to clean up. This
+ // isn't easy to do. If the Thread object resurrects itself in its
+ // own finalizer then we will need to reinitialize this structure at
+ // any "interesting" point.
+ natThread *nt = (natThread *) _Jv_AllocBytes (sizeof (natThread));
+ data = (jobject) nt;
+ _Jv_MutexInit (&nt->interrupt_mutex);
+ _Jv_CondInit (&nt->interrupt_cond);
+ _Jv_ThreadInitData (&nt->thread, this);
+ nt->joiner = 0;
+ nt->next = 0;
+}
+
+jint
+java::lang::Thread::countStackFrames (void)
+{
+ // NOTE: This is deprecated in JDK 1.2.
+ JvFail ("java::lang::Thread::countStackFrames unimplemented");
+ return 0;
+}
+
+java::lang::Thread *
+java::lang::Thread::currentThread (void)
+{
+ return _Jv_ThreadCurrent ();
+}
+
+// FIXME: this is apparently the only way a thread can be removed from
+// a ThreadGroup. That seems wrong.
+void
+java::lang::Thread::destroy (void)
+{
+ // NOTE: This is marked as unimplemented in the JDK 1.2
+ // documentation.
+ JvFail ("java::lang::Thread::destroy unimplemented");
+}
+
+void
+java::lang::Thread::dumpStack (void)
+{
+ // We don't implement this because it is very hard. Once we have a
+ // VM, this could potentially ask the VM to do the dump in cases
+ // where it makes sense.
+ JvFail ("java::lang::Thread::dumpStack unimplemented");
+}
+
+void
+java::lang::Thread::interrupt (void)
+{
+ interrupt_flag = true;
+
+ // Wake up this thread, whether it is sleeping or waiting for
+ // another thread to exit.
+ natThread *nt = (natThread *) data;
+ _Jv_MutexLock (&nt->interrupt_mutex);
+ _Jv_CondNotify (&nt->interrupt_cond, &nt->interrupt_mutex);
+ _Jv_MutexUnlock (&nt->interrupt_mutex);
+
+ _Jv_ThreadInterrupt (nt->thread);
+}
+
+void
+java::lang::Thread::join (jlong millis, jint nanos)
+{
+ // FIXME: what if we are trying to join ourselves with no timeout?
+
+ if (millis < 0 || nanos < 0 || nanos > 999999)
+ _Jv_Throw (new IllegalArgumentException);
+
+ Thread *current = currentThread ();
+ if (current->isInterrupted ())
+ _Jv_Throw (new InterruptedException);
+
+ // Update the list of all threads waiting for this thread to exit.
+ // We grab a mutex when doing this in order to ensure that the
+ // required state changes are atomic.
+ _Jv_MonitorEnter (this);
+ if (! isAlive ())
+ {
+ _Jv_MonitorExit (this);
+ return;
+ }
+
+ // Here `CURR_NT' is the native structure for the currently
+ // executing thread, while `NT' is the native structure for the
+ // thread we are trying to join.
+ natThread *curr_nt = (natThread *) current->data;
+ natThread *nt = (natThread *) data;
+
+ JvAssert (curr_nt->next == NULL);
+ // Put thread CURR_NT onto NT's list. When NT exits, it will
+ // traverse its list and notify all joiners.
+ curr_nt->next = nt->joiner;
+ nt->joiner = curr_nt;
+ _Jv_MonitorExit (this);
+
+
+ // Now wait for: (1) an interrupt, (2) the thread to exit, or (3)
+ // the timeout to occur.
+ _Jv_MutexLock (&curr_nt->interrupt_mutex);
+ _Jv_CondWait (&curr_nt->interrupt_cond,
+ &curr_nt->interrupt_mutex,
+ millis, nanos);
+ _Jv_MutexUnlock (&curr_nt->interrupt_mutex);
+
+ // Now the join has completed, one way or another. Update the
+ // joiners list to account for this.
+ _Jv_MonitorEnter (this);
+ JvAssert (nt->joiner != NULL);
+ natThread *prev = 0;
+ natThread *t;
+ for (t = nt->joiner; t != NULL; t = t->next)
+ {
+ if (t == curr_nt)
+ {
+ if (prev)
+ prev->next = t->next;
+ else
+ nt->joiner = t->next;
+ t->next = 0;
+ break;
+ }
+ }
+ JvAssert (t != NULL);
+ _Jv_MonitorExit (this);
+
+ if (current->isInterrupted ())
+ _Jv_Throw (new InterruptedException);
+}
+
+void
+java::lang::Thread::resume (void)
+{
+ checkAccess ();
+ JvFail ("java::lang::Thread::resume unimplemented");
+}
+
+void
+java::lang::Thread::setPriority (jint newPriority)
+{
+ checkAccess ();
+ if (newPriority < MIN_PRIORITY || newPriority > MAX_PRIORITY)
+ _Jv_Throw (new IllegalArgumentException);
+
+ jint gmax = group->getMaxPriority();
+ if (newPriority > gmax)
+ newPriority = gmax;
+
+ priority = newPriority;
+ natThread *nt = (natThread *) data;
+ _Jv_ThreadSetPriority (nt->thread, priority);
+}
+
+void
+java::lang::Thread::sleep (jlong millis, jint nanos)
+{
+ if (millis < 0 || nanos < 0 || nanos > 999999)
+ _Jv_Throw (new IllegalArgumentException);
+
+ Thread *current = currentThread ();
+ if (current->isInterrupted ())
+ _Jv_Throw (new InterruptedException);
+
+ // We use a condition variable to implement sleeping so that an
+ // interrupt can wake us up.
+ natThread *nt = (natThread *) current->data;
+ _Jv_MutexLock (&nt->interrupt_mutex);
+ _Jv_CondWait (&nt->interrupt_cond, &nt->interrupt_mutex,
+ millis, nanos);
+ _Jv_MutexUnlock (&nt->interrupt_mutex);
+
+ if (current->isInterrupted ())
+ _Jv_Throw (new InterruptedException);
+}
+
+void
+java::lang::Thread::finish_ (void)
+{
+ // Notify all threads waiting to join this thread.
+ _Jv_MonitorEnter (this);
+ alive_flag = false;
+
+ // Note that we don't bother cleaning up the joiner list here. That
+ // is taken care of when each thread wakes up again.
+ natThread *nt = (natThread *) data;
+ for (natThread *t = nt->joiner; t != NULL; t = t->next)
+ {
+ _Jv_MutexLock (&t->interrupt_mutex);
+ _Jv_CondNotify (&t->interrupt_cond, &t->interrupt_mutex);
+ _Jv_MutexUnlock (&t->interrupt_mutex);
+ }
+
+ _Jv_MonitorExit (this);
+}
+
+void
+java::lang::Thread::run__ (jobject obj)
+{
+ java::lang::Thread *thread = (java::lang::Thread *) obj;
+ thread->run_ ();
+}
+
+void
+java::lang::Thread::start (void)
+{
+ JvSynchronize sync (this);
+
+ if (alive_flag)
+ _Jv_Throw (new IllegalThreadStateException);
+
+ alive_flag = true;
+ natThread *nt = (natThread *) data;
+ _Jv_ThreadStart (this, nt->thread, (_Jv_ThreadStartFunc *) &run__);
+}
+
+void
+java::lang::Thread::stop (java::lang::Throwable *e)
+{
+ JvSynchronize sync (this);
+ checkAccess ();
+ if (! e)
+ _Jv_Throw (new NullPointerException);
+ natThread *nt = (natThread *) data;
+ _Jv_ThreadCancel (nt->thread, e);
+}
+
+void
+java::lang::Thread::suspend (void)
+{
+ checkAccess ();
+ JvFail ("java::lang::Thread::suspend unimplemented");
+}
+
+void
+java::lang::Thread::yield (void)
+{
+ _Jv_ThreadYield ();
+}
diff --git a/libjava/java/lang/reflect/AccessibleObject.java b/libjava/java/lang/reflect/AccessibleObject.java
new file mode 100644
index 00000000000..8c869e167b0
--- /dev/null
+++ b/libjava/java/lang/reflect/AccessibleObject.java
@@ -0,0 +1,53 @@
+// AccessibleObject.java - Base for reflection objects.
+
+/* 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.lang.reflect;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date December 12, 1998
+ */
+/* Written using JDK 1.2 beta docs.
+ * Status: Believed complete and correct.
+ */
+
+public class AccessibleObject
+{
+ protected AccessibleObject ()
+ {
+ flag = false;
+ }
+
+ boolean isAccessible ()
+ {
+ return flag;
+ }
+
+ static void setAccessible (AccessibleObject[] array, boolean flag)
+ {
+ checkPermission ();
+ for (int i = 0; i < array.length; ++i)
+ array[i].flag = flag;
+ }
+
+ void setAccessible (boolean flag)
+ {
+ checkPermission ();
+ this.flag = flag;
+ }
+
+ private static final void checkPermission ()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ // FIXME: sm.checkPermission(ReflectPermission ("suppressAccessChecks"))
+ }
+
+ private boolean flag;
+}
diff --git a/libjava/java/lang/reflect/Array.java b/libjava/java/lang/reflect/Array.java
new file mode 100644
index 00000000000..398f80d5643
--- /dev/null
+++ b/libjava/java/lang/reflect/Array.java
@@ -0,0 +1,78 @@
+// FileDescriptor.java - Open file or device
+
+/* 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 java.lang.reflect;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date january 12, 1999
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3.
+ * Status: Believe complete and correct.
+ */
+
+public final class Array
+{
+ Array () { }
+
+ public static native Object newInstance(Class componentType, int length);
+ public static native Object newInstance(Class elementType, int[] dimensions);
+ public static native int getLength (Object array);
+
+ public static native Object get (Object array, int index);
+ public static native char getChar (Object array, int index);
+ public static native byte getByte (Object array, int index);
+ public static native short getShort (Object array, int index);
+ public static native int getInt (Object array, int index);
+ public static native long getLong (Object array, int index);
+ public static native float getFloat (Object array, int index);
+ public static native double getDouble (Object array, int index);
+ public static native boolean getBoolean (Object array, int index);
+
+ private static native Class getElementType (Object array, int index);
+
+ private static native void set (Object array, int index,
+ Object value, Class elType);
+
+ public static void set (Object array, int index, Object value)
+ {
+ Class elType = getElementType(array, index);
+ if (! elType.isPrimitive())
+ set(array, index, value, elType);
+ else if (value instanceof Byte)
+ setByte(array, index, ((Byte) value).byteValue());
+ else if (value instanceof Short)
+ setShort (array, index, ((Short) value).shortValue());
+ else if (value instanceof Integer)
+ setInt(array, index, ((Integer) value).intValue());
+ else if (value instanceof Long)
+ setLong(array, index, ((Long) value).longValue());
+ else if (value instanceof Float)
+ setFloat(array, index, ((Float) value).floatValue());
+ else if (value instanceof Double)
+ setDouble(array, index, ((Double) value).doubleValue());
+ else if (value instanceof Character)
+ setChar(array, index, ((Character) value).charValue());
+ else if (value instanceof Boolean)
+ setBoolean(array, index, ((Boolean) value).booleanValue());
+ else
+ throw new IllegalArgumentException();
+ }
+
+ public static native void setByte (Object array, int index, byte value);
+ public static native void setShort (Object array, int index, short value);
+ public static native void setInt (Object array, int index, int value);
+ public static native void setLong (Object array, int index, long value);
+ public static native void setFloat (Object array, int index, float value);
+ public static native void setDouble (Object array, int index, double value);
+ public static native void setChar (Object array, int index, char value);
+ public static native void setBoolean(Object array, int index, boolean value);
+}
diff --git a/libjava/java/lang/reflect/Constructor.java b/libjava/java/lang/reflect/Constructor.java
new file mode 100644
index 00000000000..466c1204bae
--- /dev/null
+++ b/libjava/java/lang/reflect/Constructor.java
@@ -0,0 +1,106 @@
+// Constructor.java - Represents a constructor for a class.
+
+/* 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.lang.reflect;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date December 12, 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: Incomplete: needs a private constructor, and
+ * newInstance() needs to be written.
+ */
+
+public final class Constructor extends AccessibleObject implements Member
+{
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof Constructor))
+ return false;
+ Constructor c = (Constructor) obj;
+ return decl_class == c.decl_class && index == c.index;
+ }
+
+ public Class getDeclaringClass ()
+ {
+ return decl_class;
+ }
+
+ public Class[] getExceptionTypes ()
+ {
+ return (Class[]) exception_types.clone();
+ }
+
+ public int getModifiers ()
+ {
+ return modifiers;
+ }
+
+ public String getName ()
+ {
+ return decl_class.getName();
+ }
+
+ public Class[] getParameterTypes ()
+ {
+ return (Class[]) parameter_types.clone();
+ }
+
+ public int hashCode ()
+ {
+ // FIXME.
+ return getName().hashCode();
+ }
+
+ // FIXME: this must be native. Should share implementation with
+ // Method.invoke.
+ public Object newInstance (Object[] args)
+ throws InstantiationException, IllegalAccessException,
+ IllegalArgumentException, InvocationTargetException
+ {
+ return null;
+ }
+
+ public String toString ()
+ {
+ StringBuffer b = new StringBuffer ();
+ b.append(Modifier.toString(modifiers));
+ b.append(" ");
+ b.append(getName());
+ b.append("(");
+ for (int i = 0; i < parameter_types.length; ++i)
+ {
+ b.append(parameter_types[i].toString());
+ if (i < parameter_types.length - 1)
+ b.append(",");
+ }
+ b.append(")");
+ return b.toString();
+ }
+
+ // Can't create these. FIXME.
+ private Constructor ()
+ {
+ }
+
+ // Declaring class.
+ private Class decl_class;
+ // Exception types.
+ private Class[] exception_types;
+ // Modifiers.
+ private int modifiers;
+ // Parameter types.
+ private Class[] parameter_types;
+ // Index of this method in declaring class' method table.
+ private int index;
+}
diff --git a/libjava/java/lang/reflect/Field.java b/libjava/java/lang/reflect/Field.java
new file mode 100644
index 00000000000..7c7e690926a
--- /dev/null
+++ b/libjava/java/lang/reflect/Field.java
@@ -0,0 +1,264 @@
+/* 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.lang.reflect;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date September 1998; February 1999.
+ */
+/* Status: Mostly implemented.
+ * However, access checks are not implemented. See natField.cc for
+ * _Jv_CheckFieldAccessibility as well as the missing getCaller.
+ * Note that the idea is to have to compiler convert calls to
+ * setXXX(...) and getXXX(...) to setXXX(CALLER, ...) and getXXX(CALLER, ...),
+ * where CALLER is reference to the class that contains the calls to
+ * setXXX or getXXX. This is easy for the compiler, and replaces
+ * expensive stack and table searching with a constant.
+ */
+
+public final class Field extends AccessibleObject implements Member
+{
+ private Class declaringClass;
+
+ // This is filled in by getName.
+ private String name;
+
+ // Offset in bytes from the start of declaringClass's fields array.
+ private int offset;
+
+ public boolean equals (Object fld)
+ {
+ if (! (fld instanceof Field))
+ return false;
+ Field f = (Field) fld;
+ return declaringClass == f.declaringClass && offset == f.offset;
+ }
+
+ public Class getDeclaringClass ()
+ {
+ return declaringClass;
+ }
+
+ public native String getName ();
+
+ public native Class getType ();
+
+ public native int getModifiers ();
+
+ public int hashCode()
+ {
+ return (declaringClass.hashCode() ^ offset);
+ }
+
+ // The idea is that the compiler will magically translate
+ // fld.getShort(obj) to fld.getShort(THISCLASS, obj).
+ // This makes checking assessiblity more efficient,
+ // since we don't have to do any stack-walking.
+
+ public boolean getBoolean (Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getBoolean(null, obj);
+ }
+ public char getChar (Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getChar(null, obj);
+ }
+
+ public byte getByte (Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getByte(null, obj);
+ }
+
+ public short getShort (Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getShort(null, obj);
+ }
+
+ public int getInt (Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getInt(null, obj);
+ }
+
+ public long getLong (Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getLong(null, obj);
+ }
+
+ public float getFloat (Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getFloat(null, obj);
+ }
+
+ public double getDouble (Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getDouble(null, obj);
+ }
+
+ public Object get (Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return get(null, obj);
+ }
+
+ private native boolean getBoolean (Class caller, Object obj)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ private native char getChar (Class caller, Object obj)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ private native byte getByte (Class caller, Object obj)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ private native short getShort (Class caller, Object obj)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ private native int getInt (Class caller, Object obj)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ private native long getLong (Class caller, Object obj)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ private native float getFloat (Class caller, Object obj)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ private native double getDouble (Class caller, Object obj)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ public native Object get (Class caller, Object obj)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ public void setByte (Object obj, byte b)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ setByte(null, obj, b);
+ }
+
+ public void setShort (Object obj, short s)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ setShort(null, obj, s);
+ }
+
+ public void setInt (Object obj, int i)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ setInt(null, obj, i);
+ }
+
+ public void setLong (Object obj, long l)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ setLong(null, obj, l);
+ }
+
+ public void setFloat (Object obj, float f)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ setFloat(null, obj, f);
+ }
+
+ public void setDouble (Object obj, double d)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ setDouble(null, obj, d);
+ }
+
+ public void setChar (Object obj, char c)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ setChar(null, obj, c);
+ }
+
+ public void setBoolean (Object obj, boolean b)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ setBoolean(null, obj, b);
+ }
+
+ public native void setByte (Class caller, Object obj, byte b)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ public native void setShort (Class caller, Object obj, short s)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ public native void setInt (Class caller, Object obj, int i)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ public native void setLong (Class caller, Object obj, long l)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ public native void setFloat (Class caller, Object obj, float f)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ public native void setDouble (Class caller, Object obj, double d)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ public native void setChar (Class caller, Object obj, char c)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ public native void setBoolean (Class caller, Object obj, boolean b)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ private native void set (Class caller, Object obj, Object val, Class type)
+ throws IllegalArgumentException, IllegalAccessException;
+
+ public void set (Object object, Object value)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ set(null, object, value);
+ }
+
+ public void set (Class caller, Object object, Object value)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ Class type = getType();
+ if (! type.isPrimitive())
+ set(caller, object, value, type);
+ else if (value instanceof Byte)
+ setByte(caller, object, ((Byte) value).byteValue());
+ else if (value instanceof Short)
+ setShort (caller, object, ((Short) value).shortValue());
+ else if (value instanceof Integer)
+ setInt(caller, object, ((Integer) value).intValue());
+ else if (value instanceof Long)
+ setLong(caller, object, ((Long) value).longValue());
+ else if (value instanceof Float)
+ setFloat(caller, object, ((Float) value).floatValue());
+ else if (value instanceof Double)
+ setDouble(caller, object, ((Double) value).doubleValue());
+ else if (value instanceof Character)
+ setChar(caller, object, ((Character) value).charValue());
+ else if (value instanceof Boolean)
+ setBoolean(caller, object, ((Boolean) value).booleanValue());
+ else
+ throw new IllegalArgumentException();
+ }
+
+ public String toString ()
+ {
+ StringBuffer sbuf = new StringBuffer ();
+ int mods = getModifiers();
+ if (mods != 0)
+ Modifier.toString(mods, sbuf);
+ sbuf.append(getType());
+ sbuf.append(' ');
+ sbuf.append(getDeclaringClass());
+ sbuf.append('.');
+ sbuf.append(getName());
+ return sbuf.toString();
+ }
+}
diff --git a/libjava/java/lang/reflect/InvocationTargetException.java b/libjava/java/lang/reflect/InvocationTargetException.java
new file mode 100644
index 00000000000..eccd5f7daed
--- /dev/null
+++ b/libjava/java/lang/reflect/InvocationTargetException.java
@@ -0,0 +1,73 @@
+// InvocationTargetException.java - Wrapper exception for reflection.
+
+/* 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.lang.reflect;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date December 12, 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 InvocationTargetException extends Exception
+{
+ public Throwable getTargetException ()
+ {
+ return target;
+ }
+
+ protected InvocationTargetException ()
+ {
+ super ();
+ target = null;
+ }
+
+ public InvocationTargetException (Throwable exception)
+ {
+ super ();
+ target = exception;
+ }
+
+ public InvocationTargetException (Throwable exception, String msg)
+ {
+ super (msg);
+ target = exception;
+ }
+
+ // This is from JDK 1.2.
+ public void printStackTrace ()
+ {
+ if (target != null)
+ target.printStackTrace();
+ }
+
+ // This is from JDK 1.2.
+ public void printStackTrace (PrintStream s)
+ {
+ if (target != null)
+ target.printStackTrace(s);
+ }
+
+ // This is from JDK 1.2.
+ public void printStackTrace (PrintWriter wr)
+ {
+ if (target != null)
+ target.printStackTrace(wr);
+ }
+
+ // The wrapped exception. The name is specified by the
+ // serialization spec.
+ private Throwable target;
+}
diff --git a/libjava/java/lang/reflect/Member.java b/libjava/java/lang/reflect/Member.java
new file mode 100644
index 00000000000..a54f05f689e
--- /dev/null
+++ b/libjava/java/lang/reflect/Member.java
@@ -0,0 +1,26 @@
+/* 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.lang.reflect;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date September 27, 1998.
+ */
+/* Written using "Java Class Libraries", 2nd edition.
+ * Status: Believed complete and correct.
+ */
+
+public interface Member
+{
+ public static final int PUBLIC = 0;
+ public static final int DECLARED = 1;
+ public Class getDeclaringClass ();
+ public int getModifiers ();
+ public String getName();
+}
diff --git a/libjava/java/lang/reflect/Method.java b/libjava/java/lang/reflect/Method.java
new file mode 100644
index 00000000000..01e830876e5
--- /dev/null
+++ b/libjava/java/lang/reflect/Method.java
@@ -0,0 +1,123 @@
+// Method.java - Represent method of class or interface.
+
+/* 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.lang.reflect;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date December 12, 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: Incomplete: needs a private constructor, and
+ * invoke() needs to be finished.
+ */
+
+public final class Method extends AccessibleObject implements Member
+{
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof Method))
+ return false;
+ Method m = (Method) obj;
+ return declaringClass == m.declaringClass && offset == m.offset;
+ }
+
+ public Class getDeclaringClass ()
+ {
+ return declaringClass;
+ }
+
+ public Class[] getExceptionTypes ()
+ {
+ return (Class[]) exception_types.clone();
+ }
+
+ public native int getModifiers ();
+
+ public native String getName ();
+
+ private native void getType ();
+
+ public Class[] getParameterTypes ()
+ {
+ if (parameter_types == null)
+ getType();
+ return (Class[]) parameter_types.clone();
+ }
+
+ public Class getReturnType ()
+ {
+ if (return_type == null)
+ getType();
+ return return_type;
+ }
+
+ public int hashCode ()
+ {
+ // FIXME.
+ return name.hashCode() + declaringClass.getName().hashCode();
+ }
+
+ public native Object invoke (Object obj, Object[] args)
+ throws IllegalAccessException, IllegalArgumentException,
+ InvocationTargetException;
+
+ public String toString ()
+ {
+ StringBuffer b = new StringBuffer ();
+ b.append(Modifier.toString(getModifiers()));
+ b.append(" ");
+ b.append(return_type.toString());
+ b.append(" ");
+ b.append(declaringClass.toString());
+ b.append(".");
+ b.append(name);
+ b.append("(");
+ for (int i = 0; i < parameter_types.length; ++i)
+ {
+ b.append(parameter_types[i].toString());
+ if (i < parameter_types.length - 1)
+ b.append(",");
+ }
+ b.append(")");
+ if (exception_types.length > 0)
+ {
+ b.append(" throws ");
+ for (int i = 0; i < exception_types.length; ++i)
+ {
+ b.append(exception_types[i].toString());
+ if (i < exception_types.length - 1)
+ b.append(",");
+ }
+ }
+ return b.toString();
+ }
+
+ private Method ()
+ {
+ }
+
+ // Declaring class.
+ private Class declaringClass;
+
+ // Exception types.
+ private Class[] exception_types;
+ // Name cache. (Initially null.)
+ private String name;
+ // Parameter types.
+ private Class[] parameter_types;
+ // Return type.
+ private Class return_type;
+
+ // Offset in bytes from the start of declaringClass's methods array.
+ private int offset;
+}
diff --git a/libjava/java/lang/reflect/Modifier.java b/libjava/java/lang/reflect/Modifier.java
new file mode 100644
index 00000000000..f9df49e80ee
--- /dev/null
+++ b/libjava/java/lang/reflect/Modifier.java
@@ -0,0 +1,130 @@
+// Modifier.java - Process modifier values.
+
+/* 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. */
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 1, 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 to version 1.1
+ */
+
+package java.lang.reflect;
+
+public class Modifier
+{
+ public static final int PUBLIC = 0x001;
+ public static final int PRIVATE = 0x002;
+ public static final int PROTECTED = 0x004;
+ public static final int STATIC = 0x008;
+ public static final int FINAL = 0x010;
+ public static final int SYNCHRONIZED = 0x020;
+ public static final int VOLATILE = 0x040;
+ public static final int TRANSIENT = 0x080;
+ public static final int NATIVE = 0x100;
+ public static final int INTERFACE = 0x200;
+ public static final int ABSTRACT = 0x400;
+
+ public static boolean isAbstract (int mod)
+ {
+ return (mod & ABSTRACT) != 0;
+ }
+
+ public static boolean isFinal (int mod)
+ {
+ return (mod & FINAL) != 0;
+ }
+
+ public static boolean isInterface (int mod)
+ {
+ return (mod & INTERFACE) != 0;
+ }
+
+ public static boolean isNative (int mod)
+ {
+ return (mod & NATIVE) != 0;
+ }
+
+ public static boolean isPrivate (int mod)
+ {
+ return (mod & PRIVATE) != 0;
+ }
+
+ public static boolean isProtected (int mod)
+ {
+ return (mod & PROTECTED) != 0;
+ }
+
+ public static boolean isPublic (int mod)
+ {
+ return (mod & PUBLIC) != 0;
+ }
+
+ public static boolean isStatic (int mod)
+ {
+ return (mod & STATIC) != 0;
+ }
+
+ public static boolean isSynchronized (int mod)
+ {
+ return (mod & SYNCHRONIZED) != 0;
+ }
+
+ public static boolean isTransient (int mod)
+ {
+ return (mod & TRANSIENT) != 0;
+ }
+
+ public static boolean isVolatile (int mod)
+ {
+ return (mod & VOLATILE) != 0;
+ }
+
+ public static String toString (int mod)
+ {
+ StringBuffer r = new StringBuffer ();
+ toString(mod, r);
+ return r.toString();
+ }
+
+ static void toString (int mod, StringBuffer r)
+ {
+ if (isPublic (mod))
+ r.append("public ");
+ if (isProtected (mod))
+ r.append("protected ");
+ if (isPrivate (mod))
+ r.append("private ");
+ if (isAbstract (mod))
+ r.append("abstract ");
+ if (isStatic (mod))
+ r.append("static ");
+ if (isFinal (mod))
+ r.append("final ");
+ if (isTransient (mod))
+ r.append("transient ");
+ if (isVolatile (mod))
+ r.append("volatile ");
+ if (isNative (mod))
+ r.append("native ");
+ if (isSynchronized (mod))
+ r.append("synchronized ");
+ if (isInterface (mod))
+ r.append("interface ");
+
+ // Trim trailing space.
+ int l = r.length();
+ if (l > 0)
+ r.setLength(l - 1);
+ }
+}
diff --git a/libjava/java/lang/reflect/natArray.cc b/libjava/java/lang/reflect/natArray.cc
new file mode 100644
index 00000000000..3da8b5c01ce
--- /dev/null
+++ b/libjava/java/lang/reflect/natArray.cc
@@ -0,0 +1,339 @@
+// natField.cc - Implementation of java.lang.reflect.Field native methods.
+
+/* 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 <stdlib.h>
+
+#include <jvm.h>
+#include <cni.h>
+#include <java/lang/reflect/Array.h>
+#include <java/lang/IllegalArgumentException.h>
+#include <java/lang/Byte.h>
+#include <java/lang/Short.h>
+#include <java/lang/Integer.h>
+#include <java/lang/Long.h>
+#include <java/lang/Float.h>
+#include <java/lang/Double.h>
+#include <java/lang/Boolean.h>
+#include <java/lang/Character.h>
+
+jobject
+java::lang::reflect::Array::newInstance (jclass componentType, jint length)
+{
+ if (componentType->isPrimitive())
+ return _Jv_NewPrimArray (componentType, length);
+ else
+ return JvNewObjectArray (length, componentType, NULL);
+
+}
+
+jobject
+java::lang::reflect::Array::newInstance (jclass componentType, jintArray dimensions)
+{
+ jint ndims = dimensions->length;
+ if (ndims == 0)
+ return componentType->newInstance ();
+ jint* dims = elements (dimensions);
+ if (ndims == 1)
+ return newInstance (componentType, dims[0]);
+ jclass arrayType = componentType;
+ for (int i = 0; i < ndims; i++)
+ arrayType = _Jv_FindArrayClass (arrayType);
+ return _Jv_NewMultiArray (arrayType, ndims, dims);
+
+}
+
+jint
+java::lang::reflect::Array::getLength (jobject array)
+{
+ jclass arrayType = array->getClass();
+ if (! arrayType->isArray ())
+ JvThrow (new java::lang::IllegalArgumentException());
+ return ((__JArray*) array)->length;
+}
+
+jclass
+java::lang::reflect::Array::getElementType (jobject array, jint index)
+{
+ jclass arrayType = array->getClass();
+ if (! arrayType->isArray ())
+ JvThrow (new java::lang::IllegalArgumentException());
+ jint length = ((__JArray*) array)->length;
+ if ((_Jv_uint) index >= (_Jv_uint) length)
+ _Jv_ThrowBadArrayIndex(index);
+ return arrayType->getComponentType ();
+}
+
+jboolean
+java::lang::reflect::Array::getBoolean (jobject array, jint index)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (boolean))
+ return elements ((jbooleanArray) array) [index];
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+jchar
+java::lang::reflect::Array::getChar (jobject array, jint index)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (char))
+ return elements ((jcharArray) array) [index];
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+jbyte
+java::lang::reflect::Array::getByte (jobject array, jint index)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (byte))
+ return elements ((jbyteArray) array) [index];
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+jshort
+java::lang::reflect::Array::getShort (jobject array, jint index)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (short))
+ return elements ((jshortArray) array) [index];
+ if (elementType == JvPrimClass (byte))
+ return elements ((jbyteArray) array) [index];
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+jint
+java::lang::reflect::Array::getInt (jobject array, jint index)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (int))
+ return elements ((jintArray) array) [index];
+ if (elementType == JvPrimClass (short))
+ return elements ((jshortArray) array) [index];
+ if (elementType == JvPrimClass (byte))
+ return elements ((jbyteArray) array) [index];
+ if (elementType == JvPrimClass (char))
+ return elements ((jcharArray) array) [index];
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+jlong
+java::lang::reflect::Array::getLong (jobject array, jint index)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (long))
+ return elements ((jlongArray) array) [index];
+ if (elementType == JvPrimClass (int))
+ return elements ((jintArray) array) [index];
+ if (elementType == JvPrimClass (short))
+ return elements ((jshortArray) array) [index];
+ if (elementType == JvPrimClass (byte))
+ return elements ((jbyteArray) array) [index];
+ if (elementType == JvPrimClass (char))
+ return elements ((jcharArray) array) [index];
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+jfloat
+java::lang::reflect::Array::getFloat (jobject array, jint index)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (float))
+ return elements ((jfloatArray) array) [index];
+ if (elementType == JvPrimClass (long))
+ return elements ((jlongArray) array) [index];
+ if (elementType == JvPrimClass (int))
+ return elements ((jintArray) array) [index];
+ if (elementType == JvPrimClass (short))
+ return elements ((jshortArray) array) [index];
+ if (elementType == JvPrimClass (byte))
+ return elements ((jbyteArray) array) [index];
+ if (elementType == JvPrimClass (char))
+ return elements ((jcharArray) array) [index];
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+jdouble
+java::lang::reflect::Array::getDouble (jobject array, jint index)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (double))
+ return elements ((jdoubleArray) array) [index];
+ if (elementType == JvPrimClass (float))
+ return elements ((jfloatArray) array) [index];
+ if (elementType == JvPrimClass (long))
+ return elements ((jlongArray) array) [index];
+ if (elementType == JvPrimClass (int))
+ return elements ((jintArray) array) [index];
+ if (elementType == JvPrimClass (short))
+ return elements ((jshortArray) array) [index];
+ if (elementType == JvPrimClass (byte))
+ return elements ((jbyteArray) array) [index];
+ if (elementType == JvPrimClass (char))
+ return elements ((jcharArray) array) [index];
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+jobject
+java::lang::reflect::Array::get (jobject array, jint index)
+{
+ jclass elementType = getElementType (array, index);
+ if (! elementType->isPrimitive ())
+ return elements ((jobjectArray) array) [index];
+ if (elementType == JvPrimClass (double))
+ return new java::lang::Double (elements ((jdoubleArray) array) [index]);
+ if (elementType == JvPrimClass (float))
+ return new java::lang::Float (elements ((jfloatArray) array) [index]);
+ if (elementType == JvPrimClass (long))
+ return new java::lang::Long (elements ((jlongArray) array) [index]);
+ if (elementType == JvPrimClass (int))
+ return new java::lang::Integer (elements ((jintArray) array) [index]);
+ if (elementType == JvPrimClass (short))
+ return new java::lang::Short (elements ((jshortArray) array) [index]);
+ if (elementType == JvPrimClass (byte))
+ return new java::lang::Byte (elements ((jbyteArray) array) [index]);
+ if (elementType == JvPrimClass (char))
+ return new java::lang::Character (elements ((jcharArray) array) [index]);
+ if (elementType == JvPrimClass (boolean))
+ if (elements ((jbooleanArray) array) [index])
+ return java::lang::Boolean::TRUE;
+ else
+ return java::lang::Boolean::FALSE;
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+void
+java::lang::reflect::Array::setChar (jobject array, jint index, jchar value)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (char))
+ elements ((jcharArray) array) [index] = value;
+ else if (elementType == JvPrimClass (int))
+ elements ((jintArray) array) [index] = value;
+ else if (elementType == JvPrimClass (long))
+ elements ((jlongArray) array) [index] = value;
+ else if (elementType == JvPrimClass (float))
+ elements ((jfloatArray) array) [index] = value;
+ else if (elementType == JvPrimClass (double))
+ elements ((jdoubleArray) array) [index] = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+void
+java::lang::reflect::Array::setByte (jobject array, jint index, jbyte value)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (byte))
+ elements ((jbyteArray) array) [index] = value;
+ else if (elementType == JvPrimClass (short))
+ elements ((jshortArray) array) [index] = value;
+ else if (elementType == JvPrimClass (int))
+ elements ((jintArray) array) [index] = value;
+ else if (elementType == JvPrimClass (long))
+ elements ((jlongArray) array) [index] = value;
+ else if (elementType == JvPrimClass (float))
+ elements ((jfloatArray) array) [index] = value;
+ else if (elementType == JvPrimClass (double))
+ elements ((jdoubleArray) array) [index] = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+void
+java::lang::reflect::Array::setShort (jobject array, jint index, jshort value)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (short))
+ elements ((jshortArray) array) [index] = value;
+ else if (elementType == JvPrimClass (int))
+ elements ((jintArray) array) [index] = value;
+ else if (elementType == JvPrimClass (long))
+ elements ((jlongArray) array) [index] = value;
+ else if (elementType == JvPrimClass (float))
+ elements ((jfloatArray) array) [index] = value;
+ else if (elementType == JvPrimClass (double))
+ elements ((jdoubleArray) array) [index] = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+void
+java::lang::reflect::Array::setInt (jobject array, jint index, jint value)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (int))
+ elements ((jintArray) array) [index] = value;
+ else if (elementType == JvPrimClass (long))
+ elements ((jlongArray) array) [index] = value;
+ else if (elementType == JvPrimClass (float))
+ elements ((jfloatArray) array) [index] = value;
+ else if (elementType == JvPrimClass (double))
+ elements ((jdoubleArray) array) [index] = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+void
+java::lang::reflect::Array::setLong (jobject array, jint index, jlong value)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (long))
+ elements ((jlongArray) array) [index] = value;
+ else if (elementType == JvPrimClass (float))
+ elements ((jfloatArray) array) [index] = value;
+ else if (elementType == JvPrimClass (double))
+ elements ((jdoubleArray) array) [index] = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+void
+java::lang::reflect::Array::setFloat (jobject array, jint index, jfloat value)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (float))
+ elements ((jfloatArray) array) [index] = value;
+ else if (elementType == JvPrimClass (double))
+ elements ((jdoubleArray) array) [index] = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+void
+java::lang::reflect::Array::setDouble (jobject array, jint index, jdouble value)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (double))
+ elements ((jdoubleArray) array) [index] = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+void
+java::lang::reflect::Array::setBoolean (jobject array,
+ jint index, jboolean value)
+{
+ jclass elementType = getElementType (array, index);
+ if (elementType == JvPrimClass (boolean))
+ elements ((jbooleanArray) array) [index] = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+void
+java::lang::reflect::Array::set (jobject array, jint index,
+ jobject value, jclass elType)
+{
+ if (! _Jv_IsInstanceOf (value, elType))
+ JvThrow (new java::lang::IllegalArgumentException ());
+ elements ((jobjectArray) array) [index] = value;
+}
diff --git a/libjava/java/lang/reflect/natField.cc b/libjava/java/lang/reflect/natField.cc
new file mode 100644
index 00000000000..2449b42545c
--- /dev/null
+++ b/libjava/java/lang/reflect/natField.cc
@@ -0,0 +1,435 @@
+// natField.cc - Implementation of java.lang.reflect.Field native methods.
+
+/* 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 <stdlib.h>
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/lang/reflect/Field.h>
+#include <java/lang/reflect/Modifier.h>
+#include <java/lang/IllegalArgumentException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/Byte.h>
+#include <java/lang/Short.h>
+#include <java/lang/Integer.h>
+#include <java/lang/Long.h>
+#include <java/lang/Float.h>
+#include <java/lang/Double.h>
+#include <java/lang/Boolean.h>
+#include <java/lang/Character.h>
+#include <java-field.h>
+
+jint
+java::lang::reflect::Field::getModifiers ()
+{
+ return _Jv_FromReflectedField (this)->getModifiers ();
+}
+
+jstring
+java::lang::reflect::Field::getName ()
+{
+ if (name == NULL)
+ name = _Jv_NewStringUtf8Const (_Jv_FromReflectedField (this)->name);
+ return name;
+}
+
+jclass
+java::lang::reflect::Field::getType ()
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ if (! fld->isResolved())
+ {
+ JvSynchronize sync (declaringClass);
+ if (! fld->isResolved())
+ {
+ fld->type
+ = _Jv_FindClassFromSignature(((Utf8Const*) (fld->type))->data,
+ declaringClass->getClassLoader());
+ fld->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG;
+ }
+ }
+ return fld->type;
+}
+
+static void
+_Jv_CheckFieldAccessibility (jfieldID /*fld*/, jclass /*caller*/)
+{
+#if 0
+ if (caller == NULL)
+ caller = getCaller();
+#endif
+#if 0
+ _Jv_ushort flags = fld->getModifiers();
+ check accesss;
+#endif
+}
+
+static void*
+getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj)
+{
+ jfieldID fld = _Jv_FromReflectedField (field);
+ _Jv_ushort flags = fld->getModifiers();
+ if (! (flags & java::lang::reflect::Modifier::PUBLIC)
+ && ! field->isAccessible ())
+ _Jv_CheckFieldAccessibility (fld, caller);
+ if (flags & java::lang::reflect::Modifier::STATIC)
+ {
+ jclass fldClass = field->getDeclaringClass ();
+ JvInitClass(fldClass);
+ return fld->u.addr;
+ }
+ else
+ {
+ if (obj == NULL)
+ _Jv_Throw (new java::lang::NullPointerException ());
+ if (! _Jv_IsInstanceOf (obj, field->getDeclaringClass()))
+ JvThrow (new java::lang::IllegalArgumentException ());
+ return (void*) ((char*) obj + fld->getOffset ());
+ }
+}
+
+static jboolean
+getBoolean (jclass cls, void* addr)
+{
+ if (cls == JvPrimClass (boolean))
+ return * (jboolean *) addr;
+ _Jv_Throw (new java::lang::IllegalArgumentException());
+}
+
+static jchar
+getChar (jclass cls, void* addr)
+{
+ if (cls == JvPrimClass (char))
+ return * (jchar *) addr;
+ _Jv_Throw (new java::lang::IllegalArgumentException());
+}
+
+static jbyte
+getByte (jclass cls, void* addr)
+{
+ if (cls == JvPrimClass (byte))
+ return * (jbyte *) addr;
+ _Jv_Throw (new java::lang::IllegalArgumentException());
+}
+
+static jshort
+getShort (jclass cls, void* addr)
+{
+ if (cls == JvPrimClass (short))
+ return * (jshort *) addr;
+ if (cls == JvPrimClass (byte))
+ return * (jbyte *) addr;
+ _Jv_Throw (new java::lang::IllegalArgumentException());
+}
+
+static jint
+getInt (jclass cls, void* addr)
+{
+ if (cls == JvPrimClass (int))
+ return * (jint *) addr;
+ if (cls == JvPrimClass (short))
+ return * (jshort *) addr;
+ if (cls == JvPrimClass (char))
+ return * (jchar *) addr;
+ if (cls == JvPrimClass (byte))
+ return * (jbyte *) addr;
+ _Jv_Throw (new java::lang::IllegalArgumentException());
+}
+
+static jlong
+getLong (jclass cls, void* addr)
+{
+ if (cls == JvPrimClass (long))
+ return * (jlong *) addr;
+ return ::getInt(cls, addr);
+}
+
+static jfloat
+getFloat (jclass cls, void* addr)
+{
+ if (cls == JvPrimClass (float))
+ return * (jfloat *) addr;
+ if (cls == JvPrimClass (long))
+ return * (jlong *) addr;
+ return ::getInt(cls, addr);
+}
+
+static jdouble
+getDouble (jclass cls, void* addr)
+{
+ if (cls == JvPrimClass (double))
+ return * (jdouble *) addr;
+ if (cls == JvPrimClass (float))
+ return * (jfloat *) addr;
+ if (cls == JvPrimClass (long))
+ return * (jlong *) addr;
+ return ::getInt(cls, addr);
+}
+
+jboolean
+java::lang::reflect::Field::getBoolean (jclass caller, jobject obj)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ return ::getBoolean (fld->type, getAddr (this, caller, obj));
+}
+
+jchar
+java::lang::reflect::Field::getChar (jclass caller, jobject obj)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ return ::getChar (fld->type, getAddr (this, caller, obj));
+}
+
+jbyte
+java::lang::reflect::Field::getByte (jclass caller, jobject obj)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ return ::getByte (fld->type, getAddr (this, caller, obj));
+}
+
+jshort
+java::lang::reflect::Field::getShort (jclass caller, jobject obj)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ return ::getShort (fld->type, getAddr (this, caller, obj));
+}
+
+jint
+java::lang::reflect::Field::getInt (jclass caller, jobject obj)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ return ::getInt (fld->type, getAddr (this, caller, obj));
+}
+
+jlong
+java::lang::reflect::Field::getLong (jclass caller, jobject obj)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ return ::getLong (fld->type, getAddr (this, caller, obj));
+}
+
+jfloat
+java::lang::reflect::Field::getFloat (jclass caller, jobject obj)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ return ::getFloat (fld->type, getAddr (this, caller, obj));
+}
+
+jdouble
+java::lang::reflect::Field::getDouble (jclass caller, jobject obj)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ return ::getDouble (fld->type, getAddr (this, caller, obj));
+}
+
+jobject
+java::lang::reflect::Field::get (jclass caller, jobject obj)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ void* addr = getAddr (this, caller, obj);
+ if (! fld->type->isPrimitive ())
+ return * (jobject*) addr;
+ if (fld->type == JvPrimClass (double))
+ return new java::lang::Double (* (jdouble*) addr);
+ if (fld->type == JvPrimClass (float))
+ return new java::lang::Float (* (jfloat*) addr);
+ if (fld->type == JvPrimClass (long))
+ return new java::lang::Long (* (jlong*) addr);
+ if (fld->type == JvPrimClass (int))
+ return new java::lang::Integer (* (jint*) addr);
+ if (fld->type == JvPrimClass (short))
+ return new java::lang::Short (* (jshort*) addr);
+ if (fld->type == JvPrimClass (byte))
+ return new java::lang::Byte (* (jbyte*) addr);
+ if (fld->type == JvPrimClass (char))
+ return new java::lang::Character (* (jchar*) addr);
+ if (fld->type == JvPrimClass (boolean))
+ if (* (jboolean*) addr)
+ return java::lang::Boolean::TRUE;
+ else
+ return java::lang::Boolean::FALSE;
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+static void
+setBoolean (jclass type, void *addr, jboolean value)
+{
+ if (type == JvPrimClass (boolean))
+ * (jboolean *) addr = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+static void
+setChar (jclass type, void *addr, jchar value)
+{
+ if (type == JvPrimClass (char))
+ * (jchar *) addr = value;
+ else if (type == JvPrimClass (int))
+ * (jint *) addr = value;
+ else if (type == JvPrimClass (long))
+ * (jlong *) addr = value;
+ else if (type == JvPrimClass (float))
+ * (jfloat *) addr = value;
+ else if (type == JvPrimClass (double))
+ * (jdouble *) addr = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+static void
+setByte (jclass type, void *addr, jbyte value)
+{
+ if (type == JvPrimClass (byte))
+ * (jbyte *) addr = value;
+ else if (type == JvPrimClass (short))
+ * (jshort *) addr = value;
+ else if (type == JvPrimClass (int))
+ * (jint *) addr = value;
+ else if (type == JvPrimClass (long))
+ * (jlong *) addr = value;
+ else if (type == JvPrimClass (float))
+ * (jfloat *) addr = value;
+ else if (type == JvPrimClass (double))
+ * (jdouble *) addr = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+static void
+setShort (jclass type, void *addr, jshort value)
+{
+ if (type == JvPrimClass (short))
+ * (jshort *) addr = value;
+ else if (type == JvPrimClass (int))
+ * (jint *) addr = value;
+ else if (type == JvPrimClass (long))
+ * (jlong *) addr = value;
+ else if (type == JvPrimClass (float))
+ * (jfloat *) addr = value;
+ else if (type == JvPrimClass (double))
+ * (jdouble *) addr = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+static void
+setInt (jclass type, void *addr, jint value)
+{
+ if (type == JvPrimClass (int))
+ * (jint *) addr = value;
+ else if (type == JvPrimClass (long))
+ * (jlong *) addr = value;
+ else if (type == JvPrimClass (float))
+ * (jfloat *) addr = value;
+ else if (type == JvPrimClass (double))
+ * (jdouble *) addr = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+static void
+setLong (jclass type, void *addr, jlong value)
+{
+ if (type == JvPrimClass (long))
+ * (jlong *) addr = value;
+ else if (type == JvPrimClass (float))
+ * (jfloat *) addr = value;
+ else if (type == JvPrimClass (double))
+ * (jdouble *) addr = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+static void
+setFloat (jclass type, void *addr, jfloat value)
+{
+ if (type == JvPrimClass (float))
+ * (jfloat *) addr = value;
+ else if (type == JvPrimClass (double))
+ * (jdouble *) addr = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+static void
+setDouble (jclass type, void *addr, jdouble value)
+{
+ if (type == JvPrimClass (double))
+ * (jdouble *) addr = value;
+ else
+ JvThrow (new java::lang::IllegalArgumentException());
+}
+
+void
+java::lang::reflect::Field::setBoolean (jclass caller, jobject obj, jboolean b)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ ::setBoolean (fld->type, getAddr (this, caller, obj), b);
+}
+
+void
+java::lang::reflect::Field::setChar (jclass caller, jobject obj, jchar c)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ ::setChar (fld->type, getAddr (this, caller, obj), c);
+}
+
+void
+java::lang::reflect::Field::setByte (jclass caller, jobject obj, jbyte b)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ ::setByte (fld->type, getAddr (this, caller, obj), b);
+}
+
+void
+java::lang::reflect::Field::setShort (jclass caller, jobject obj, jshort s)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ ::setShort (fld->type, getAddr (this, caller, obj), s);
+}
+
+void
+java::lang::reflect::Field::setInt (jclass caller, jobject obj, jint i)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ ::setInt (fld->type, getAddr (this, caller, obj), i);
+}
+
+void
+java::lang::reflect::Field::setLong (jclass caller, jobject obj, jlong l)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ ::setLong (fld->type, getAddr (this, caller, obj), l);
+}
+void
+java::lang::reflect::Field::setFloat (jclass caller, jobject obj, jfloat f)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ ::setFloat (fld->type, getAddr (this, caller, obj), f);
+}
+
+void
+java::lang::reflect::Field::setDouble (jclass caller, jobject obj, jdouble d)
+{
+ jfieldID fld = _Jv_FromReflectedField (this);
+ ::setDouble (fld->type, getAddr (this, caller, obj), d);
+}
+
+void
+java::lang::reflect::Field::set (jclass caller, jobject object, jobject value, jclass type)
+{
+ if (! _Jv_IsInstanceOf (value, type))
+ JvThrow (new java::lang::IllegalArgumentException ());
+ void* addr = getAddr (this, caller, object);
+ * (jobject*) addr = value;
+}
diff --git a/libjava/java/lang/reflect/natMethod.cc b/libjava/java/lang/reflect/natMethod.cc
new file mode 100644
index 00000000000..720bbc3d74e
--- /dev/null
+++ b/libjava/java/lang/reflect/natMethod.cc
@@ -0,0 +1,386 @@
+// natMethod.cc - Native code for Method class.
+
+/* 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. */
+
+// This is about 90% done. Search for FIXME to see what remains.
+
+#include <config.h>
+
+#include <cni.h>
+#include <jvm.h>
+#include <java-array.h>
+
+#include <java/lang/reflect/Method.h>
+#include <java/lang/reflect/InvocationTargetException.h>
+#include <java/lang/reflect/Modifier.h>
+
+#include <java/lang/Void.h>
+#include <java/lang/Byte.h>
+#include <java/lang/Boolean.h>
+#include <java/lang/Character.h>
+#include <java/lang/Short.h>
+#include <java/lang/Integer.h>
+#include <java/lang/Long.h>
+#include <java/lang/Float.h>
+#include <java/lang/Double.h>
+#include <java/lang/IllegalArgumentException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/Class.h>
+#include <java-method.h>
+
+#define ClassClass _CL_Q34java4lang5Class
+extern java::lang::Class ClassClass;
+
+#include <stdlib.h>
+
+#if 0
+
+#include <ffi.h>
+
+#define VoidClass _CL_Q34java4lang4Void
+extern java::lang::Class VoidClass;
+#define ByteClass _CL_Q34java4lang4Byte
+extern java::lang::Class ByteClass;
+#define ShortClass _CL_Q34java4lang5Short
+extern java::lang::Class ShortClass;
+#define CharacterClass _CL_Q34java4lang9Character
+extern java::lang::Class CharacterClass;
+#define IntegerClass _CL_Q34java4lang7Integer
+extern java::lang::Class IntegerClass;
+#define LongClass _CL_Q34java4lang4Long
+extern java::lang::Class LongClass;
+#define FloatClass _CL_Q34java4lang5Float
+extern java::lang::Class FloatClass;
+#define DoubleClass _CL_Q34java4lang6Double
+extern java::lang::Class DoubleClass;
+
+struct cpair
+{
+ jclass prim;
+ jclass wrap;
+};
+
+// This is used to determine when a primitive widening conversion is
+// allowed.
+static cpair primitives[] =
+{
+#define VOID 0
+ { JvPrimClass (void), &VoidClass },
+ { JvPrimClass (byte), &ByteClass },
+#define SHORT 2
+ { JvPrimClass (short), &ShortClass },
+#define CHAR 3
+ { JvPrimClass (char), &CharacterClass },
+ { JvPrimClass (int), &IntegerClass },
+ { JvPrimClass (long), &LongClass },
+ { JvPrimClass (float), &FloatClass },
+ { JvPrimClass (double), &DoubleClass },
+ { NULL, NULL }
+};
+
+static jboolean
+can_widen (jclass from, jclass to)
+{
+ int fromx = -1, tox = -1;
+
+ for (int i = 0; primitives[i].prim; ++i)
+ {
+ if (primitives[i].wrap == from)
+ fromx = i;
+ if (primitives[i].prim == to)
+ tox = i;
+ }
+
+ // Can't handle a miss.
+ if (fromx == -1 || tox == -1)
+ return false;
+ // Can't handle Void arguments.
+ if (fromx == VOID || tox == VOID)
+ return false;
+ // Special-case short/char conversions.
+ if ((fromx == SHORT && tox == CHAR) || (fromx == CHAR && tox == SHORT))
+ return false;
+
+ return fromx <= tox;
+}
+
+static ffi_type *
+get_ffi_type (jclass klass)
+{
+ // A special case.
+ if (klass == NULL)
+ return &ffi_type_pointer;
+
+ ffi_type *r;
+ if (klass == JvPrimClass (byte))
+ r = &ffi_type_sint8;
+ else if (klass == JvPrimClass (short))
+ r = &ffi_type_sint16;
+ else if (klass == JvPrimClass (int))
+ r = &ffi_type_sint32;
+ else if (klass == JvPrimClass (long))
+ r = &ffi_type_sint64;
+ else if (klass == JvPrimClass (float))
+ r = &ffi_type_float;
+ else if (klass == JvPrimClass (double))
+ r = &ffi_type_double;
+ else if (klass == JvPrimClass (boolean))
+ {
+ // FIXME.
+ r = &ffi_type_sint8;
+ }
+ else if (klass == JvPrimClass (char))
+ r = &ffi_type_uint16;
+ else
+ {
+ JvAssert (! klass->isPrimitive());
+ r = &ffi_type_pointer;
+ }
+
+ return r;
+}
+
+// FIXME: the body of this method should be a separate function so
+// that Constructor can use it too.
+jobject
+java::lang::reflect::Method::invoke (jobject obj,
+ jobjectArray args)
+{
+ // FIXME: we need to be a friend of Class here.
+ _Jv_Method *meth = decl_class->methods[index];
+ if (! java::lang::reflect::Modifier::isStatic(modifiers))
+ {
+ jclass k = obj ? obj->getClass() : NULL;
+ if (! obj || ! decl_class->isAssignableFrom(k))
+ JvThrow (new java::lang::NullPointerException);
+ // FIXME: access checks.
+ meth = _Jv_LookupMethod (k, meth->name, meth->signature);
+ }
+
+ // FIXME: access checks.
+
+ if (parameter_types->length != args->length)
+ JvThrow (new java::lang::IllegalArgumentException);
+
+ ffi_type *rtype = get_ffi_type (return_type);
+ ffi_type **argtypes = (ffi_type **) alloca (parameter_types->length
+ * sizeof (ffi_type *));
+
+ jobject *paramelts = elements (parameter_types);
+ jobject *argelts = elements (args);
+
+ int size = 0;
+ for (int i = 0; i < parameter_types->length; ++i)
+ {
+ jclass k = argelts[i] ? argelts[i]->getClass() : NULL;
+ argtypes[i] = get_ffi_type (k);
+ if (paramelts[i]->isPrimitive())
+ {
+ if (! argelts[i]
+ || ! k->isPrimitive ()
+ || ! can_widen (k, paramelts[i]))
+ JvThrow (new java::lang::IllegalArgumentException);
+ size += paramelts[i]->size();
+ }
+ else
+ {
+ if (argelts[i] && ! paramelts[i]->isAssignableFrom (k))
+ JvThrow (new java::lang::IllegalArgumentException);
+ size += sizeof (jobject);
+ }
+ }
+
+ ffi_cif cif;
+ if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, parameter_types->length,
+ rtype, argtypes) != FFI_OK)
+ {
+ // FIXME: throw some kind of VirtualMachineError here.
+ }
+
+ char *values = (char *) alloca (size);
+ char *p = values;
+
+#define COPY(Where, What, Type) \
+ do { \
+ Type val = (What); \
+ memcpy ((Where), &val, sizeof (Type)); \
+ Where += sizeof (Type); \
+ } while (0)
+
+ for (int i = 0; i < parameter_types->length; ++i)
+ {
+ java::lang::Number *num = (java::lang::Number *) paramelts[i];
+ if (paramelts[i] == JvPrimClass (byte))
+ COPY (p, num->byteValue(), jbyte);
+ else if (paramelts[i] == JvPrimClass (short))
+ COPY (p, num->shortValue(), jshort);
+ else if (paramelts[i] == JvPrimClass (int))
+ COPY (p, num->intValue(), jint);
+ else if (paramelts[i] == JvPrimClass (long))
+ COPY (p, num->longValue(), jlong);
+ else if (paramelts[i] == JvPrimClass (float))
+ COPY (p, num->floatValue(), jfloat);
+ else if (paramelts[i] == JvPrimClass (double))
+ COPY (p, num->doubleValue(), jdouble);
+ else if (paramelts[i] == JvPrimClass (boolean))
+ COPY (p, ((java::lang::Boolean *) argelts[i])->booleanValue(), jboolean);
+ else if (paramelts[i] == JvPrimClass (char))
+ COPY (p, ((java::lang::Character *) argelts[i])->charValue(), jchar);
+ else
+ {
+ JvAssert (! paramelts[i]->isPrimitive());
+ COPY (p, argelts[i], jobject);
+ }
+ }
+
+ // FIXME: exception handling.
+ java::lang::Throwable *ex;
+ jdouble ret_value; // Largest possible value. Hopefully
+ // it is aligned!
+ ex = TRAMP_CALL (ffi_call (&cif, meth->ncode, &ret_value, (void *) values));
+
+ if (ex)
+ JvThrow (new InvocationTargetException (ex));
+
+ jobject r;
+#define VAL(Wrapper, Type) (new Wrapper (* (Type *) &ret_value))
+ if (return_type == JvPrimClass (byte))
+ r = VAL (java::lang::Byte, jbyte);
+ else if (return_type == JvPrimClass (short))
+ r = VAL (java::lang::Short, jshort);
+ else if (return_type == JvPrimClass (int))
+ r = VAL (java::lang::Integer, jint);
+ else if (return_type == JvPrimClass (long))
+ r = VAL (java::lang::Long, jlong);
+ else if (return_type == JvPrimClass (float))
+ r = VAL (java::lang::Float, jfloat);
+ else if (return_type == JvPrimClass (double))
+ r = VAL (java::lang::Double, jdouble);
+ else if (return_type == JvPrimClass (boolean))
+ r = VAL (java::lang::Boolean, jboolean);
+ else if (return_type == JvPrimClass (char))
+ r = VAL (java::lang::Character, jchar);
+ else if (return_type == JvPrimClass (void))
+ r = NULL;
+ else
+ {
+ JvAssert (! return_type->isPrimitive());
+ r = VAL (java::lang::Object, jobject);
+ }
+
+ return r;
+}
+
+#else /* 0 */
+
+jobject
+java::lang::reflect::Method::invoke (jobject, jobjectArray)
+{
+ JvFail ("not enabled yet");
+}
+
+#endif /* 0 */
+
+jint
+java::lang::reflect::Method::getModifiers ()
+{
+ return _Jv_FromReflectedMethod (this)->accflags;
+}
+
+jstring
+java::lang::reflect::Method::getName ()
+{
+ if (name == NULL)
+ name = _Jv_NewStringUtf8Const (_Jv_FromReflectedMethod (this)->name);
+ return name;
+}
+
+/* Internal method to set return_type and parameter_types fields. */
+
+void
+java::lang::reflect::Method::getType ()
+{
+ _Jv_Utf8Const* sig = _Jv_FromReflectedMethod (this)->signature;
+ java::lang::ClassLoader *loader = declaringClass->getClassLoader();
+ char *ptr = sig->data;
+ int numArgs = 0;
+ /* First just count the number of parameters. */
+ for (; ; ptr++)
+ {
+ switch (*ptr)
+ {
+ case 0:
+ case ')':
+ case 'V':
+ break;
+ case '[':
+ case '(':
+ continue;
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'S':
+ case 'I':
+ case 'J':
+ case 'Z':
+ numArgs++;
+ continue;
+ case 'L':
+ numArgs++;
+ do
+ ptr++;
+ while (*ptr != ';' && ptr[1] != '\0');
+ continue;
+ }
+ break;
+ }
+
+ JArray<jclass> *args = (JArray<jclass> *)
+ JvNewObjectArray (numArgs, &ClassClass, NULL);
+ jclass* argPtr = elements (args);
+ for (ptr = sig->data; *ptr != '\0'; ptr++)
+ {
+ int num_arrays = 0;
+ jclass type;
+ for (; *ptr == '['; ptr++)
+ num_arrays++;
+ switch (*ptr)
+ {
+ default:
+ return;
+ case ')':
+ argPtr = &return_type;
+ continue;
+ case '(':
+ continue;
+ case 'V':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'S':
+ case 'I':
+ case 'J':
+ case 'Z':
+ type = _Jv_FindClassFromSignature(ptr, loader);
+ break;
+ case 'L':
+ type = _Jv_FindClassFromSignature(ptr, loader);
+ do
+ ptr++;
+ while (*ptr != ';' && ptr[1] != '\0');
+ break;
+ }
+ while (--num_arrays >= 0)
+ type = _Jv_FindArrayClass (type);
+ *argPtr++ = type;
+ }
+ parameter_types = args;
+}
diff --git a/libjava/java/lang/s_atan.c b/libjava/java/lang/s_atan.c
new file mode 100644
index 00000000000..b1410ecca55
--- /dev/null
+++ b/libjava/java/lang/s_atan.c
@@ -0,0 +1,181 @@
+
+/* @(#)s_atan.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/*
+FUNCTION
+ <<atan>>, <<atanf>>---arc tangent
+
+INDEX
+ atan
+INDEX
+ atanf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double atan(double <[x]>);
+ float atanf(float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double atan(<[x]>);
+ double <[x]>;
+
+ float atanf(<[x]>);
+ float <[x]>;
+
+DESCRIPTION
+
+<<atan>> computes the inverse tangent (arc tangent) of the input value.
+
+<<atanf>> is identical to <<atan>>, save that it operates on <<floats>>.
+
+RETURNS
+@ifinfo
+<<atan>> returns a value in radians, in the range of -pi/2 to pi/2.
+@end ifinfo
+@tex
+<<atan>> returns a value in radians, in the range of $-\pi/2$ to $\pi/2$.
+@end tex
+
+PORTABILITY
+<<atan>> is ANSI C. <<atanf>> is an extension.
+
+*/
+
+/* atan(x)
+ * Method
+ * 1. Reduce x to positive by atan(x) = -atan(-x).
+ * 2. According to the integer k=4t+0.25 chopped, t=x, the argument
+ * is further reduced to one of the following intervals and the
+ * arctangent of t is evaluated by the corresponding formula:
+ *
+ * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
+ * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
+ * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
+ * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
+ * [39/16,INF] atan(x) = atan(INF) + atan( -1/t )
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double atanhi[] = {
+#else
+static double atanhi[] = {
+#endif
+ 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
+ 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
+ 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
+ 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
+};
+
+#ifdef __STDC__
+static const double atanlo[] = {
+#else
+static double atanlo[] = {
+#endif
+ 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
+ 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
+ 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
+ 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
+};
+
+#ifdef __STDC__
+static const double aT[] = {
+#else
+static double aT[] = {
+#endif
+ 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
+ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
+ 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
+ -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
+ 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */
+ -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
+ 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */
+ -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
+ 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */
+ -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
+ 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
+};
+
+#ifdef __STDC__
+ static const double
+#else
+ static double
+#endif
+one = 1.0,
+huge = 1.0e300;
+
+#ifdef __STDC__
+ double atan(double x)
+#else
+ double atan(x)
+ double x;
+#endif
+{
+ double w,s1,s2,z;
+ __int32_t ix,hx,id;
+
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x44100000) { /* if |x| >= 2^66 */
+ __uint32_t low;
+ GET_LOW_WORD(low,x);
+ if(ix>0x7ff00000||
+ (ix==0x7ff00000&&(low!=0)))
+ return x+x; /* NaN */
+ if(hx>0) return atanhi[3]+atanlo[3];
+ else return -atanhi[3]-atanlo[3];
+ } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */
+ if (ix < 0x3e200000) { /* |x| < 2^-29 */
+ if(huge+x>one) return x; /* raise inexact */
+ }
+ id = -1;
+ } else {
+ x = fabs(x);
+ if (ix < 0x3ff30000) { /* |x| < 1.1875 */
+ if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */
+ id = 0; x = (2.0*x-one)/(2.0+x);
+ } else { /* 11/16<=|x|< 19/16 */
+ id = 1; x = (x-one)/(x+one);
+ }
+ } else {
+ if (ix < 0x40038000) { /* |x| < 2.4375 */
+ id = 2; x = (x-1.5)/(one+1.5*x);
+ } else { /* 2.4375 <= |x| < 2^66 */
+ id = 3; x = -1.0/x;
+ }
+ }}
+ /* end of argument reduction */
+ z = x*x;
+ w = z*z;
+ /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+ s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
+ s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
+ if (id<0) return x - x*(s1+s2);
+ else {
+ z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+ return (hx<0)? -z:z;
+ }
+}
+
+#endif /* _DOUBLE_IS_32BITS */
diff --git a/libjava/java/lang/s_ceil.c b/libjava/java/lang/s_ceil.c
new file mode 100644
index 00000000000..1476ef821be
--- /dev/null
+++ b/libjava/java/lang/s_ceil.c
@@ -0,0 +1,80 @@
+
+/* @(#)s_ceil.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * ceil(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to ceil(x).
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double huge = 1.0e300;
+#else
+static double huge = 1.0e300;
+#endif
+
+#ifdef __STDC__
+ double ceil(double x)
+#else
+ double ceil(x)
+ double x;
+#endif
+{
+ __int32_t i0,i1,j0;
+ __uint32_t i,j;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0<0) {i0=0x80000000;i1=0;}
+ else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
+ }
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0>0) i0 += (0x00100000)>>j0;
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((__uint32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0>0) {
+ if(j0==20) i0+=1;
+ else {
+ j = i1 + (1<<(52-j0));
+ if(j<(__uint32_t)i1) i0+=1; /* got a carry */
+ i1 = j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ INSERT_WORDS(x,i0,i1);
+ return x;
+}
+
+#endif /* _DOUBLE_IS_32BITS */
diff --git a/libjava/java/lang/s_copysign.c b/libjava/java/lang/s_copysign.c
new file mode 100644
index 00000000000..bfc546db503
--- /dev/null
+++ b/libjava/java/lang/s_copysign.c
@@ -0,0 +1,82 @@
+
+/* @(#)s_copysign.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+<<copysign>>, <<copysignf>>---sign of <[y]>, magnitude of <[x]>
+
+INDEX
+ copysign
+INDEX
+ copysignf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double copysign (double <[x]>, double <[y]>);
+ float copysignf (float <[x]>, float <[y]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double copysign (<[x]>, <[y]>)
+ double <[x]>;
+ double <[y]>;
+
+ float copysignf (<[x]>, <[y]>)
+ float <[x]>;
+ float <[y]>;
+
+DESCRIPTION
+<<copysign>> constructs a number with the magnitude (absolute value)
+of its first argument, <[x]>, and the sign of its second argument,
+<[y]>.
+
+<<copysignf>> does the same thing; the two functions differ only in
+the type of their arguments and result.
+
+RETURNS
+<<copysign>> returns a <<double>> with the magnitude of
+<[x]> and the sign of <[y]>.
+<<copysignf>> returns a <<float>> with the magnitude of
+<[x]> and the sign of <[y]>.
+
+PORTABILITY
+<<copysign>> is not required by either ANSI C or the System V Interface
+Definition (Issue 2).
+
+*/
+
+/*
+ * copysign(double x, double y)
+ * copysign(x,y) returns a value with the magnitude of x and
+ * with the sign bit of y.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double copysign(double x, double y)
+#else
+ double copysign(x,y)
+ double x,y;
+#endif
+{
+ __uint32_t hx,hy;
+ GET_HIGH_WORD(hx,x);
+ GET_HIGH_WORD(hy,y);
+ SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
+ return x;
+}
+
+#endif /* _DOUBLE_IS_32BITS */
diff --git a/libjava/java/lang/s_cos.c b/libjava/java/lang/s_cos.c
new file mode 100644
index 00000000000..c4712330137
--- /dev/null
+++ b/libjava/java/lang/s_cos.c
@@ -0,0 +1,82 @@
+
+/* @(#)s_cos.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* cos(x)
+ * Return cosine function of x.
+ *
+ * kernel function:
+ * __kernel_sin ... sine function on [-pi/4,pi/4]
+ * __kernel_cos ... cosine function on [-pi/4,pi/4]
+ * __ieee754_rem_pio2 ... argument reduction routine
+ *
+ * Method.
+ * Let S,C and T denote the sin, cos and tan respectively on
+ * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ * in [-pi/4 , +pi/4], and let n = k mod 4.
+ * We have
+ *
+ * n sin(x) cos(x) tan(x)
+ * ----------------------------------------------------------
+ * 0 S C T
+ * 1 C -S -1/T
+ * 2 -S -C T
+ * 3 -C S -1/T
+ * ----------------------------------------------------------
+ *
+ * Special cases:
+ * Let trig be any of sin, cos, or tan.
+ * trig(+-INF) is NaN, with signals;
+ * trig(NaN) is that NaN;
+ *
+ * Accuracy:
+ * TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double cos(double x)
+#else
+ double cos(x)
+ double x;
+#endif
+{
+ double y[2],z=0.0;
+ __int32_t n,ix;
+
+ /* High word of x. */
+ GET_HIGH_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3fe921fb) return __kernel_cos(x,z);
+
+ /* cos(Inf or NaN) is NaN */
+ else if (ix>=0x7ff00000) return x-x;
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2(x,y);
+ switch(n&3) {
+ case 0: return __kernel_cos(y[0],y[1]);
+ case 1: return -__kernel_sin(y[0],y[1],1);
+ case 2: return -__kernel_cos(y[0],y[1]);
+ default:
+ return __kernel_sin(y[0],y[1],1);
+ }
+ }
+}
+
+#endif /* _DOUBLE_IS_32BITS */
diff --git a/libjava/java/lang/s_fabs.c b/libjava/java/lang/s_fabs.c
new file mode 100644
index 00000000000..95b871ca53a
--- /dev/null
+++ b/libjava/java/lang/s_fabs.c
@@ -0,0 +1,73 @@
+
+/* @(#)s_fabs.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+ <<fabs>>, <<fabsf>>---absolute value (magnitude)
+INDEX
+ fabs
+INDEX
+ fabsf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double fabs(double <[x]>);
+ float fabsf(float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double fabs(<[x]>)
+ double <[x]>;
+
+ float fabsf(<[x]>)
+ float <[x]>;
+
+DESCRIPTION
+<<fabs>> and <<fabsf>> calculate
+@tex
+$|x|$,
+@end tex
+the absolute value (magnitude) of the argument <[x]>, by direct
+manipulation of the bit representation of <[x]>.
+
+RETURNS
+The calculated value is returned. No errors are detected.
+
+PORTABILITY
+<<fabs>> is ANSI.
+<<fabsf>> is an extension.
+
+*/
+
+/*
+ * fabs(x) returns the absolute value of x.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double fabs(double x)
+#else
+ double fabs(x)
+ double x;
+#endif
+{
+ __uint32_t high;
+ GET_HIGH_WORD(high,x);
+ SET_HIGH_WORD(x,high&0x7fffffff);
+ return x;
+}
+
+#endif /* _DOUBLE_IS_32BITS */
diff --git a/libjava/java/lang/s_floor.c b/libjava/java/lang/s_floor.c
new file mode 100644
index 00000000000..86f73e0e136
--- /dev/null
+++ b/libjava/java/lang/s_floor.c
@@ -0,0 +1,134 @@
+
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+<<floor>>, <<floorf>>, <<ceil>>, <<ceilf>>---floor and ceiling
+INDEX
+ floor
+INDEX
+ floorf
+INDEX
+ ceil
+INDEX
+ ceilf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double floor(double <[x]>);
+ float floorf(float <[x]>);
+ double ceil(double <[x]>);
+ float ceilf(float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double floor(<[x]>)
+ double <[x]>;
+ float floorf(<[x]>)
+ float <[x]>;
+ double ceil(<[x]>)
+ double <[x]>;
+ float ceilf(<[x]>)
+ float <[x]>;
+
+DESCRIPTION
+<<floor>> and <<floorf>> find
+@tex
+$\lfloor x \rfloor$,
+@end tex
+the nearest integer less than or equal to <[x]>.
+<<ceil>> and <<ceilf>> find
+@tex
+$\lceil x\rceil$,
+@end tex
+the nearest integer greater than or equal to <[x]>.
+
+RETURNS
+<<floor>> and <<ceil>> return the integer result as a double.
+<<floorf>> and <<ceilf>> return the integer result as a float.
+
+PORTABILITY
+<<floor>> and <<ceil>> are ANSI.
+<<floorf>> and <<ceilf>> are extensions.
+
+
+*/
+
+/*
+ * floor(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to floor(x).
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double huge = 1.0e300;
+#else
+static double huge = 1.0e300;
+#endif
+
+#ifdef __STDC__
+ double floor(double x)
+#else
+ double floor(x)
+ double x;
+#endif
+{
+ __int32_t i0,i1,j0;
+ __uint32_t i,j;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0>=0) {i0=i1=0;}
+ else if(((i0&0x7fffffff)|i1)!=0)
+ { i0=0xbff00000;i1=0;}
+ }
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0<0) i0 += (0x00100000)>>j0;
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((__uint32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0<0) {
+ if(j0==20) i0+=1;
+ else {
+ j = i1+(1<<(52-j0));
+ if(j<(__uint32_t)i1) i0 +=1 ; /* got a carry */
+ i1=j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ INSERT_WORDS(x,i0,i1);
+ return x;
+}
+
+#endif /* _DOUBLE_IS_32BITS */
diff --git a/libjava/java/lang/s_rint.c b/libjava/java/lang/s_rint.c
new file mode 100644
index 00000000000..9936a49b801
--- /dev/null
+++ b/libjava/java/lang/s_rint.c
@@ -0,0 +1,87 @@
+
+/* @(#)s_rint.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * rint(x)
+ * Return x rounded to integral value according to the prevailing
+ * rounding mode.
+ * Method:
+ * Using floating addition.
+ * Exception:
+ * Inexact flag raised if x not equal to rint(x).
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+TWO52[2]={
+ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+};
+
+#ifdef __STDC__
+ double rint(double x)
+#else
+ double rint(x)
+ double x;
+#endif
+{
+ __int32_t i0,j0,sx;
+ __uint32_t i,i1;
+ double t;
+ volatile double w;
+ EXTRACT_WORDS(i0,i1,x);
+ sx = (i0>>31)&1;
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) {
+ if(((i0&0x7fffffff)|i1)==0) return x;
+ i1 |= (i0&0x0fffff);
+ i0 &= 0xfffe0000;
+ i0 |= ((i1|-i1)>>12)&0x80000;
+ SET_HIGH_WORD(x,i0);
+ w = TWO52[sx]+x;
+ t = w-TWO52[sx];
+ GET_HIGH_WORD(i0,t);
+ SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
+ return t;
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ i>>=1;
+ if(((i0&i)|i1)!=0) {
+ if(j0==19) i1 = 0x40000000; else
+ i0 = (i0&(~i))|((0x20000)>>j0);
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((__uint32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ i>>=1;
+ if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
+ }
+ INSERT_WORDS(x,i0,i1);
+ w = TWO52[sx]+x;
+ return w-TWO52[sx];
+}
+
+#endif /* _DOUBLE_IS_32BITS */
diff --git a/libjava/java/lang/s_scalbn.c b/libjava/java/lang/s_scalbn.c
new file mode 100644
index 00000000000..b06834e913f
--- /dev/null
+++ b/libjava/java/lang/s_scalbn.c
@@ -0,0 +1,104 @@
+
+/* @(#)s_scalbn.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+<<scalbn>>, <<scalbnf>>---scale by integer
+INDEX
+ scalbn
+INDEX
+ scalbnf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double scalbn(double <[x]>, int <[y]>);
+ float scalbnf(float <[x]>, int <[y]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double scalbn(<[x]>,<[y]>)
+ double <[x]>;
+ int <[y]>;
+ float scalbnf(<[x]>,<[y]>)
+ float <[x]>;
+ int <[y]>;
+
+DESCRIPTION
+<<scalbn>> and <<scalbnf>> scale <[x]> by <[n]>, returning <[x]> times
+2 to the power <[n]>. The result is computed by manipulating the
+exponent, rather than by actually performing an exponentiation or
+multiplication.
+
+RETURNS
+<[x]> times 2 to the power <[n]>.
+
+PORTABILITY
+Neither <<scalbn>> nor <<scalbnf>> is required by ANSI C or by the System V
+Interface Definition (Issue 2).
+
+*/
+
+/*
+ * scalbn (double x, int n)
+ * scalbn(x,n) returns x* 2**n computed by exponent
+ * manipulation rather than by actually performing an
+ * exponentiation or a multiplication.
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+huge = 1.0e+300,
+tiny = 1.0e-300;
+
+#ifdef __STDC__
+ double scalbn (double x, int n)
+#else
+ double scalbn (x,n)
+ double x; int n;
+#endif
+{
+ __int32_t k,hx,lx;
+ EXTRACT_WORDS(hx,lx,x);
+ k = (hx&0x7ff00000)>>20; /* extract exponent */
+ if (k==0) { /* 0 or subnormal x */
+ if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
+ x *= two54;
+ GET_HIGH_WORD(hx,x);
+ k = ((hx&0x7ff00000)>>20) - 54;
+ if (n< -50000) return tiny*x; /*underflow*/
+ }
+ if (k==0x7ff) return x+x; /* NaN or Inf */
+ k = k+n;
+ if (k > 0x7fe) return huge*copysign(huge,x); /* overflow */
+ if (k > 0) /* normal result */
+ {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
+ if (k <= -54) {
+ if (n > 50000) /* in case integer overflow in n+k */
+ return huge*copysign(huge,x); /*overflow*/
+ else return tiny*copysign(tiny,x); /*underflow*/
+ }
+ k += 54; /* subnormal result */
+ SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
+ return x*twom54;
+}
+
+#endif /* _DOUBLE_IS_32BITS */
diff --git a/libjava/java/lang/s_sin.c b/libjava/java/lang/s_sin.c
new file mode 100644
index 00000000000..28259f378fe
--- /dev/null
+++ b/libjava/java/lang/s_sin.c
@@ -0,0 +1,132 @@
+
+/* @(#)s_sin.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+ <<sin>>, <<sinf>>, <<cos>>, <<cosf>>---sine or cosine
+INDEX
+sin
+INDEX
+sinf
+INDEX
+cos
+INDEX
+cosf
+ANSI_SYNOPSIS
+ #include <math.h>
+ double sin(double <[x]>);
+ float sinf(float <[x]>);
+ double cos(double <[x]>);
+ float cosf(float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double sin(<[x]>)
+ double <[x]>;
+ float sinf(<[x]>)
+ float <[x]>;
+
+ double cos(<[x]>)
+ double <[x]>;
+ float cosf(<[x]>)
+ float <[x]>;
+
+DESCRIPTION
+ <<sin>> and <<cos>> compute (respectively) the sine and cosine
+ of the argument <[x]>. Angles are specified in radians.
+
+ <<sinf>> and <<cosf>> are identical, save that they take and
+ return <<float>> values.
+
+
+RETURNS
+ The sine or cosine of <[x]> is returned.
+
+PORTABILITY
+ <<sin>> and <<cos>> are ANSI C.
+ <<sinf>> and <<cosf>> are extensions.
+
+QUICKREF
+ sin ansi pure
+ sinf - pure
+*/
+
+/* sin(x)
+ * Return sine function of x.
+ *
+ * kernel function:
+ * __kernel_sin ... sine function on [-pi/4,pi/4]
+ * __kernel_cos ... cose function on [-pi/4,pi/4]
+ * __ieee754_rem_pio2 ... argument reduction routine
+ *
+ * Method.
+ * Let S,C and T denote the sin, cos and tan respectively on
+ * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ * in [-pi/4 , +pi/4], and let n = k mod 4.
+ * We have
+ *
+ * n sin(x) cos(x) tan(x)
+ * ----------------------------------------------------------
+ * 0 S C T
+ * 1 C -S -1/T
+ * 2 -S -C T
+ * 3 -C S -1/T
+ * ----------------------------------------------------------
+ *
+ * Special cases:
+ * Let trig be any of sin, cos, or tan.
+ * trig(+-INF) is NaN, with signals;
+ * trig(NaN) is that NaN;
+ *
+ * Accuracy:
+ * TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double sin(double x)
+#else
+ double sin(x)
+ double x;
+#endif
+{
+ double y[2],z=0.0;
+ __int32_t n,ix;
+
+ /* High word of x. */
+ GET_HIGH_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0);
+
+ /* sin(Inf or NaN) is NaN */
+ else if (ix>=0x7ff00000) return x-x;
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2(x,y);
+ switch(n&3) {
+ case 0: return __kernel_sin(y[0],y[1],1);
+ case 1: return __kernel_cos(y[0],y[1]);
+ case 2: return -__kernel_sin(y[0],y[1],1);
+ default:
+ return -__kernel_cos(y[0],y[1]);
+ }
+ }
+}
+
+#endif /* _DOUBLE_IS_32BITS */
diff --git a/libjava/java/lang/s_tan.c b/libjava/java/lang/s_tan.c
new file mode 100644
index 00000000000..2959f416e83
--- /dev/null
+++ b/libjava/java/lang/s_tan.c
@@ -0,0 +1,114 @@
+
+/* @(#)s_tan.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+
+/*
+
+FUNCTION
+ <<tan>>, <<tanf>>---tangent
+
+INDEX
+tan
+INDEX
+tanf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double tan(double <[x]>);
+ float tanf(float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double tan(<[x]>)
+ double <[x]>;
+
+ float tanf(<[x]>)
+ float <[x]>;
+
+
+DESCRIPTION
+<<tan>> computes the tangent of the argument <[x]>.
+Angles are specified in radians.
+
+<<tanf>> is identical, save that it takes and returns <<float>> values.
+
+RETURNS
+The tangent of <[x]> is returned.
+
+PORTABILITY
+<<tan>> is ANSI. <<tanf>> is an extension.
+*/
+
+/* tan(x)
+ * Return tangent function of x.
+ *
+ * kernel function:
+ * __kernel_tan ... tangent function on [-pi/4,pi/4]
+ * __ieee754_rem_pio2 ... argument reduction routine
+ *
+ * Method.
+ * Let S,C and T denote the sin, cos and tan respectively on
+ * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ * in [-pi/4 , +pi/4], and let n = k mod 4.
+ * We have
+ *
+ * n sin(x) cos(x) tan(x)
+ * ----------------------------------------------------------
+ * 0 S C T
+ * 1 C -S -1/T
+ * 2 -S -C T
+ * 3 -C S -1/T
+ * ----------------------------------------------------------
+ *
+ * Special cases:
+ * Let trig be any of sin, cos, or tan.
+ * trig(+-INF) is NaN, with signals;
+ * trig(NaN) is that NaN;
+ *
+ * Accuracy:
+ * TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double tan(double x)
+#else
+ double tan(x)
+ double x;
+#endif
+{
+ double y[2],z=0.0;
+ __int32_t n,ix;
+
+ /* High word of x. */
+ GET_HIGH_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1);
+
+ /* tan(Inf or NaN) is NaN */
+ else if (ix>=0x7ff00000) return x-x; /* NaN */
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2(x,y);
+ return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even
+ -1 -- n odd */
+ }
+}
+
+#endif /* _DOUBLE_IS_32BITS */
diff --git a/libjava/java/lang/sf_rint.c b/libjava/java/lang/sf_rint.c
new file mode 100644
index 00000000000..e4769e0dc60
--- /dev/null
+++ b/libjava/java/lang/sf_rint.c
@@ -0,0 +1,80 @@
+/* sf_rint.c -- float version of s_rint.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "fdlibm.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+TWO23[2]={
+ 8.3886080000e+06, /* 0x4b000000 */
+ -8.3886080000e+06, /* 0xcb000000 */
+};
+
+#ifdef __STDC__
+ float rintf(float x)
+#else
+ float rintf(x)
+ float x;
+#endif
+{
+ __int32_t i0,j0,sx;
+ __uint32_t i,i1;
+ float w,t;
+ GET_FLOAT_WORD(i0,x);
+ sx = (i0>>31)&1;
+ j0 = ((i0>>23)&0xff)-0x7f;
+ if(j0<23) {
+ if(j0<0) {
+ if((i0&0x7fffffff)==0) return x;
+ i1 = (i0&0x07fffff);
+ i0 &= 0xfff00000;
+ i0 |= ((i1|-i1)>>9)&0x400000;
+ SET_FLOAT_WORD(x,i0);
+ w = TWO23[sx]+x;
+ t = w-TWO23[sx];
+ GET_FLOAT_WORD(i0,t);
+ SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31));
+ return t;
+ } else {
+ i = (0x007fffff)>>j0;
+ if((i0&i)==0) return x; /* x is integral */
+ i>>=1;
+ if((i0&i)!=0) i0 = (i0&(~i))|((0x100000)>>j0);
+ }
+ } else {
+ if(j0==0x80) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ }
+ SET_FLOAT_WORD(x,i0);
+ w = TWO23[sx]+x;
+ return w-TWO23[sx];
+}
+
+#ifdef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double rint(double x)
+#else
+ double rint(x)
+ double x;
+#endif
+{
+ return (double) rintf((float) x);
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/strtod.c b/libjava/java/lang/strtod.c
new file mode 100644
index 00000000000..e0e8e74828b
--- /dev/null
+++ b/libjava/java/lang/strtod.c
@@ -0,0 +1,720 @@
+/*
+FUNCTION
+ <<strtod>>, <<strtodf>>---string to double or float
+
+INDEX
+ strtod
+INDEX
+ _strtod_r
+INDEX
+ strtodf
+
+ANSI_SYNOPSIS
+ #include <stdlib.h>
+ double strtod(const char *<[str]>, char **<[tail]>);
+ float strtodf(const char *<[str]>, char **<[tail]>);
+
+ double _strtod_r(void *<[reent]>,
+ const char *<[str]>, char **<[tail]>);
+
+TRAD_SYNOPSIS
+ #include <stdlib.h>
+ double strtod(<[str]>,<[tail]>)
+ char *<[str]>;
+ char **<[tail]>;
+
+ float strtodf(<[str]>,<[tail]>)
+ char *<[str]>;
+ char **<[tail]>;
+
+ double _strtod_r(<[reent]>,<[str]>,<[tail]>)
+ char *<[reent]>;
+ char *<[str]>;
+ char **<[tail]>;
+
+DESCRIPTION
+ The function <<strtod>> parses the character string <[str]>,
+ producing a substring which can be converted to a double
+ value. The substring converted is the longest initial
+ subsequence of <[str]>, beginning with the first
+ non-whitespace character, that has the format:
+ .[+|-]<[digits]>[.][<[digits]>][(e|E)[+|-]<[digits]>]
+ The substring contains no characters if <[str]> is empty, consists
+ entirely of whitespace, or if the first non-whitespace
+ character is something other than <<+>>, <<->>, <<.>>, or a
+ digit. If the substring is empty, no conversion is done, and
+ the value of <[str]> is stored in <<*<[tail]>>>. Otherwise,
+ the substring is converted, and a pointer to the final string
+ (which will contain at least the terminating null character of
+ <[str]>) is stored in <<*<[tail]>>>. If you want no
+ assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>.
+ <<strtodf>> is identical to <<strtod>> except for its return type.
+
+ This implementation returns the nearest machine number to the
+ input decimal string. Ties are broken by using the IEEE
+ round-even rule.
+
+ The alternate function <<_strtod_r>> is a reentrant version.
+ The extra argument <[reent]> is a pointer to a reentrancy structure.
+
+RETURNS
+ <<strtod>> returns the converted substring value, if any. If
+ no conversion could be performed, 0 is returned. If the
+ correct value is out of the range of representable values,
+ plus or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is
+ stored in errno. If the correct value would cause underflow, 0
+ is returned and <<ERANGE>> is stored in errno.
+
+Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
+<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
+*/
+
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991 by AT&T.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* Please send bug reports to
+ David M. Gay
+ AT&T Bell Laboratories, Room 2C-463
+ 600 Mountain Avenue
+ Murray Hill, NJ 07974-2070
+ U.S.A.
+ dmg@research.att.com or research!dmg
+ */
+
+#include <string.h>
+#include <float.h>
+#include <errno.h>
+#include "mprec.h"
+
+double
+_DEFUN (_strtod_r, (ptr, s00, se),
+ struct _Jv_reent *ptr _AND
+ _CONST char *s00 _AND
+ char **se)
+{
+ int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e1, esign, i, j,
+ k, nd, nd0, nf, nz, nz0, sign;
+ int digits = 0; /* Number of digits found in fraction part. */
+ long e;
+ _CONST char *s, *s0, *s1;
+ double aadj, aadj1, adj;
+ long L;
+ unsigned long y, z;
+ union double_union rv, rv0;
+
+ _Jv_Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
+ sign = nz0 = nz = 0;
+ rv.d = 0.;
+ for (s = s00;; s++)
+ switch (*s)
+ {
+ case '-':
+ sign = 1;
+ /* no break */
+ case '+':
+ if (*++s)
+ goto break2;
+ /* no break */
+ case 0:
+ s = s00;
+ goto ret;
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ continue;
+ default:
+ goto break2;
+ }
+break2:
+ if (*s == '0')
+ {
+ digits++;
+ nz0 = 1;
+ while (*++s == '0')
+ digits++;
+ if (!*s)
+ goto ret;
+ }
+ s0 = s;
+ y = z = 0;
+ for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+ {
+ digits++;
+ if (nd < 9)
+ y = 10 * y + c - '0';
+ else if (nd < 16)
+ z = 10 * z + c - '0';
+ }
+ nd0 = nd;
+ if (c == '.')
+ {
+ c = *++s;
+ if (!nd)
+ {
+ for (; c == '0'; c = *++s)
+ {
+ digits++;
+ nz++;
+ }
+ if (c > '0' && c <= '9')
+ {
+ digits++;
+ s0 = s;
+ nf += nz;
+ nz = 0;
+ goto have_dig;
+ }
+ goto dig_done;
+ }
+ for (; c >= '0' && c <= '9'; c = *++s)
+ {
+ digits++;
+ have_dig:
+ nz++;
+ if (c -= '0')
+ {
+ nf += nz;
+ for (i = 1; i < nz; i++)
+ if (nd++ < 9)
+ y *= 10;
+ else if (nd <= DBL_DIG + 1)
+ z *= 10;
+ if (nd++ < 9)
+ y = 10 * y + c;
+ else if (nd <= DBL_DIG + 1)
+ z = 10 * z + c;
+ nz = 0;
+ }
+ }
+ }
+dig_done:
+ e = 0;
+ if (c == 'e' || c == 'E')
+ {
+ if (!nd && !nz && !nz0)
+ {
+ s = s00;
+ goto ret;
+ }
+ s00 = s;
+ esign = 0;
+ switch (c = *++s)
+ {
+ case '-':
+ esign = 1;
+ case '+':
+ c = *++s;
+ }
+ if (c >= '0' && c <= '9')
+ {
+ while (c == '0')
+ c = *++s;
+ if (c > '0' && c <= '9')
+ {
+ e = c - '0';
+ s1 = s;
+ while ((c = *++s) >= '0' && c <= '9')
+ e = 10 * e + c - '0';
+ if (s - s1 > 8)
+ /* Avoid confusion from exponents
+ * so large that e might overflow.
+ */
+ e = 9999999L;
+ if (esign)
+ e = -e;
+ }
+ else
+ {
+ /* No exponent after an 'E' : that's an error. */
+ ptr->_errno = EINVAL;
+ e = 0;
+ goto ret;
+ }
+ }
+ else
+ s = s00;
+ }
+ if (!nd)
+ {
+ if (!nz && !nz0)
+ s = s00;
+ goto ret;
+ }
+ e1 = e -= nf;
+
+ /* Now we have nd0 digits, starting at s0, followed by a
+ * decimal point, followed by nd-nd0 digits. The number we're
+ * after is the integer represented by those digits times
+ * 10**e */
+
+ if (!nd0)
+ nd0 = nd;
+ k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+ rv.d = y;
+ if (k > 9)
+ rv.d = tens[k - 9] * rv.d + z;
+ bd0 = 0;
+ if (nd <= DBL_DIG
+#ifndef RND_PRODQUOT
+ && FLT_ROUNDS == 1
+#endif
+ )
+ {
+ if (!e)
+ goto ret;
+ if (e > 0)
+ {
+ if (e <= Ten_pmax)
+ {
+#ifdef VAX
+ goto vax_ovfl_check;
+#else
+ /* rv.d = */ rounded_product (rv.d, tens[e]);
+ goto ret;
+#endif
+ }
+ i = DBL_DIG - nd;
+ if (e <= Ten_pmax + i)
+ {
+ /* A fancier test would sometimes let us do
+ * this for larger i values.
+ */
+ e -= i;
+ rv.d *= tens[i];
+#ifdef VAX
+ /* VAX exponent range is so narrow we must
+ * worry about overflow here...
+ */
+ vax_ovfl_check:
+ word0 (rv) -= P * Exp_msk1;
+ /* rv.d = */ rounded_product (rv.d, tens[e]);
+ if ((word0 (rv) & Exp_mask)
+ > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P))
+ goto ovfl;
+ word0 (rv) += P * Exp_msk1;
+#else
+ /* rv.d = */ rounded_product (rv.d, tens[e]);
+#endif
+ goto ret;
+ }
+ }
+#ifndef Inaccurate_Divide
+ else if (e >= -Ten_pmax)
+ {
+ /* rv.d = */ rounded_quotient (rv.d, tens[-e]);
+ goto ret;
+ }
+#endif
+ }
+ e1 += nd - k;
+
+ /* Get starting approximation = rv.d * 10**e1 */
+
+ if (e1 > 0)
+ {
+ if ((i = e1 & 15))
+ rv.d *= tens[i];
+
+ if (e1 &= ~15)
+ {
+ if (e1 > DBL_MAX_10_EXP)
+ {
+ ovfl:
+ ptr->_errno = ERANGE;
+
+ /* Force result to IEEE infinity. */
+ word0 (rv) = Exp_mask;
+ word1 (rv) = 0;
+
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+ if (e1 >>= 4)
+ {
+ for (j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ rv.d *= bigtens[j];
+ /* The last multiplication could overflow. */
+ word0 (rv) -= P * Exp_msk1;
+ rv.d *= bigtens[j];
+ if ((z = word0 (rv) & Exp_mask)
+ > Exp_msk1 * (DBL_MAX_EXP + Bias - P))
+ goto ovfl;
+ if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P))
+ {
+ /* set to largest number */
+ /* (Can't trust DBL_MAX) */
+ word0 (rv) = Big0;
+#ifndef _DOUBLE_IS_32BITS
+ word1 (rv) = Big1;
+#endif
+ }
+ else
+ word0 (rv) += P * Exp_msk1;
+ }
+
+ }
+ }
+ else if (e1 < 0)
+ {
+ e1 = -e1;
+ if ((i = e1 & 15))
+ rv.d /= tens[i];
+ if (e1 &= ~15)
+ {
+ e1 >>= 4;
+ if (e1 >= 1 << n_bigtens)
+ goto undfl;
+ for (j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ rv.d *= tinytens[j];
+ /* The last multiplication could underflow. */
+ rv0.d = rv.d;
+ rv.d *= tinytens[j];
+ if (!rv.d)
+ {
+ rv.d = 2. * rv0.d;
+ rv.d *= tinytens[j];
+ if (!rv.d)
+ {
+ undfl:
+ rv.d = 0.;
+ ptr->_errno = ERANGE;
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+#ifndef _DOUBLE_IS_32BITS
+ word0 (rv) = Tiny0;
+ word1 (rv) = Tiny1;
+#else
+ word0 (rv) = Tiny1;
+#endif
+ /* The refinement below will clean
+ * this approximation up.
+ */
+ }
+ }
+ }
+
+ /* Now the hard part -- adjusting rv to the correct value.*/
+
+ /* Put digits into bd: true value = bd * 10^e */
+
+ bd0 = s2b (ptr, s0, nd0, nd, y);
+
+ for (;;)
+ {
+ bd = Balloc (ptr, bd0->_k);
+ Bcopy (bd, bd0);
+ bb = d2b (ptr, rv.d, &bbe, &bbbits); /* rv.d = bb * 2^bbe */
+ bs = i2b (ptr, 1);
+
+ if (e >= 0)
+ {
+ bb2 = bb5 = 0;
+ bd2 = bd5 = e;
+ }
+ else
+ {
+ bb2 = bb5 = -e;
+ bd2 = bd5 = 0;
+ }
+ if (bbe >= 0)
+ bb2 += bbe;
+ else
+ bd2 -= bbe;
+ bs2 = bb2;
+#ifdef Sudden_Underflow
+#ifdef IBM
+ j = 1 + 4 * P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
+#else
+ j = P + 1 - bbbits;
+#endif
+#else
+ i = bbe + bbbits - 1; /* logb(rv.d) */
+ if (i < Emin) /* denormal */
+ j = bbe + (P - Emin);
+ else
+ j = P + 1 - bbbits;
+#endif
+ bb2 += j;
+ bd2 += j;
+ i = bb2 < bd2 ? bb2 : bd2;
+ if (i > bs2)
+ i = bs2;
+ if (i > 0)
+ {
+ bb2 -= i;
+ bd2 -= i;
+ bs2 -= i;
+ }
+ if (bb5 > 0)
+ {
+ bs = pow5mult (ptr, bs, bb5);
+ bb1 = mult (ptr, bs, bb);
+ Bfree (ptr, bb);
+ bb = bb1;
+ }
+ if (bb2 > 0)
+ bb = lshift (ptr, bb, bb2);
+ if (bd5 > 0)
+ bd = pow5mult (ptr, bd, bd5);
+ if (bd2 > 0)
+ bd = lshift (ptr, bd, bd2);
+ if (bs2 > 0)
+ bs = lshift (ptr, bs, bs2);
+ delta = diff (ptr, bb, bd);
+ dsign = delta->_sign;
+ delta->_sign = 0;
+ i = cmp (delta, bs);
+ if (i < 0)
+ {
+ /* Error is less than half an ulp -- check for
+ * special case of mantissa a power of two.
+ */
+ if (dsign || word1 (rv) || word0 (rv) & Bndry_mask)
+ break;
+ delta = lshift (ptr, delta, Log2P);
+ if (cmp (delta, bs) > 0)
+ goto drop_down;
+ break;
+ }
+ if (i == 0)
+ {
+ /* exactly half-way between */
+ if (dsign)
+ {
+ if ((word0 (rv) & Bndry_mask1) == Bndry_mask1
+ && word1 (rv) == 0xffffffff)
+ {
+ /*boundary case -- increment exponent*/
+ word0 (rv) = (word0 (rv) & Exp_mask)
+ + Exp_msk1
+#ifdef IBM
+ | Exp_msk1 >> 4
+#endif
+ ;
+#ifndef _DOUBLE_IS_32BITS
+ word1 (rv) = 0;
+#endif
+ break;
+ }
+ }
+ else if (!(word0 (rv) & Bndry_mask) && !word1 (rv))
+ {
+ drop_down:
+ /* boundary case -- decrement exponent */
+#ifdef Sudden_Underflow
+ L = word0 (rv) & Exp_mask;
+#ifdef IBM
+ if (L < Exp_msk1)
+#else
+ if (L <= Exp_msk1)
+#endif
+ goto undfl;
+ L -= Exp_msk1;
+#else
+ L = (word0 (rv) & Exp_mask) - Exp_msk1;
+#endif
+ word0 (rv) = L | Bndry_mask1;
+#ifndef _DOUBLE_IS_32BITS
+ word1 (rv) = 0xffffffff;
+#endif
+#ifdef IBM
+ goto cont;
+#else
+ break;
+#endif
+ }
+#ifndef ROUND_BIASED
+ if (!(word1 (rv) & LSB))
+ break;
+#endif
+ if (dsign)
+ rv.d += ulp (rv.d);
+#ifndef ROUND_BIASED
+ else
+ {
+ rv.d -= ulp (rv.d);
+#ifndef Sudden_Underflow
+ if (!rv.d)
+ goto undfl;
+#endif
+ }
+#endif
+ break;
+ }
+ if ((aadj = ratio (delta, bs)) <= 2.)
+ {
+ if (dsign)
+ aadj = aadj1 = 1.;
+ else if (word1 (rv) || word0 (rv) & Bndry_mask)
+ {
+#ifndef Sudden_Underflow
+ if (word1 (rv) == Tiny1 && !word0 (rv))
+ goto undfl;
+#endif
+ aadj = 1.;
+ aadj1 = -1.;
+ }
+ else
+ {
+ /* special case -- power of FLT_RADIX to be */
+ /* rounded down... */
+
+ if (aadj < 2. / FLT_RADIX)
+ aadj = 1. / FLT_RADIX;
+ else
+ aadj *= 0.5;
+ aadj1 = -aadj;
+ }
+ }
+ else
+ {
+ aadj *= 0.5;
+ aadj1 = dsign ? aadj : -aadj;
+#ifdef Check_FLT_ROUNDS
+ switch (FLT_ROUNDS)
+ {
+ case 2: /* towards +infinity */
+ aadj1 -= 0.5;
+ break;
+ case 0: /* towards 0 */
+ case 3: /* towards -infinity */
+ aadj1 += 0.5;
+ }
+#else
+ if (FLT_ROUNDS == 0)
+ aadj1 += 0.5;
+#endif
+ }
+ y = word0 (rv) & Exp_mask;
+
+ /* Check for overflow */
+
+ if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1))
+ {
+ rv0.d = rv.d;
+ word0 (rv) -= P * Exp_msk1;
+ adj = aadj1 * ulp (rv.d);
+ rv.d += adj;
+ if ((word0 (rv) & Exp_mask) >=
+ Exp_msk1 * (DBL_MAX_EXP + Bias - P))
+ {
+ if (word0 (rv0) == Big0 && word1 (rv0) == Big1)
+ goto ovfl;
+#ifdef _DOUBLE_IS_32BITS
+ word0 (rv) = Big1;
+#else
+ word0 (rv) = Big0;
+ word1 (rv) = Big1;
+#endif
+ goto cont;
+ }
+ else
+ word0 (rv) += P * Exp_msk1;
+ }
+ else
+ {
+#ifdef Sudden_Underflow
+ if ((word0 (rv) & Exp_mask) <= P * Exp_msk1)
+ {
+ rv0.d = rv.d;
+ word0 (rv) += P * Exp_msk1;
+ adj = aadj1 * ulp (rv.d);
+ rv.d += adj;
+#ifdef IBM
+ if ((word0 (rv) & Exp_mask) < P * Exp_msk1)
+#else
+ if ((word0 (rv) & Exp_mask) <= P * Exp_msk1)
+#endif
+ {
+ if (word0 (rv0) == Tiny0
+ && word1 (rv0) == Tiny1)
+ goto undfl;
+ word0 (rv) = Tiny0;
+ word1 (rv) = Tiny1;
+ goto cont;
+ }
+ else
+ word0 (rv) -= P * Exp_msk1;
+ }
+ else
+ {
+ adj = aadj1 * ulp (rv.d);
+ rv.d += adj;
+ }
+#else
+ /* Compute adj so that the IEEE rounding rules will
+ * correctly round rv.d + adj in some half-way cases.
+ * If rv.d * ulp(rv.d) is denormalized (i.e.,
+ * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
+ * trouble from bits lost to denormalization;
+ * example: 1.2e-307 .
+ */
+ if (y <= (P - 1) * Exp_msk1 && aadj >= 1.)
+ {
+ aadj1 = (double) (int) (aadj + 0.5);
+ if (!dsign)
+ aadj1 = -aadj1;
+ }
+ adj = aadj1 * ulp (rv.d);
+ rv.d += adj;
+#endif
+ }
+ z = word0 (rv) & Exp_mask;
+ if (y == z)
+ {
+ /* Can we stop now? */
+ L = aadj;
+ aadj -= L;
+ /* The tolerances below are conservative. */
+ if (dsign || word1 (rv) || word0 (rv) & Bndry_mask)
+ {
+ if (aadj < .4999999 || aadj > .5000001)
+ break;
+ }
+ else if (aadj < .4999999 / FLT_RADIX)
+ break;
+ }
+ cont:
+ Bfree (ptr, bb);
+ Bfree (ptr, bd);
+ Bfree (ptr, bs);
+ Bfree (ptr, delta);
+ }
+retfree:
+ Bfree (ptr, bb);
+ Bfree (ptr, bd);
+ Bfree (ptr, bs);
+ Bfree (ptr, bd0);
+ Bfree (ptr, delta);
+ret:
+ if (se)
+ *se = (char *) s;
+ if (digits == 0)
+ ptr->_errno = EINVAL;
+ return sign ? -rv.d : rv.d;
+}
+
diff --git a/libjava/java/lang/w_acos.c b/libjava/java/lang/w_acos.c
new file mode 100644
index 00000000000..c9ca99c4041
--- /dev/null
+++ b/libjava/java/lang/w_acos.c
@@ -0,0 +1,118 @@
+
+/* @(#)w_acos.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+ <<acos>>, <<acosf>>---arc cosine
+
+INDEX
+ acos
+INDEX
+ acosf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double acos(double <[x]>);
+ float acosf(float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double acos(<[x]>)
+ double <[x]>;
+
+ float acosf(<[x]>)
+ float <[x]>;
+
+
+
+DESCRIPTION
+
+ <<acos>> computes the inverse cosine (arc cosine) of the input value.
+ Arguments to <<acos>> must be in the range @minus{}1 to 1.
+
+ <<acosf>> is identical to <<acos>>, except that it performs
+ its calculations on <<floats>>.
+
+RETURNS
+ @ifinfo
+ <<acos>> and <<acosf>> return values in radians, in the range of 0 to pi.
+ @end ifinfo
+ @tex
+ <<acos>> and <<acosf>> return values in radians, in the range of <<0>> to $\pi$.
+ @end tex
+
+ If <[x]> is not between @minus{}1 and 1, the returned value is NaN
+ (not a number) the global variable <<errno>> is set to <<EDOM>>, and a
+ <<DOMAIN error>> message is sent as standard error output.
+
+ You can modify error handling for these functions using <<matherr>>.
+
+
+QUICKREF ANSI SVID POSIX RENTRANT
+ acos y,y,y,m
+ acosf n,n,n,m
+
+MATHREF
+ acos, [-1,1], acos(arg),,,
+ acos, NAN, arg,DOMAIN,EDOM
+
+MATHREF
+ acosf, [-1,1], acosf(arg),,,
+ acosf, NAN, argf,DOMAIN,EDOM
+
+*/
+
+/*
+ * wrap_acos(x)
+ */
+
+#include "fdlibm.h"
+#include <errno.h>
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double acos(double x) /* wrapper acos */
+#else
+ double acos(x) /* wrapper acos */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_acos(x);
+#else
+ double z;
+ struct exception exc;
+ z = __ieee754_acos(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ if(fabs(x)>1.0) {
+ /* acos(|x|>1) */
+ exc.type = DOMAIN;
+ exc.name = "acos";
+ exc.err = 0;
+ exc.arg1 = exc.arg2 = x;
+ exc.retval = 0.0;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ } else
+ return z;
+#endif
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/w_asin.c b/libjava/java/lang/w_asin.c
new file mode 100644
index 00000000000..f6cb271d392
--- /dev/null
+++ b/libjava/java/lang/w_asin.c
@@ -0,0 +1,121 @@
+
+/* @(#)w_asin.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/*
+FUNCTION
+ <<asin>>, <<asinf>>---arc sine
+
+INDEX
+ asin
+INDEX
+ asinf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double asin(double <[x]>);
+ float asinf(float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double asin(<[x]>)
+ double <[x]>;
+
+ float asinf(<[x]>)
+ float <[x]>;
+
+
+DESCRIPTION
+
+<<asin>> computes the inverse sine (arc sine) of the argument <[x]>.
+Arguments to <<asin>> must be in the range @minus{}1 to 1.
+
+<<asinf>> is identical to <<asin>>, other than taking and
+returning floats.
+
+You can modify error handling for these routines using <<matherr>>.
+
+RETURNS
+@ifinfo
+<<asin>> returns values in radians, in the range of -pi/2 to pi/2.
+@end ifinfo
+@tex
+<<asin>> returns values in radians, in the range of $-\pi/2$ to $\pi/2$.
+@end tex
+
+If <[x]> is not in the range @minus{}1 to 1, <<asin>> and <<asinf>>
+return NaN (not a number), set the global variable <<errno>> to
+<<EDOM>>, and issue a <<DOMAIN error>> message.
+
+You can change this error treatment using <<matherr>>.
+
+QUICKREF ANSI SVID POSIX RENTRANT
+ asin y,y,y,m
+ asinf n,n,n,m
+
+MATHREF
+ asin, -1<=arg<=1, asin(arg),,,
+ asin, NAN, arg,EDOM, DOMAIN
+
+MATHREF
+ asinf, -1<=arg<=1, asin(arg),,,
+ asinf, NAN, arg,EDOM, DOMAIN
+
+
+*/
+
+/*
+ * wrapper asin(x)
+ */
+
+
+#include "fdlibm.h"
+#include <errno.h>
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double asin(double x) /* wrapper asin */
+#else
+ double asin(x) /* wrapper asin */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_asin(x);
+#else
+ double z;
+ struct exception exc;
+ z = __ieee754_asin(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ if(fabs(x)>1.0) {
+ /* asin(|x|>1) */
+ exc.type = DOMAIN;
+ exc.name = "asin";
+ exc.err = 0;
+ exc.arg1 = exc.arg2 = x;
+ exc.retval = 0.0;
+ if(_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ } else
+ return z;
+#endif
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/w_atan2.c b/libjava/java/lang/w_atan2.c
new file mode 100644
index 00000000000..91742c72b91
--- /dev/null
+++ b/libjava/java/lang/w_atan2.c
@@ -0,0 +1,117 @@
+
+/* @(#)w_atan2.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/*
+FUNCTION
+ <<atan2>>, <<atan2f>>---arc tangent of y/x
+
+INDEX
+ atan2
+INDEX
+ atan2f
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double atan2(double <[y]>,double <[x]>);
+ float atan2f(float <[y]>,float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double atan2(<[y]>,<[x]>);
+ double <[y]>;
+ double <[x]>;
+
+ float atan2f(<[y]>,<[x]>);
+ float <[y]>;
+ float <[x]>;
+
+DESCRIPTION
+
+<<atan2>> computes the inverse tangent (arc tangent) of <[y]>/<[x]>.
+<<atan2>> produces the correct result even for angles near
+@ifinfo
+pi/2 or -pi/2
+@end ifinfo
+@tex
+$\pi/2$ or $-\pi/2$
+@end tex
+(that is, when <[x]> is near 0).
+
+<<atan2f>> is identical to <<atan2>>, save that it takes and returns
+<<float>>.
+
+RETURNS
+<<atan2>> and <<atan2f>> return a value in radians, in the range of
+@ifinfo
+-pi to pi.
+@end ifinfo
+@tex
+$-\pi$ to $\pi$.
+@end tex
+
+If both <[x]> and <[y]> are 0.0, <<atan2>> causes a <<DOMAIN>> error.
+
+You can modify error handling for these functions using <<matherr>>.
+
+PORTABILITY
+<<atan2>> is ANSI C. <<atan2f>> is an extension.
+
+
+*/
+
+/*
+ * wrapper atan2(y,x)
+ */
+
+#include "fdlibm.h"
+#include <errno.h>
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double atan2(double y, double x) /* wrapper atan2 */
+#else
+ double atan2(y,x) /* wrapper atan2 */
+ double y,x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_atan2(y,x);
+#else
+ double z;
+ struct exception exc;
+ z = __ieee754_atan2(y,x);
+ if(_LIB_VERSION == _IEEE_||isnan(x)||isnan(y)) return z;
+ if(x==0.0&&y==0.0) {
+ /* atan2(+-0,+-0) */
+ exc.arg1 = y;
+ exc.arg2 = x;
+ exc.type = DOMAIN;
+ exc.name = "atan2";
+ exc.err = 0;
+ exc.retval = 0.0;
+ if(_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ } else
+ return z;
+#endif
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/w_exp.c b/libjava/java/lang/w_exp.c
new file mode 100644
index 00000000000..ae792a84642
--- /dev/null
+++ b/libjava/java/lang/w_exp.c
@@ -0,0 +1,136 @@
+
+/* @(#)w_exp.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+ <<exp>>, <<expf>>---exponential
+INDEX
+ exp
+INDEX
+ expf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double exp(double <[x]>);
+ float expf(float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double exp(<[x]>);
+ double <[x]>;
+
+ float expf(<[x]>);
+ float <[x]>;
+
+DESCRIPTION
+ <<exp>> and <<expf>> calculate the exponential of <[x]>, that is,
+ @ifinfo
+ e raised to the power <[x]> (where e
+ @end ifinfo
+ @tex
+ $e^x$ (where $e$
+ @end tex
+ is the base of the natural system of logarithms, approximately 2.71828).
+
+ You can use the (non-ANSI) function <<matherr>> to specify
+ error handling for these functions.
+
+RETURNS
+ On success, <<exp>> and <<expf>> return the calculated value.
+ If the result underflows, the returned value is <<0>>. If the
+ result overflows, the returned value is <<HUGE_VAL>>. In
+ either case, <<errno>> is set to <<ERANGE>>.
+
+PORTABILITY
+ <<exp>> is ANSI C. <<expf>> is an extension.
+
+*/
+
+/*
+ * wrapper exp(x)
+ */
+
+#include "fdlibm.h"
+#include <errno.h>
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
+u_threshold= -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */
+
+#ifdef __STDC__
+ double exp(double x) /* wrapper exp */
+#else
+ double exp(x) /* wrapper exp */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_exp(x);
+#else
+ double z;
+ struct exception exc;
+ z = __ieee754_exp(x);
+ if(_LIB_VERSION == _IEEE_) return z;
+ if(finite(x)) {
+ if(x>o_threshold) {
+ /* exp(finite) overflow */
+#ifndef HUGE_VAL
+#define HUGE_VAL inf
+ double inf = 0.0;
+
+ SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */
+#endif
+ exc.type = OVERFLOW;
+ exc.name = "exp";
+ exc.err = 0;
+ exc.arg1 = exc.arg2 = x;
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = HUGE;
+ else
+ exc.retval = HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ } else if(x<u_threshold) {
+ /* exp(finite) underflow */
+ exc.type = UNDERFLOW;
+ exc.name = "exp";
+ exc.err = 0;
+ exc.arg1 = exc.arg2 = x;
+ exc.retval = 0.0;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ }
+ }
+ return z;
+#endif
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/w_fmod.c b/libjava/java/lang/w_fmod.c
new file mode 100644
index 00000000000..b6b36cb76ab
--- /dev/null
+++ b/libjava/java/lang/w_fmod.c
@@ -0,0 +1,107 @@
+
+/* @(#)w_fmod.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+<<fmod>>, <<fmodf>>---floating-point remainder (modulo)
+
+INDEX
+fmod
+INDEX
+fmodf
+
+ANSI_SYNOPSIS
+#include <math.h>
+double fmod(double <[x]>, double <[y]>)
+float fmodf(float <[x]>, float <[y]>)
+
+TRAD_SYNOPSIS
+#include <math.h>
+double fmod(<[x]>, <[y]>)
+double (<[x]>, <[y]>);
+
+float fmodf(<[x]>, <[y]>)
+float (<[x]>, <[y]>);
+
+DESCRIPTION
+The <<fmod>> and <<fmodf>> functions compute the floating-point
+remainder of <[x]>/<[y]> (<[x]> modulo <[y]>).
+
+RETURNS
+The <<fmod>> function returns the value
+@ifinfo
+<[x]>-<[i]>*<[y]>,
+@end ifinfo
+@tex
+$x-i\times y$,
+@end tex
+for the largest integer <[i]> such that, if <[y]> is nonzero, the
+result has the same sign as <[x]> and magnitude less than the
+magnitude of <[y]>.
+
+<<fmod(<[x]>,0)>> returns NaN, and sets <<errno>> to <<EDOM>>.
+
+You can modify error treatment for these functions using <<matherr>>.
+
+PORTABILITY
+<<fmod>> is ANSI C. <<fmodf>> is an extension.
+*/
+
+/*
+ * wrapper fmod(x,y)
+ */
+
+#include "fdlibm.h"
+#include <errno.h>
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double fmod(double x, double y) /* wrapper fmod */
+#else
+ double fmod(x,y) /* wrapper fmod */
+ double x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_fmod(x,y);
+#else
+ double z;
+ struct exception exc;
+ z = __ieee754_fmod(x,y);
+ if(_LIB_VERSION == _IEEE_ ||isnan(y)||isnan(x)) return z;
+ if(y==0.0) {
+ /* fmod(x,0) */
+ exc.type = DOMAIN;
+ exc.name = "fmod";
+ exc.arg1 = x;
+ exc.arg2 = y;
+ exc.err = 0;
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = x;
+ else
+ exc.retval = 0.0/0.0;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ } else
+ return z;
+#endif
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/w_log.c b/libjava/java/lang/w_log.c
new file mode 100644
index 00000000000..dcc8b9762ec
--- /dev/null
+++ b/libjava/java/lang/w_log.c
@@ -0,0 +1,115 @@
+
+/* @(#)w_log.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+ <<log>>, <<logf>>---natural logarithms
+
+INDEX
+ log
+INDEX
+ logf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double log(double <[x]>);
+ float logf(float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double log(<[x]>);
+ double <[x]>;
+
+ float logf(<[x]>);
+ float <[x]>;
+
+DESCRIPTION
+Return the natural logarithm of <[x]>, that is, its logarithm base e
+(where e is the base of the natural system of logarithms, 2.71828@dots{}).
+<<log>> and <<logf>> are identical save for the return and argument types.
+
+You can use the (non-ANSI) function <<matherr>> to specify error
+handling for these functions.
+
+RETURNS
+Normally, returns the calculated value. When <[x]> is zero, the
+returned value is <<-HUGE_VAL>> and <<errno>> is set to <<ERANGE>>.
+When <[x]> is negative, the returned value is <<-HUGE_VAL>> and
+<<errno>> is set to <<EDOM>>. You can control the error behavior via
+<<matherr>>.
+
+PORTABILITY
+<<log>> is ANSI, <<logf>> is an extension.
+*/
+
+/*
+ * wrapper log(x)
+ */
+
+#include "fdlibm.h"
+#include <errno.h>
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double log(double x) /* wrapper log */
+#else
+ double log(x) /* wrapper log */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_log(x);
+#else
+ double z;
+ struct exception exc;
+ z = __ieee754_log(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x) || x > 0.0) return z;
+#ifndef HUGE_VAL
+#define HUGE_VAL inf
+ double inf = 0.0;
+
+ SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */
+#endif
+ exc.name = "log";
+ exc.err = 0;
+ exc.arg1 = x;
+ exc.arg2 = x;
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if(x==0.0) {
+ /* log(0) */
+ exc.type = SING;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ } else {
+ /* log(x<0) */
+ exc.type = DOMAIN;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+#endif
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/lang/w_pow.c b/libjava/java/lang/w_pow.c
new file mode 100644
index 00000000000..3df099a1714
--- /dev/null
+++ b/libjava/java/lang/w_pow.c
@@ -0,0 +1,231 @@
+
+
+/* @(#)w_pow.c 5.2 93/10/01 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+ <<pow>>, <<powf>>---x to the power y
+INDEX
+ pow
+INDEX
+ powf
+
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double pow(double <[x]>, double <[y]>);
+ float pow(float <[x]>, float <[y]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double pow(<[x]>, <[y]>);
+ double <[x]>, <[y]>;
+
+ float pow(<[x]>, <[y]>);
+ float <[x]>, <[y]>;
+
+DESCRIPTION
+ <<pow>> and <<powf>> calculate <[x]> raised to the exp1.0nt <[y]>.
+ @tex
+ (That is, $x^y$.)
+ @end tex
+
+RETURNS
+ On success, <<pow>> and <<powf>> return the value calculated.
+
+ When the argument values would produce overflow, <<pow>>
+ returns <<HUGE_VAL>> and set <<errno>> to <<ERANGE>>. If the
+ argument <[x]> passed to <<pow>> or <<powf>> is a negative
+ noninteger, and <[y]> is also not an integer, then <<errno>>
+ is set to <<EDOM>>. If <[x]> and <[y]> are both 0, then
+ <<pow>> and <<powf>> return <<1>>.
+
+ You can modify error handling for these functions using <<matherr>>.
+
+PORTABILITY
+ <<pow>> is ANSI C. <<powf>> is an extension. */
+
+/*
+ * wrapper pow(x,y) return x**y
+ */
+
+#include "fdlibm.h"
+#include <errno.h>
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double pow(double x, double y) /* wrapper pow */
+#else
+ double pow(x,y) /* wrapper pow */
+ double x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_pow(x,y);
+#else
+ double z;
+#ifndef HUGE_VAL
+#define HUGE_VAL inf
+ double inf = 0.0;
+
+ SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */
+#endif
+ struct exception exc;
+ z=__ieee754_pow(x,y);
+ if(_LIB_VERSION == _IEEE_|| isnan(y)) return z;
+ if(isnan(x)) {
+ if(y==0.0) {
+ /* pow(NaN,0.0) */
+ /* error only if _LIB_VERSION == _SVID_ & _XOPEN_ */
+ exc.type = DOMAIN;
+ exc.name = "pow";
+ exc.err = 0;
+ exc.arg1 = x;
+ exc.arg2 = y;
+ exc.retval = x;
+ if (_LIB_VERSION == _IEEE_ ||
+ _LIB_VERSION == _POSIX_) exc.retval = 1.0;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ } else
+ return z;
+ }
+ if(x==0.0){
+ if(y==0.0) {
+ /* pow(0.0,0.0) */
+ /* error only if _LIB_VERSION == _SVID_ */
+ exc.type = DOMAIN;
+ exc.name = "pow";
+ exc.err = 0;
+ exc.arg1 = x;
+ exc.arg2 = y;
+ exc.retval = 0.0;
+ if (_LIB_VERSION != _SVID_) exc.retval = 1.0;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ }
+ if(finite(y)&&y<0.0) {
+ /* 0**neg */
+ exc.type = DOMAIN;
+ exc.name = "pow";
+ exc.err = 0;
+ exc.arg1 = x;
+ exc.arg2 = y;
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = 0.0;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ }
+ return z;
+ }
+ if(!finite(z)) {
+ if(finite(x)&&finite(y)) {
+ if(isnan(z)) {
+ /* neg**non-integral */
+ exc.type = DOMAIN;
+ exc.name = "pow";
+ exc.err = 0;
+ exc.arg1 = x;
+ exc.arg2 = y;
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = 0.0;
+ else
+ exc.retval = 0.0/0.0; /* X/Open allow NaN */
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ } else {
+ /* pow(x,y) overflow */
+ exc.type = OVERFLOW;
+ exc.name = "pow";
+ exc.err = 0;
+ exc.arg1 = x;
+ exc.arg2 = y;
+ if (_LIB_VERSION == _SVID_) {
+ exc.retval = HUGE;
+ y *= 0.5;
+ if(x<0.0&&rint(y)!=y) exc.retval = -HUGE;
+ } else {
+ exc.retval = HUGE_VAL;
+ y *= 0.5;
+ if(x<0.0&&rint(y)!=y) exc.retval = -HUGE_VAL;
+ }
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ }
+ }
+ }
+ if(z==0.0&&finite(x)&&finite(y)) {
+ /* pow(x,y) underflow */
+ exc.type = UNDERFLOW;
+ exc.name = "pow";
+ exc.err = 0;
+ exc.arg1 = x;
+ exc.arg2 = y;
+ exc.retval = 0.0;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ }
+ return z;
+#endif
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libjava/java/lang/w_remainder.c b/libjava/java/lang/w_remainder.c
new file mode 100644
index 00000000000..a06be0e7b30
--- /dev/null
+++ b/libjava/java/lang/w_remainder.c
@@ -0,0 +1,119 @@
+
+/* @(#)w_remainder.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+<<rint>>, <<rintf>>, <<remainder>>, <<remainderf>>---round and remainder
+INDEX
+ rint
+INDEX
+ rintf
+INDEX
+ remainder
+INDEX
+ remainderf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double rint(double <[x]>);
+ float rintf(float <[x]>);
+ double remainder(double <[x]>, double <[y]>);
+ float remainderf(float <[x]>, float <[y]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double rint(<[x]>)
+ double <[x]>;
+ float rintf(<[x]>)
+ float <[x]>;
+ double remainder(<[x]>,<[y]>)
+ double <[x]>, <[y]>;
+ float remainderf(<[x]>,<[y]>)
+ float <[x]>, <[y]>;
+
+DESCRIPTION
+<<rint>> and <<rintf>> returns their argument rounded to the nearest
+integer. <<remainder>> and <<remainderf>> find the remainder of
+<[x]>/<[y]>; this value is in the range -<[y]>/2 .. +<[y]>/2.
+
+RETURNS
+<<rint>> and <<remainder>> return the integer result as a double.
+
+PORTABILITY
+<<rint>> and <<remainder>> are System V release 4. <<rintf>> and
+<<remainderf>> are extensions.
+
+*/
+
+/*
+ * wrapper remainder(x,p)
+ */
+
+#include "fdlibm.h"
+#include <errno.h>
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double remainder(double x, double y) /* wrapper remainder */
+#else
+ double remainder(x,y) /* wrapper remainder */
+ double x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_remainder(x,y);
+#else
+ double z;
+ struct exception exc;
+ z = __ieee754_remainder(x,y);
+ if(_LIB_VERSION == _IEEE_ || isnan(y)) return z;
+ if(y==0.0) {
+ /* remainder(x,0) */
+ exc.type = DOMAIN;
+ exc.name = "remainder";
+ exc.err = 0;
+ exc.arg1 = x;
+ exc.arg2 = y;
+ exc.retval = 0.0/0.0;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ } else
+ return z;
+#endif
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libjava/java/lang/w_sqrt.c b/libjava/java/lang/w_sqrt.c
new file mode 100644
index 00000000000..23a793ce74a
--- /dev/null
+++ b/libjava/java/lang/w_sqrt.c
@@ -0,0 +1,93 @@
+
+/* @(#)w_sqrt.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+ <<sqrt>>, <<sqrtf>>---positive square root
+
+INDEX
+ sqrt
+INDEX
+ sqrtf
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double sqrt(double <[x]>);
+ float sqrtf(float <[x]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double sqrt(<[x]>);
+ float sqrtf(<[x]>);
+
+DESCRIPTION
+ <<sqrt>> computes the positive square root of the argument.
+ You can modify error handling for this function with
+ <<matherr>>.
+
+RETURNS
+ On success, the square root is returned. If <[x]> is real and
+ positive, then the result is positive. If <[x]> is real and
+ negative, the global value <<errno>> is set to <<EDOM>> (domain error).
+
+
+PORTABILITY
+ <<sqrt>> is ANSI C. <<sqrtf>> is an extension.
+*/
+
+/*
+ * wrapper sqrt(x)
+ */
+
+#include "fdlibm.h"
+#include <errno.h>
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+ double sqrt(double x) /* wrapper sqrt */
+#else
+ double sqrt(x) /* wrapper sqrt */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_sqrt(x);
+#else
+ struct exception exc;
+ double z;
+ z = __ieee754_sqrt(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ if(x<0.0) {
+ exc.type = DOMAIN;
+ exc.name = "sqrt";
+ exc.err = 0;
+ exc.arg1 = exc.arg2 = x;
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = 0.0;
+ else
+ exc.retval = 0.0/0.0;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ if (exc.err != 0)
+ errno = exc.err;
+ return exc.retval;
+ } else
+ return z;
+#endif
+}
+
+#endif /* defined(_DOUBLE_IS_32BITS) */
diff --git a/libjava/java/net/BindException.java b/libjava/java/net/BindException.java
new file mode 100644
index 00000000000..5f7b4919b40
--- /dev/null
+++ b/libjava/java/net/BindException.java
@@ -0,0 +1,35 @@
+// BindException.java
+
+/* 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 java.net;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public class BindException extends SocketException
+{
+ public BindException()
+ {
+ super();
+ }
+
+ public BindException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/net/ConnectException.java b/libjava/java/net/ConnectException.java
new file mode 100644
index 00000000000..d4d3a48cc68
--- /dev/null
+++ b/libjava/java/net/ConnectException.java
@@ -0,0 +1,35 @@
+// ConnectException.java
+
+/* 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 java.net;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public class ConnectException extends SocketException
+{
+ public ConnectException()
+ {
+ super();
+ }
+
+ public ConnectException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/net/ContentHandler.java b/libjava/java/net/ContentHandler.java
new file mode 100644
index 00000000000..fd2e3b12f48
--- /dev/null
+++ b/libjava/java/net/ContentHandler.java
@@ -0,0 +1,29 @@
+// ContentHandler.java - Superclass of classes that read from a URLConnection.
+
+/* 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 java.net;
+
+import java.io.IOException;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public abstract class ContentHandler
+{
+ public abstract Object getContent(URLConnection urlc) throws IOException;
+}
diff --git a/libjava/java/net/ContentHandlerFactory.java b/libjava/java/net/ContentHandlerFactory.java
new file mode 100644
index 00000000000..ee6dcffdb69
--- /dev/null
+++ b/libjava/java/net/ContentHandlerFactory.java
@@ -0,0 +1,27 @@
+// ContentHandlerFactory.java - Abstract Content Handler factory.
+
+/* 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 java.net;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public abstract interface ContentHandlerFactory
+{
+ public ContentHandler createContentHandler(String mimetype);
+}
diff --git a/libjava/java/net/FileNameMap.java b/libjava/java/net/FileNameMap.java
new file mode 100644
index 00000000000..24e8ef894f1
--- /dev/null
+++ b/libjava/java/net/FileNameMap.java
@@ -0,0 +1,27 @@
+// FileNameMap.java - Abstract interface to map from a File Name to MIME type.
+
+/* 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 java.net;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public abstract interface FileNameMap
+{
+ public String getContentTypeFor(String fileName);
+}
diff --git a/libjava/java/net/HttpURLConnection.java b/libjava/java/net/HttpURLConnection.java
new file mode 100644
index 00000000000..8b05b73ebbb
--- /dev/null
+++ b/libjava/java/net/HttpURLConnection.java
@@ -0,0 +1,174 @@
+// HttpURLConnection.java - Subclass of communications links using
+// Hypertext Transfer 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 java.net;
+
+import java.io.*;
+
+/**
+ * @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: Believed complete and correct.
+ */
+
+public abstract class HttpURLConnection extends URLConnection
+{
+ /* HTTP Success Response Codes */
+ public static final int HTTP_OK = 200;
+ public static final int HTTP_CREATED = 201;
+ public static final int HTTP_ACCEPTED = 202;
+ public static final int HTTP_NOT_AUTHORITATIVE = 203;
+ public static final int HTTP_NO_CONTENT = 204;
+ public static final int HTTP_RESET = 205;
+ public static final int HTTP_PARTIAL = 206;
+
+ /* HTTP Redirection Response Codes */
+ public static final int HTTP_MULT_CHOICE = 300;
+ public static final int HTTP_MOVED_PERM = 301;
+ public static final int HTTP_MOVED_TEMP = 302;
+ public static final int HTTP_SEE_OTHER = 303;
+ public static final int HTTP_NOT_MODIFIED = 304;
+ public static final int HTTP_USE_PROXY = 305;
+
+ /* HTTP Client Error Response Codes */
+ public static final int HTTP_BAD_REQUEST = 400;
+ public static final int HTTP_UNAUTHORIZED = 401;
+ public static final int HTTP_PAYMENT_REQUIRED = 402;
+ public static final int HTTP_FORBIDDEN = 403;
+ public static final int HTTP_NOT_FOUND = 404;
+ public static final int HTTP_BAD_METHOD = 405;
+ public static final int HTTP_NOT_ACCEPTABLE = 406;
+ public static final int HTTP_PROXY_AUTH = 407;
+ public static final int HTTP_CLIENT_TIMEOUT = 408;
+ public static final int HTTP_CONFLICT = 409;
+ public static final int HTTP_GONE = 410;
+ public static final int HTTP_LENGTH_REQUIRED = 411;
+ public static final int HTTP_PRECON_FAILED = 412;
+ public static final int HTTP_ENTITY_TOO_LARGE = 413;
+ public static final int HTTP_REQ_TOO_LONG = 414;
+ public static final int HTTP_UNSUPPORTED_TYPE = 415;
+
+ /* HTTP Server Error Response Codes */
+ public static final int HTTP_SERVER_ERROR = 500;
+ public static final int HTTP_INTERNAL_ERROR = 501;
+ public static final int HTTP_BAD_GATEWAY = 502;
+ public static final int HTTP_UNAVAILABLE = 503;
+ public static final int HTTP_GATEWAY_TIMEOUT = 504;
+ public static final int HTTP_VERSION = 505;
+
+ protected String method = "GET";
+ protected int responseCode = -1;
+ protected String responseMessage;
+
+ static boolean followRedirects = true;
+
+ protected HttpURLConnection(URL url)
+ {
+ super(url);
+ }
+
+ public abstract void disconnect();
+
+ public abstract boolean usingProxy();
+
+ public static void setFollowRedirects(boolean set)
+ {
+ // Throw an exception if an extant security mgr precludes
+ // setting the factory.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkSetFactory();
+
+ followRedirects = set;
+ }
+
+ public static boolean getFollowRedirects()
+ {
+ return followRedirects;
+ }
+
+ public void setRequestMethod(String method) throws ProtocolException
+ {
+ if (connected)
+ throw new ProtocolException("Already connected");
+
+ if (method.equals("GET") || method.equals("POST") ||
+ method.equals("HEAD") || method.equals("OPTIONS") ||
+ method.equals("PUT") || method.equals("DELETE") ||
+ method.equals("TRACE"))
+ this.method = method;
+ else
+ throw new ProtocolException("Invalid HTTP request method");
+ }
+
+ public String getRequestMethod()
+ {
+ return method;
+ }
+
+ public int getResponseCode() throws IOException
+ {
+ getResponseVals();
+ return responseCode;
+ }
+
+ public String getResponseMessage() throws IOException
+ {
+ getResponseVals();
+ return responseMessage;
+ }
+
+ private void getResponseVals() throws IOException
+ {
+ // Response is the first header received from the connection.
+ String respField = getHeaderField(0);
+ if (! respField.startsWith("HTTP/"))
+ {
+ // Set to default values on failure.
+ responseCode = -1;
+ responseMessage = null;
+ return;
+ }
+
+ int firstSpc, nextSpc;
+ firstSpc = respField.indexOf(' ');
+ nextSpc = respField.indexOf(' ', firstSpc + 1);
+ responseMessage = respField.substring(nextSpc + 1);
+ String codeStr = respField.substring(firstSpc + 1, nextSpc);
+ try
+ {
+ responseCode = Integer.parseInt(codeStr);
+ }
+ catch (NumberFormatException e)
+ {
+ // Set to default values on failure.
+ responseCode = -1;
+ responseMessage = null;
+ }
+ if (responseCode == HTTP_NOT_FOUND)
+ throw new FileNotFoundException(url.toString());
+ else if (responseCode >= 400)
+ throw new IOException(url.toString() + " " + respField);
+ }
+
+ // TODO12: public Permission getPermission() throws IOException
+ // {
+ // }
+
+ // TODO12: public InputStream getErrorStream()
+ // {
+ // }
+}
diff --git a/libjava/java/net/InetAddress.java b/libjava/java/net/InetAddress.java
new file mode 100644
index 00000000000..baf5153e933
--- /dev/null
+++ b/libjava/java/net/InetAddress.java
@@ -0,0 +1,255 @@
+// INetAddress.java -- An Internet Protocol (IP) address.
+
+/* 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.net;
+
+/**
+ * @author Per Bothner
+ * @date January 6, 1999.
+ */
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * (The latter turns out to have some errors ...)
+ * Status: Believed complete and correct.
+ */
+
+public final class InetAddress
+{
+ String hostname;
+ byte[] address;
+
+ InetAddress (byte[] address, String hostname)
+ {
+ this.address = address;
+ this.hostname = hostname;
+ }
+
+ public boolean isMulticastAddress ()
+ {
+ int len = address.length;
+ if (len == 4)
+ return (address[0] & 0xF0) == 0xE0;
+ if (len == 16)
+ return address[0] == (byte) 0xFF;
+ return false;
+ }
+
+ public String getHostName ()
+ {
+ if (hostname == null)
+ lookup (null, this, false);
+ return hostname;
+ }
+
+ public byte[] getAddress ()
+ {
+ // An experiment shows that JDK1.2 returns a different byte array each
+ // time. This makes sense, in terms of security.
+ return (byte[]) address.clone();
+ }
+
+ /* Helper function due to a CNI limitation. */
+ private static InetAddress[] allocArray (int count)
+ {
+ return new InetAddress[count];
+ }
+
+ /* Helper function due to a CNI limitation. */
+ private static SecurityException checkConnect (String hostname)
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s == null)
+ return null;
+ try
+ {
+ s.checkConnect(hostname, -1);
+ return null;
+ }
+ catch (SecurityException ex)
+ {
+ return ex;
+ }
+ }
+
+ public String getHostAddress ()
+ {
+ StringBuffer sbuf = new StringBuffer(40);
+ int len = address.length;
+ int i = 0;
+ if (len == 16)
+ { // An IPv6 address.
+ for (; ; i += 2)
+ {
+ if (i >= 16)
+ return sbuf.toString();
+ int x = ((address[i] & 0xFF) << 8) | (address[i+1] & 0xFF);
+ boolean empty = sbuf.length() == 0;
+ if (empty)
+ {
+ if (i == 10 && x == 0xFFFF)
+ { // IPv4-mapped IPv6 address.
+ sbuf.append(":FFFF:");
+ break; // Continue as IPv4 address;
+ }
+ else if (i == 12)
+ { // IPv4-compatible IPv6 address.
+ sbuf.append(':');
+ break; // Continue as IPv4 address.
+ }
+ else if (i > 0)
+ sbuf.append("::");
+ }
+ else
+ sbuf.append(':');
+ if (x != 0 || i >= 14)
+ sbuf.append(Integer.toHexString(x).toUpperCase());
+ }
+ }
+ for ( ; ; )
+ {
+ sbuf.append(address[i] & 0xFF);
+ i++;
+ if (i == len)
+ break;
+ sbuf.append('.');
+ }
+ return sbuf.toString();
+ }
+
+ public int hashCode()
+ {
+ // There hashing algorithm is not specified, but a simple experiment
+ // shows that it is equal to the address, as a 32-bit big-endian integer.
+ int hash = 0;
+ int len = address.length;
+ int i = len > 4 ? len - 4 : 0;
+ for ( ; i < len; i++)
+ hash = (hash << 8) | (address[i] & 0xFF);
+ return hash;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (obj == null || ! (obj instanceof InetAddress))
+ return false;
+ // "The Java Class Libraries" 2nd edition says "If a machine has
+ // multiple names instances of InetAddress for different name of
+ // that same machine are not equal. This is because they have
+ // different host names." This violates the description in the
+ // JDK 1.2 API documentation. A little experiementation
+ // shows that the latter is correct.
+ byte[] addr1 = address;
+ byte[] addr2 = ((InetAddress) obj).address;
+ if (addr1.length != addr2.length)
+ return false;
+ for (int i = addr1.length; --i >= 0; )
+ if (addr1[i] != addr2[i])
+ return false;
+ return true;
+ }
+
+ public String toString()
+ {
+ return getHostName()+'/'+getHostAddress();
+ }
+
+ /** If host is a valid numeric IP address, return the numeric address.
+ * Otherwise, return null. */
+ private static native byte[] aton (String host);
+
+ private static native InetAddress[] lookup
+ (String hostname, InetAddress addr, boolean all);
+
+ public static InetAddress getByName (String host)
+ throws UnknownHostException
+ {
+ if (host == null)
+ return getLocalHost();
+ byte[] address = aton(host);
+ if (address != null)
+ return new InetAddress(address, null);
+ InetAddress iaddr = new InetAddress(null, null);
+ lookup(host, iaddr, false);
+ return iaddr;
+ }
+
+ public static InetAddress[] getAllByName (String host)
+ throws UnknownHostException
+ {
+ byte[] address = aton(host);
+ if (address != null)
+ {
+ InetAddress[] result = new InetAddress[1];
+ result[0] = new InetAddress(address, null);
+ return result;
+ }
+ return lookup(host, null, true);
+ }
+
+ private static final byte[] localhostAddress = { 127, 0, 0, 1 };
+
+ private static native String getLocalHostname ();
+
+ private static InetAddress localhost = null;
+
+ public static InetAddress getLocalHost() throws UnknownHostException
+ {
+ SecurityManager s = System.getSecurityManager();
+ // Experimentation shows that JDK1.2 does cache the result.
+ // However, if there is a security manager, and the cached result
+ // is other than "localhost", we need to check again.
+ if (localhost == null
+ || (s != null && localhost.address != localhostAddress))
+ getLocalHost(s);
+ return localhost;
+ }
+
+ private static synchronized void getLocalHost(SecurityManager s)
+ throws UnknownHostException
+ {
+ // Check the localhost cache again, now that we've synchronized.
+ if (s == null && localhost != null)
+ return;
+ String hostname = getLocalHostname();
+ if (s != null)
+ {
+ // "The Java Class Libraries" suggests that if the security
+ // manager disallows getting the local host name, then
+ // we use the loopback host.
+ // However, the JDK 1.2 API claims to throw SecurityException,
+ // which seems to suggest SecurityException is *not* caught.
+ // In this case, experimentation shows that former is correct.
+ try
+ {
+ // This is wrong, if the name returned from getLocalHostname()
+ // is not a fully qualified name. FIXME.
+ s.checkConnect(hostname, -1);
+ }
+ catch (SecurityException ex)
+ {
+ hostname = null;
+ }
+ }
+ if (hostname != null)
+ {
+ try
+ {
+ localhost = getByName(hostname);
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+ if (localhost == null)
+ localhost = new InetAddress (localhostAddress, "localhost");
+ }
+}
diff --git a/libjava/java/net/MalformedURLException.java b/libjava/java/net/MalformedURLException.java
new file mode 100644
index 00000000000..a5a8db586b2
--- /dev/null
+++ b/libjava/java/net/MalformedURLException.java
@@ -0,0 +1,35 @@
+// MalformedURLException.java
+
+/* 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 java.net;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public class MalformedURLException extends java.io.IOException
+{
+ public MalformedURLException()
+ {
+ super();
+ }
+
+ public MalformedURLException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/net/NoRouteToHostException.java b/libjava/java/net/NoRouteToHostException.java
new file mode 100644
index 00000000000..dc01688ab3f
--- /dev/null
+++ b/libjava/java/net/NoRouteToHostException.java
@@ -0,0 +1,35 @@
+// NoRouteToHostException.java
+
+/* 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 java.net;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public class NoRouteToHostException extends SocketException
+{
+ public NoRouteToHostException()
+ {
+ super();
+ }
+
+ public NoRouteToHostException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/net/PlainSocketImpl.java b/libjava/java/net/PlainSocketImpl.java
new file mode 100644
index 00000000000..5bc2caef042
--- /dev/null
+++ b/libjava/java/net/PlainSocketImpl.java
@@ -0,0 +1,64 @@
+// natClass.cc - Implementation of java.lang.Class native methods.
+
+/* 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.net;
+import java.io.*;
+
+class PlainSocketImpl extends SocketImpl
+{
+ int fnum = -1;
+
+ protected native void create (boolean stream) throws IOException;
+
+ protected void connect (String host, int port) throws IOException
+ {
+ connect(InetAddress.getByName(host), port);
+ }
+
+ protected native void connect (InetAddress host, int port)
+ throws IOException;
+
+ protected native void bind (InetAddress host, int port) throws IOException;
+
+ protected native void listen (int backlog) throws IOException;
+
+ private native void accept (PlainSocketImpl s) throws IOException;
+ protected void accept (SocketImpl s) throws IOException
+ {
+ accept((PlainSocketImpl) s);
+ }
+
+ private InputStream in;
+ private OutputStream out;
+
+ protected InputStream getInputStream() throws IOException
+ {
+ if (in == null)
+ in = new FileInputStream (fd);
+ return in;
+ }
+
+ protected OutputStream getOutputStream() throws IOException
+ {
+ if (out == null)
+ out = new FileOutputStream (fd);
+ return out;
+ }
+
+ protected int available () throws IOException
+ {
+ return in.available();
+ }
+
+ protected void close () throws IOException
+ {
+ fd.close();
+ }
+}
diff --git a/libjava/java/net/ProtocolException.java b/libjava/java/net/ProtocolException.java
new file mode 100644
index 00000000000..f7db6852edd
--- /dev/null
+++ b/libjava/java/net/ProtocolException.java
@@ -0,0 +1,35 @@
+// ProtocolException.java
+
+/* 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 java.net;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public class ProtocolException extends java.io.IOException
+{
+ public ProtocolException()
+ {
+ super();
+ }
+
+ public ProtocolException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/net/ServerSocket.java b/libjava/java/net/ServerSocket.java
new file mode 100644
index 00000000000..e4b50693e75
--- /dev/null
+++ b/libjava/java/net/ServerSocket.java
@@ -0,0 +1,105 @@
+// Socket.java
+
+/* 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. */
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date January 6, 1999.
+ */
+
+/** Written using on-line Java Platform 1.2 API Specification.
+ * Status: I believe all methods are implemented, but many
+ * of them just throw an exception.
+ */
+
+package java.net;
+import java.io.*;
+
+public class ServerSocket
+{
+ static SocketImplFactory factory;
+ SocketImpl impl;
+
+ public ServerSocket (int port)
+ throws java.io.IOException
+ {
+ this(port, 5);
+ }
+
+ public ServerSocket (int port, int backlog)
+ throws java.io.IOException
+ {
+ this(port, backlog, InetAddress.getLocalHost());
+ }
+
+ public ServerSocket (int port, int backlog, InetAddress bindAddr)
+ throws java.io.IOException
+ {
+ if (factory == null)
+ this.impl = new PlainSocketImpl();
+ else
+ this.impl = factory.createSocketImpl();
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkListen(port);
+ impl.create(true);
+ impl.bind(bindAddr, port);
+ impl.listen(backlog);
+ }
+
+ public InetAddress getInetAddress()
+ {
+ return impl.getInetAddress();
+ }
+
+ public int getLocalPort()
+ {
+ return impl.getLocalPort();
+ }
+
+ public Socket accept () throws IOException
+ {
+ Socket s = new Socket(Socket.factory == null ? new PlainSocketImpl()
+ : Socket.factory.createSocketImpl());
+ implAccept (s);
+ return s;
+ }
+
+ protected final void implAccept (Socket s) throws IOException
+ {
+ impl.accept(s.impl);
+ }
+
+ public void close () throws IOException
+ {
+ impl.close();
+ }
+
+ public void setSoTimeout (int timeout) throws SocketException
+ {
+ throw new InternalError("ServerSocket.setSoTimeout not implemented");
+ }
+
+ public int getSoTimeout () throws SocketException
+ {
+ throw new InternalError("ServerSocket.getSoTimeout not implemented");
+ }
+
+ public String toString ()
+ {
+ return impl.toString();
+ }
+
+ public static void setSocketImplFactory (SocketImplFactory fac)
+ throws IOException
+ {
+ factory = fac;
+ }
+
+}
diff --git a/libjava/java/net/Socket.java b/libjava/java/net/Socket.java
new file mode 100644
index 00000000000..8c027d9f88f
--- /dev/null
+++ b/libjava/java/net/Socket.java
@@ -0,0 +1,209 @@
+// Socket.java
+
+/* 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. */
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date January 6, 1999.
+ */
+
+/** Written using on-line Java Platform 1.2 API Specification.
+ * Status: I believe all methods are implemented, but many
+ * of them just throw an exception.
+ */
+
+package java.net;
+import java.io.*;
+
+public class Socket
+{
+ static SocketImplFactory factory;
+ SocketImpl impl;
+
+ protected Socket ()
+ {
+ }
+
+ protected Socket (SocketImpl impl) throws SocketException
+ {
+ this.impl = impl;
+ }
+
+ public Socket (String host, int port)
+ throws UnknownHostException, IOException
+ {
+ this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl());
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkConnect(host, port);
+ impl.create(true);
+ impl.connect(host, port);
+ }
+
+ public Socket (InetAddress address, int port)
+ throws IOException
+ {
+ this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl());
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkConnect(address.getHostName(), port);
+ impl.create(true);
+ impl.connect(address, port);
+ }
+
+ public Socket (String host, int port,
+ InetAddress localAddr, int localPort) throws IOException
+ {
+ this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl());
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkConnect(host, port);
+ impl.create(true);
+ impl.bind(localAddr, localPort);
+ impl.connect(host, port);
+ }
+
+ public Socket (InetAddress address, int port,
+ InetAddress localAddr, int localPort) throws IOException
+ {
+ this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl());
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkConnect(address.getHostName(), port);
+ impl.create(true);
+ impl.bind(localAddr, localPort);
+ impl.connect(address, port);
+ }
+
+ /**
+ * @deprecated Use DatagramSocket instead for UDP transport.
+ */
+ public Socket (String host, int port, boolean stream) throws IOException
+ {
+ impl = factory == null ? new PlainSocketImpl()
+ : factory.createSocketImpl();
+ impl.create(stream);
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkConnect(host, port);
+ impl.connect(host, port);
+ }
+
+ /**
+ * @deprecated Use DatagramSocket instead for UDP transport.
+ */
+ public Socket (InetAddress host, int port, boolean stream) throws IOException
+ {
+ impl = factory == null ? new PlainSocketImpl()
+ : factory.createSocketImpl();
+ impl.create(stream);
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkConnect(host.getHostName(), port);
+ impl.connect(host, port);
+ }
+
+ public InetAddress getInetAddress ()
+ {
+ return impl.getInetAddress();
+ }
+
+ public InetAddress getLocalAddress ()
+ {
+ // There doesn't seem to be any way to implement this
+ // using a (generic) SocketImpl ... What am I missing?
+ throw new InternalError("Socket.getLocalAddres not implemented");
+ }
+
+ public int getPort ()
+ {
+ return impl.getPort();
+ }
+
+ public int getLocalPort ()
+ {
+ return impl.getLocalPort();
+ }
+
+ public InputStream getInputStream () throws IOException
+ {
+ return impl.getInputStream();
+ }
+
+ public OutputStream getOutputStream () throws IOException
+ {
+ return impl.getOutputStream();
+ }
+
+ public void setTcpNoDelay (boolean on) throws SocketException
+ {
+ throw new InternalError("Socket.setTcpNoDelay not implemented");
+ }
+
+ public boolean getTcpNoDelay() throws SocketException
+ {
+ throw new InternalError("Socket.getTcpNoDelay not implemented");
+ }
+
+ public void setSoLinger(boolean on, int linger) throws SocketException
+ {
+ throw new InternalError("Socket.setSoLinger not implemented");
+ }
+
+ public boolean getSoLinger() throws SocketException
+ {
+ throw new InternalError("Socket.getSoLinger not implemented");
+ }
+
+ public void setSoTimeout (int timeout) throws SocketException
+ {
+ throw new InternalError("Socket.setSoTimeout not implemented");
+ }
+
+ public int getSoTimeout () throws SocketException
+ {
+ throw new InternalError("Socket.getSoTimeout not implemented");
+ }
+
+ public void setSendBufferSize (int size) throws SocketException
+ {
+ throw new InternalError("Socket.setSendBufferSize not implemented");
+ }
+
+ public int getSendBufferSize () throws SocketException
+ {
+ throw new InternalError("Socket.getSendBufferSize not implemented");
+ }
+
+ public void setReceiveBufferSize (int size) throws SocketException
+ {
+ throw new InternalError("Socket.setReceiveBufferSize not implemented");
+ }
+
+ public int getReceiveBufferSize () throws SocketException
+ {
+ throw new InternalError("Socket.getReceiveBufferSize not implemented");
+ }
+
+ public void close () throws IOException
+ {
+ impl.close();
+ }
+
+ public String toString ()
+ {
+ return impl.toString();
+ }
+
+ public static void setSocketImplFactory (SocketImplFactory fac)
+ throws IOException
+ {
+ factory = fac;
+ }
+}
diff --git a/libjava/java/net/SocketException.java b/libjava/java/net/SocketException.java
new file mode 100644
index 00000000000..24a50ef3f75
--- /dev/null
+++ b/libjava/java/net/SocketException.java
@@ -0,0 +1,33 @@
+// SocketException.java - Base class for networking 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.net;
+
+/**
+ * @author Per Bothner
+ * @date January 6, 1999.
+ */
+
+/** Written using on-line Java Platform 1.2 API Specification.
+ * Believed complete and correct.
+ */
+
+public class SocketException extends java.io.IOException
+{
+ public SocketException ()
+ {
+ super();
+ }
+
+ public SocketException (String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/java/net/SocketImpl.java b/libjava/java/net/SocketImpl.java
new file mode 100644
index 00000000000..5ad311811d8
--- /dev/null
+++ b/libjava/java/net/SocketImpl.java
@@ -0,0 +1,70 @@
+// SocketImpl.java - Abstract socket implementation.
+
+/* 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 java.net;
+import java.io.*;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date January 6, 1999.
+ */
+
+/** Written using on-line Java Platform 1.2 API Specification.
+ * Believed complete and correct, except for implementation of toString.
+ */
+
+public abstract class SocketImpl
+{
+ protected InetAddress address;
+
+ protected FileDescriptor fd;
+
+ protected int localport;
+
+ protected int port;
+
+ public SocketImpl ()
+ {
+ }
+
+ protected abstract void create (boolean stream) throws IOException;
+
+ protected abstract void connect (String host, int port) throws IOException;
+
+ protected abstract void connect (InetAddress host, int port)
+ throws IOException;
+
+ protected abstract void bind (InetAddress host, int port) throws IOException;
+
+ protected abstract void listen (int backlog) throws IOException;
+
+ protected abstract void accept (SocketImpl s) throws IOException;
+
+ protected abstract InputStream getInputStream() throws IOException;
+
+ protected abstract OutputStream getOutputStream() throws IOException;
+
+ protected abstract int available () throws IOException;
+
+ protected abstract void close () throws IOException;
+
+ protected FileDescriptor getFileDescriptor () { return fd; }
+
+ protected InetAddress getInetAddress () { return address; }
+
+ protected int getPort () { return port; }
+
+ protected int getLocalPort () { return localport; }
+
+ public String toString ()
+ {
+ return super.toString(); // FIXME
+ }
+}
diff --git a/libjava/java/net/SocketImplFactory.java b/libjava/java/net/SocketImplFactory.java
new file mode 100644
index 00000000000..7631ab8fd1f
--- /dev/null
+++ b/libjava/java/net/SocketImplFactory.java
@@ -0,0 +1,25 @@
+// SocketImplFactory.java - Abstract socket implementation factory.
+
+/* 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 java.net;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date January 6, 1999.
+ */
+
+/** Written using on-line Java Platform 1.2 API Specification.
+ * Status: Believed complete and correct.
+ */
+
+public abstract interface SocketImplFactory
+{
+ public SocketImpl createSocketImpl ();
+}
diff --git a/libjava/java/net/URL.java b/libjava/java/net/URL.java
new file mode 100644
index 00000000000..da56f49dc2d
--- /dev/null
+++ b/libjava/java/net/URL.java
@@ -0,0 +1,341 @@
+// URL.java - A Uniform Resource Locator.
+
+/* 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 java.net;
+
+import java.io.*;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 4, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public final class URL implements Serializable
+{
+ private String protocol;
+ private String host;
+ private int port;
+ private String file;
+ private String ref;
+ private URLStreamHandler handler;
+ private static Hashtable handlers = new Hashtable();
+ private static URLStreamHandlerFactory factory;
+
+ public URL(String protocol, String host, int port, String file)
+ throws MalformedURLException
+ {
+ this(protocol, host, port, file, null);
+ }
+
+ public URL(String protocol, String host, String file)
+ throws MalformedURLException
+ {
+ this(protocol, host, -1, file, null);
+ }
+
+ // JDK1.2
+ public URL(String protocol, String host, int port, String file,
+ URLStreamHandler handler) throws MalformedURLException
+ {
+ if (protocol == null)
+ throw new MalformedURLException("null protocol");
+ this.protocol = protocol;
+
+ if (handler != null)
+ {
+ // TODO12: Need SecurityManager.checkPermission and
+ // TODO12: java.net.NetPermission from JDK 1.2 to be implemented.
+ // Throw an exception if an extant security mgr precludes
+ // specifying a StreamHandler.
+ //
+ // SecurityManager s = System.getSecurityManager();
+ // if (s != null)
+ // s.checkPermission(NetPermission("specifyStreamHandler"));
+
+ this.handler = handler;
+ }
+ else
+ this.handler = setURLStreamHandler(protocol);
+
+ if (this.handler == null)
+ throw new MalformedURLException("Handler for protocol not found");
+
+ this.host = host;
+
+ this.port = port;
+
+ int hashAt = file.indexOf('#');
+ if (hashAt < 0)
+ {
+ this.file = file;
+ this.ref = null;
+ }
+ else
+ {
+ this.file = file.substring(0, hashAt);
+ this.ref = file.substring(hashAt + 1);
+ }
+ }
+
+ public URL(String spec) throws MalformedURLException
+ {
+ this((URL) null, spec, (URLStreamHandler) null);
+ }
+
+ public URL(URL context, String spec) throws MalformedURLException
+ {
+ this(context, spec, (URLStreamHandler) null);
+ }
+
+ // JDK1.2
+ public URL(URL context, String spec, URLStreamHandler handler)
+ throws MalformedURLException
+ {
+ /* A protocol is defined by the doc as the substring before a ':'
+ * as long as the ':' occurs before any '/'.
+ *
+ * If context is null, then spec must be an absolute URL.
+ *
+ * The relative URL need not specify all the components of a URL.
+ * If the protocol, host name, or port number is missing, the value
+ * is inherited from the context. A bare file component is appended
+ * to the context's file. The optional anchor is not inherited.
+ */
+
+ int colon;
+ int slash;
+ if ((colon = spec.indexOf(':')) > 0 &&
+ (colon < (slash = spec.indexOf('/')) || slash < 0))
+ {
+ // Protocol specified in spec string.
+ protocol = spec.substring(0, colon);
+ if (context != null && context.protocol == protocol)
+ {
+ // The 1.2 doc specifically says these are copied to the new URL.
+ host = context.host;
+ port = context.port;
+ file = context.file;
+ }
+ }
+ else if (context != null)
+ {
+ // Protocol NOT specified in spec string.
+ // Use context fields (except ref) as a foundation for relative URLs.
+ colon = -1;
+ protocol = context.protocol;
+ host = context.host;
+ port = context.port;
+ file = context.file;
+ }
+ else // Protocol NOT specified in spec. and no context available.
+ throw new
+ MalformedURLException("Absolute URL required with null context");
+
+ if (handler != null)
+ {
+ // TODO12: Need SecurityManager.checkPermission and
+ // TODO12: java.net.NetPermission from JDK 1.2 to be implemented.
+ // Throw an exception if an extant security mgr precludes
+ // specifying a StreamHandler.
+ //
+ // SecurityManager s = System.getSecurityManager();
+ // if (s != null)
+ // s.checkPermission(NetPermission("specifyStreamHandler"));
+
+ this.handler = handler;
+ }
+ else
+ this.handler = setURLStreamHandler(protocol);
+
+ if (this.handler == null)
+ throw new MalformedURLException("Handler for protocol not found");
+
+ // JDK 1.2 doc for parseURL specifically states that any '#' ref
+ // is to be excluded by passing the 'limit' as the indexOf the '#'
+ // if one exists, otherwise pass the end of the string.
+ int hashAt = spec.indexOf('#', colon + 1);
+ this.handler.parseURL(this, spec, colon + 1,
+ hashAt < 0 ? spec.length() : hashAt);
+ if (hashAt >= 0)
+ ref = spec.substring(hashAt + 1);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj == null || ! (obj instanceof URL))
+ return false;
+
+ URL uObj = (URL) obj;
+ if (protocol != uObj.protocol || host != uObj.host || port != uObj.port ||
+ file != uObj.file || ref != uObj.ref)
+ return false;
+
+ return true;
+ }
+
+ public final Object getContent() throws IOException
+ {
+ return openConnection().getContent();
+ }
+
+ public String getFile()
+ {
+ return file;
+ }
+
+ public String getHost()
+ {
+ return host;
+ }
+
+ public int getPort()
+ {
+ return port;
+ }
+
+ public String getProtocol()
+ {
+ return protocol;
+ }
+
+ public String getRef()
+ {
+ return ref;
+ }
+
+ public int hashCode()
+ {
+ // JCL book says this is computed using (only) the hashcodes of the
+ // protocol, host and file fields. Empirical evidence indicates this
+ // is probably XOR.
+ return (protocol.hashCode() ^ host.hashCode() ^ file.hashCode());
+ }
+
+ public URLConnection openConnection() throws IOException
+ {
+ return handler.openConnection(this);
+ }
+
+ public final InputStream openStream() throws IOException
+ {
+ return openConnection().getInputStream();
+ }
+
+ public boolean sameFile(URL other)
+ {
+ if (other == null || protocol != other.protocol || host != other.host ||
+ port != other.port || file != other.file)
+ return false;
+
+ return true;
+ }
+
+ protected void set(String protocol, String host, int port, String file,
+ String ref)
+ {
+ // TBD: Theoretically, a poorly written StreamHandler could pass an
+ // invalid protocol. It will cause the handler to be set to null
+ // thus overriding a valid handler. Callers of this method should
+ // be aware of this.
+ this.handler = setURLStreamHandler(protocol);
+ this.protocol = protocol;
+ this.port = port;
+ this.host = host;
+ this.file = file;
+ this.ref = ref;
+ }
+
+ public static synchronized void
+ setURLStreamHandlerFactory(URLStreamHandlerFactory fac)
+ {
+ if (factory != null)
+ throw new Error("URLStreamHandlerFactory already set");
+
+ // Throw an exception if an extant security mgr precludes
+ // setting the factory.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkSetFactory();
+ factory = fac;
+ }
+
+ public String toExternalForm()
+ {
+ // Identical to toString().
+ return handler.toExternalForm(this);
+ }
+
+ public String toString()
+ {
+ // Identical to toExternalForm().
+ return handler.toExternalForm(this);
+ }
+
+ private URLStreamHandler setURLStreamHandler(String protocol)
+ {
+ URLStreamHandler handler;
+
+ // See if a handler has been cached for this protocol.
+ if ((handler = (URLStreamHandler) handlers.get(protocol)) != null)
+ return handler;
+
+ // If a non-default factory has been set, use it to find the protocol.
+ if (factory != null)
+ handler = factory.createURLStreamHandler(protocol);
+
+ // Non-default factory may have returned null or a factory wasn't set.
+ // Use the default search algorithm to find a handler for this protocol.
+ if (handler == null)
+ {
+ // Get the list of packages to check and append our default handler
+ // to it, along with the JDK specified default as a last resort.
+ // Except in very unusual environments the JDK specified one shouldn't
+ // ever be needed (or available).
+ String propVal = System.getProperty("java.protocol.handler.pkgs");
+ propVal = (propVal == null) ? "" : (propVal + "|");
+ propVal = propVal + "gnu.gcj.protocol|sun.net.www.protocol";
+
+ StringTokenizer pkgPrefix = new StringTokenizer(propVal, "|");
+ do
+ {
+ String facName = pkgPrefix.nextToken() + "." + protocol +
+ ".Handler";
+ try
+ {
+ handler =
+ (URLStreamHandler) Class.forName(facName).newInstance();
+ }
+ catch (Exception e)
+ {
+ // Can't instantiate; handler still null, go on to next element.
+ }
+ } while ((handler == null ||
+ ! (handler instanceof URLStreamHandler)) &&
+ pkgPrefix.hasMoreTokens());
+ }
+
+ // Update the hashtable with the new protocol handler.
+ if (handler != null)
+ if (handler instanceof URLStreamHandler)
+ handlers.put(protocol, handler);
+ else
+ handler = null;
+
+ return handler;
+ }
+}
diff --git a/libjava/java/net/URLConnection.java b/libjava/java/net/URLConnection.java
new file mode 100644
index 00000000000..12e8a8b4cc6
--- /dev/null
+++ b/libjava/java/net/URLConnection.java
@@ -0,0 +1,423 @@
+// URLConnection.java - Superclass of all communications links between
+// an application and a URL.
+
+/* 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 java.net;
+
+import java.io.*;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Two guessContentTypeFrom... methods not implemented.
+ * getContent method assumes content type from response; see comment there.
+ */
+
+public abstract class URLConnection
+{
+ protected URL url;
+ protected boolean doInput = true;
+ protected boolean doOutput = false;
+ protected boolean allowUserInteraction;
+ protected boolean useCaches;
+ protected long ifModifiedSince = 0L;
+ protected boolean connected = false;
+ private static boolean defaultAllowUserInteraction = false;
+ private static boolean defaultUseCaches = true;
+ private static FileNameMap fileNameMap; // Set by the URLConnection subclass.
+ private static ContentHandlerFactory factory;
+ private static ContentHandler contentHandler;
+ private static Hashtable handlers = new Hashtable();
+ private static Locale locale = new Locale("En", "Us", "Unix");
+ private static SimpleDateFormat dateFormat1 =
+ new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss 'GMT'", locale);
+ private static SimpleDateFormat dateFormat2 =
+ new SimpleDateFormat("EEEE, dd-MMM-yy hh:mm:ss 'GMT'", locale);
+ private static SimpleDateFormat dateFormat3 =
+ new SimpleDateFormat("EEE MMM d hh:mm:ss yyyy", locale);
+
+ protected URLConnection(URL url)
+ {
+ this.url = url;
+ allowUserInteraction = defaultAllowUserInteraction;
+ useCaches = defaultUseCaches;
+ }
+
+ public abstract void connect() throws IOException;
+
+ public URL getURL()
+ {
+ return url;
+ }
+
+ public int getContentLength()
+ {
+ return getHeaderFieldInt("content-length", -1);
+ }
+
+ public String getContentType()
+ {
+ return getHeaderField("content-type");
+ }
+
+ public String getContentEncoding()
+ {
+ return getHeaderField("content-encoding");
+ }
+
+ public long getExpiration()
+ {
+ return getHeaderFieldDate("expiration", 0L);
+ }
+
+ public long getDate()
+ {
+ return getHeaderFieldDate("date", 0L);
+ }
+
+ public long getLastModified()
+ {
+ return getHeaderFieldDate("last-modified", 0L);
+ }
+
+ public String getHeaderField(int n)
+ {
+ // Subclasses for specific protocols override this.
+ return null;
+ }
+
+ public String getHeaderField(String name)
+ {
+ // Subclasses for specific protocols override this.
+ return null;
+ }
+
+ public int getHeaderFieldInt(String name, int val)
+ {
+ String str = getHeaderField(name);
+ try
+ {
+ if (str != null)
+ val = Integer.parseInt(str);
+ }
+ catch (NumberFormatException e)
+ {
+ ; // Do nothing; val is the default.
+ }
+ return val;
+ }
+
+ public long getHeaderFieldDate(String name, long val)
+ {
+ String str = getHeaderField(name);
+ if (str != null)
+ {
+ Date date;
+ if ((date = dateFormat1.parse(str, new ParsePosition(0))) != null)
+ val = date.getTime();
+ else if ((date = dateFormat2.parse(str, new ParsePosition(0))) != null)
+ val = date.getTime();
+ else if ((date = dateFormat3.parse(str, new ParsePosition(0))) != null)
+ val = date.getTime();
+ }
+ return val;
+ }
+
+ public String getHeaderFieldKey(int n)
+ {
+ // Subclasses for specific protocols override this.
+ return null;
+ }
+
+ public Object getContent() throws IOException
+ {
+ // FIXME: Doc indicates that other criteria should be applied as
+ // heuristics to determine the true content type, e.g. see
+ // guessContentTypeFromName() and guessContentTypeFromStream methods
+ // as well as FileNameMap class & fileNameMap field & get/set methods.
+ String cType = getContentType();
+ contentHandler = setContentHandler(cType);
+ if (contentHandler == null)
+ return getInputStream();
+
+ return contentHandler.getContent(this);
+ }
+
+// TODO12: public Permission getPermission() throws IOException
+// {
+// // Subclasses may override this.
+// return java.security.AllPermission;
+// }
+
+ public InputStream getInputStream() throws IOException
+ {
+ // Subclasses for specific protocols override this.
+ throw new UnknownServiceException("Protocol " + url.getProtocol() +
+ " does not support input.");
+ }
+
+ public OutputStream getOutputStream() throws IOException
+ {
+ // Subclasses for specific protocols override this.
+ throw new UnknownServiceException("Protocol " + url.getProtocol() +
+ " does not support output.");
+ }
+
+ public String toString()
+ {
+ return this.getClass().getName() + ":" + url.toString();
+ }
+
+ public void setDoInput(boolean doinput)
+ {
+ if (connected)
+ throw new IllegalAccessError("Already connected");
+
+ doInput = doinput;
+ }
+
+ public boolean getDoInput()
+ {
+ return doInput;
+ }
+
+ public void setDoOutput(boolean dooutput)
+ {
+ if (connected)
+ throw new IllegalAccessError("Already connected");
+
+ doOutput = dooutput;
+ if (doOutput)
+ doInput = false;
+ }
+
+ public boolean getDoOutput()
+ {
+ return doOutput;
+ }
+
+ public void setAllowUserInteraction(boolean allowuserinteraction)
+ {
+ if (connected)
+ throw new IllegalAccessError("Already connected");
+
+ allowUserInteraction = allowuserinteraction;
+ }
+
+ public boolean getAllowUserInteraction()
+ {
+ return allowUserInteraction;
+ }
+
+ public static void
+ setDefaultAllowUserInteraction(boolean defaultallowuserinteraction)
+ {
+ defaultAllowUserInteraction = defaultallowuserinteraction;
+ }
+
+ public static boolean getDefaultAllowUserInteraction()
+ {
+ return defaultAllowUserInteraction;
+ }
+
+ public void setUseCaches(boolean usecaches)
+ {
+ if (connected)
+ throw new IllegalAccessError("Already connected");
+
+ useCaches = usecaches;
+ }
+
+ public boolean getUseCaches()
+ {
+ return useCaches;
+ }
+
+ public void setIfModifiedSince(long ifmodifiedsince)
+ {
+ if (connected)
+ throw new IllegalAccessError("Already connected");
+
+ ifModifiedSince = ifmodifiedsince;
+ }
+
+ public long getIfModifiedSince()
+ {
+ return ifModifiedSince;
+ }
+
+ public boolean getDefaultUseCaches()
+ {
+ return defaultUseCaches;
+ }
+
+ public void setDefaultUseCaches(boolean defaultusecaches)
+ {
+ defaultUseCaches = defaultusecaches;
+ }
+
+ public void setRequestProperty(String key, String value)
+ {
+ // Do nothing unless overridden by subclasses that support setting
+ // header fields in the request.
+ }
+
+ public String getRequestProperty(String key)
+ {
+ // Overridden by subclasses that support reading header fields from the
+ // request.
+ return null;
+ }
+
+ public static void setDefaultRequestProperty(String key, String value)
+ {
+ // Do nothing unless overridden by subclasses that support setting
+ // default request properties.
+ }
+
+ public static String getDefaultRequestProperty(String key)
+ {
+ // Overridden by subclasses that support default request properties.
+ return null;
+ }
+
+ public static void setContentHandlerFactory(ContentHandlerFactory fac)
+ {
+ if (factory != null)
+ throw new Error("ContentHandlerFactory already set");
+
+ // Throw an exception if an extant security mgr precludes
+ // setting the factory.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkSetFactory();
+ factory = fac;
+ }
+
+// TODO: protected static String guessContentTypeFromName(String fname)
+// {
+// }
+
+// TODO: public static String guessContentTypeFromStream(InputStream is)
+// throws IOException
+// {
+// }
+
+// TODO12: protected void parseURL(URL u, String spec, int start, int limit)
+
+ // JDK1.2
+ public static FileNameMap getFileNameMap()
+ {
+ return fileNameMap;
+ }
+
+ // JDK1.2
+ public static void setFileNameMap(FileNameMap map)
+ {
+ // Throw an exception if an extant security mgr precludes
+ // setting the factory.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkSetFactory();
+
+ fileNameMap = map;
+ }
+
+ private ContentHandler setContentHandler(String contentType)
+ {
+ ContentHandler handler;
+
+ // No content type so just handle it as the default.
+ if (contentType == null || contentType == "")
+ return null;
+
+ // See if a handler has been cached for this content type.
+ // For efficiency, if a content type has been searched for but not
+ // found, it will be in the hash table but as the contentType String
+ // instead of a ContentHandler.
+ if ((handler = (ContentHandler) handlers.get(contentType)) != null)
+ if (handler instanceof ContentHandler)
+ return handler;
+ else
+ return null;
+
+ // If a non-default factory has been set, use it to find the content type.
+ if (factory != null)
+ handler = factory.createContentHandler(contentType);
+
+ // Non-default factory may have returned null or a factory wasn't set.
+ // Use the default search algorithm to find a handler for this content type.
+ if (handler == null)
+ {
+ // Get the list of packages to check and append our default handler
+ // to it, along with the JDK specified default as a last resort.
+ // Except in very unusual environments the JDK specified one shouldn't
+ // ever be needed (or available).
+ String propVal = System.getProperty("java.content.handler.pkgs");
+ propVal = (propVal == null) ? "" : (propVal + "|");
+ propVal = propVal + "gnu.gcj.content|sun.net.www.content";
+
+ // Replace the '/' character in the content type with '.' and
+ // all other non-alphabetic, non-numeric characters with '_'.
+ StringTokenizer pkgPrefix = new StringTokenizer(propVal, "|");
+ char[] cArray = contentType.toCharArray();
+ for (int i = 0; i < cArray.length; i++)
+ {
+ if (cArray[i] == '/')
+ cArray[i] = '.';
+ else if (! ((cArray[i] >= 'A' && cArray[i] <= 'Z') ||
+ (cArray[i] >= 'a' && cArray[i] <= 'z') ||
+ (cArray[i] >= '0' && cArray[i] <= '9')))
+ cArray[i] = '_';
+ }
+ String contentClass = new String(cArray);
+
+ // See if a class of this content type exists in any of the packages.
+ do
+ {
+ String facName = pkgPrefix.nextToken() + "." + contentClass;
+ try
+ {
+ handler =
+ (ContentHandler) Class.forName(facName).newInstance();
+ }
+ catch (Exception e)
+ {
+ // Can't instantiate; handler still null, go on to next element.
+ }
+ } while ((handler == null ||
+ ! (handler instanceof ContentHandler)) &&
+ pkgPrefix.hasMoreTokens());
+ }
+
+ // Update the hashtable with the new content handler.
+ if (handler != null && handler instanceof ContentHandler)
+ {
+ handlers.put(contentType, handler);
+ return handler;
+ }
+
+ // For efficiency on subsequent searches, put a dummy entry in the hash
+ // table for content types that don't have a non-default ContentHandler.
+ handlers.put(contentType, contentType);
+ return null;
+ }
+}
diff --git a/libjava/java/net/URLStreamHandler.java b/libjava/java/net/URLStreamHandler.java
new file mode 100644
index 00000000000..29e0e6d4137
--- /dev/null
+++ b/libjava/java/net/URLStreamHandler.java
@@ -0,0 +1,107 @@
+// URLStreamHandler.java - Superclass of all stream protocol handlers.
+
+/* 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 java.net;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 4, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public abstract class URLStreamHandler
+{
+ protected abstract URLConnection openConnection(URL u)
+ throws java.io.IOException;
+
+protected void parseURL(URL u, String spec, int start, int limit)
+ {
+ String tmpStr;
+ String host = ""; // Initialize to null string.
+ String file;
+ int port = -1;
+ int colon;
+
+ /* TBD: The JDK 1.2 doc specifically says that limit is the position
+ * to stop parsing at and that it will be either the end of the string
+ * or the position of '#'; thus the doc infers that this method does
+ * not set the ref.
+ */
+ tmpStr = spec.substring(start, limit);
+ int hostEnd = 0;
+ if (tmpStr.startsWith("//"))
+ {
+ int slash = tmpStr.indexOf('/', 2);
+ hostEnd = tmpStr.length();
+ if (slash >= 0)
+ hostEnd = slash;
+
+ host = tmpStr.substring(2, hostEnd);
+
+ // Look for optional port number.
+ if ((colon = host.indexOf(':')) >= 0)
+ {
+ try
+ {
+ port = Integer.parseInt(host.substring(colon + 1));
+ }
+ catch (NumberFormatException e)
+ {
+ ; // Ignore invalid port values; port is already set to -1.
+ }
+ host = host.substring(0, colon);
+ }
+ }
+
+ if (hostEnd < tmpStr.length())
+ file = ((tmpStr.startsWith("/")) ? "" : "/") + tmpStr.substring(hostEnd);
+ else
+ file = "/";
+
+ u.set(u.getProtocol(), host, port, file, u.getRef());
+ }
+
+ protected void setURL(URL u, String protocol, String host, int port,
+ String file, String ref)
+ {
+ u.set(protocol, host, port, file, ref);
+ }
+
+ protected String toExternalForm(URL u)
+ {
+ String resStr, host, file, ref;
+ int port;
+
+ resStr = u.getProtocol() + ":";
+ host = u.getHost();
+ port = u.getPort();
+ file = u.getFile();
+ ref = u.getRef();
+
+ if (! host.equals(""))
+ {
+ resStr = resStr + "//" + host;
+ if (port >= 0)
+ resStr = resStr + ":" + port;
+ }
+
+ resStr = resStr + file;
+
+ if (ref != null)
+ resStr = resStr + "#" + ref;
+
+ return resStr;
+ }
+}
diff --git a/libjava/java/net/URLStreamHandlerFactory.java b/libjava/java/net/URLStreamHandlerFactory.java
new file mode 100644
index 00000000000..474d723d4f5
--- /dev/null
+++ b/libjava/java/net/URLStreamHandlerFactory.java
@@ -0,0 +1,27 @@
+// URLStreamHandlerFactory.java - Abstract URL Stream Handler factory.
+
+/* 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 java.net;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public abstract interface URLStreamHandlerFactory
+{
+ public URLStreamHandler createURLStreamHandler(String protocol);
+}
diff --git a/libjava/java/net/UnknownHostException.java b/libjava/java/net/UnknownHostException.java
new file mode 100644
index 00000000000..1c2050923e9
--- /dev/null
+++ b/libjava/java/net/UnknownHostException.java
@@ -0,0 +1,34 @@
+// UnknownHostException.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.net;
+
+/**
+ * @author Per Bothner
+ * @date January 6, 1999.
+ */
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification.
+ * Status: Believed complete and correct.
+ */
+
+public class UnknownHostException extends java.io.IOException
+{
+ public UnknownHostException ()
+ {
+ super();
+ }
+
+ public UnknownHostException (String host)
+ {
+ super(host);
+ }
+}
diff --git a/libjava/java/net/UnknownServiceException.java b/libjava/java/net/UnknownServiceException.java
new file mode 100644
index 00000000000..dba798e0e80
--- /dev/null
+++ b/libjava/java/net/UnknownServiceException.java
@@ -0,0 +1,35 @@
+// UnknownServiceException.java
+
+/* 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 java.net;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date March 5, 1999.
+ */
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public class UnknownServiceException extends java.io.IOException
+{
+ public UnknownServiceException()
+ {
+ super();
+ }
+
+ public UnknownServiceException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/net/natInetAddress.cc b/libjava/java/net/natInetAddress.cc
new file mode 100644
index 00000000000..7f7d953b9c1
--- /dev/null
+++ b/libjava/java/net/natInetAddress.cc
@@ -0,0 +1,270 @@
+// natClass.cc - Implementation of java.lang.Class native methods.
+
+/* 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>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/net/InetAddress.h>
+#include <java/net/UnknownHostException.h>
+#include <java/lang/SecurityException.h>
+
+#if defined(HAVE_UNAME) && ! defined(HAVE_GETHOSTNAME)
+#include <sys/utsname.h>
+#endif
+
+#ifndef HAVE_GETHOSTNAME_DECL
+extern "C" int gethostname (char *name, int namelen);
+#endif
+
+jbyteArray
+java::net::InetAddress::aton (jstring host)
+{
+ char *hostname;
+ char buf[100];
+ int len = JvGetStringUTFLength(host);
+ if (len < 100)
+ hostname = buf;
+ else
+ hostname = (char*) _Jv_AllocBytesChecked (len+1);
+ JvGetStringUTFRegion (host, 0, host->length(), hostname);
+ buf[len] = '\0';
+ char* bytes = NULL;
+ int blen = 0;
+#ifdef HAVE_INET_ATON
+ struct in_addr laddr;
+ if (inet_aton (hostname, &laddr))
+ {
+ bytes = (char*) &laddr;
+ len = 4;
+ }
+#elif defined(HAVE_INET_ADDR)
+ in_addr_t laddr = inet_addr (hostname);
+ if (laddr != (in_addr_t)(-1))
+ {
+ bytes = (char*) &laddr;
+ len = 4;
+ }
+#endif
+#ifdef HAVE_INET_PTON
+ char inet6_addr[16];
+ if (len == 0 && inet_pton (AF_INET6, hostname, inet6_addr) > 0)
+ {
+ bytes = inet6_addr;
+ len = 16;
+ }
+#endif
+ if (blen == 0)
+ return NULL;
+ jbyteArray result = JvNewByteArray (len);
+ memcpy (elements (result), bytes, blen);
+ return result;
+}
+
+
+JArray<java::net::InetAddress*> *
+java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr,
+ jboolean all)
+{
+ struct hostent *hptr = NULL;
+#if defined (HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR_R)
+ struct hostent hent_r;
+ char fixed_buffer[200];
+ char *buffer_r = fixed_buffer;
+ int size_r = sizeof (fixed_buffer);
+#endif
+
+ if (host != NULL)
+ {
+ char *hostname;
+ char buf[100];
+ int len = JvGetStringUTFLength(host);
+ if (len < 100)
+ hostname = buf;
+ else
+ hostname = (char*) _Jv_AllocBytesChecked (len+1);
+ JvGetStringUTFRegion (host, 0, host->length(), hostname);
+ buf[len] = '\0';
+#ifdef HAVE_GETHOSTBYNAME_R
+ int herr = ERANGE;
+ while (hptr == NULL && herr == ERANGE)
+ {
+ int ok;
+#ifdef GETHOSTBYNAME_R_RETURNS_INT
+ ok = ! gethostbyname_r (hostname, &hent_r, buffer_r, size_r,
+ &hptr, &herr);
+#else
+ hptr = gethostbyname_r (hostname, &hent_r, buffer_r, size_r, &herr);
+ ok = hptr != NULL;
+#endif /* GETHOSTNAME_R_RETURNS_INT */
+ if (! ok && herr == ERANGE)
+ {
+ size_r *= 2;
+ buffer_r = (char *) _Jv_AllocBytesChecked (size_r);
+ }
+ }
+#else
+ // FIXME: this is insufficient if some other piece of code calls
+ // this gethostbyname.
+ JvSynchronize sync (java::net::InetAddress::localhostAddress);
+ hptr = gethostbyname (hostname);
+#endif /* HAVE_GETHOSTBYNAME_R */
+ }
+ else
+ {
+ jbyteArray bytes = iaddr->address;
+ char *chars = (char*) elements (bytes);
+ int len = bytes->length;
+ int type;
+ char *val;
+ if (len == 4)
+ {
+ val = chars;
+ type = AF_INET;
+ }
+#ifdef HAVE_INET6
+ else if (len == 16)
+ {
+ val = (char *) &chars;
+ type = AF_INET16;
+ }
+#endif /* HAVE_INET6 */
+ else
+ JvFail ("unrecognized size");
+
+#ifdef HAVE_GETHOSTBYADDR_R
+ int herr = ERANGE;
+ while (hptr == NULL && herr == ERANGE)
+ {
+ int ok;
+#ifdef GETHOSTBYADDR_R_RETURNS_INT
+ ok = ! gethostbyaddr_r (val, len, type, &hent_r,
+ buffer_r, size_r, &hptr, &herr);
+#else
+ hptr = gethostbyaddr_r (val, len, type, &hent_r,
+ buffer_r, size_r, &herr);
+ ok = hptr != NULL;
+#endif /* GETHOSTBYADDR_R_RETURNS_INT */
+ if (! ok && herr == ERANGE)
+ {
+ size_r *= 2;
+ buffer_r = (char *) _Jv_AllocBytesChecked (size_r);
+ }
+ }
+#else /* HAVE_GETHOSTBYADDR_R */
+ // FIXME: this is insufficient if some other piece of code calls
+ // this gethostbyaddr.
+ JvSynchronize sync (java::net::InetAddress::localhostAddress);
+ hptr = gethostbyaddr (val, len, type);
+#endif /* HAVE_GETHOSTBYADDR_R */
+ }
+ if (hptr != NULL)
+ {
+ host = JvNewStringUTF (hptr->h_name);
+ java::lang::SecurityException *ex = checkConnect (host);
+ if (ex != NULL)
+ {
+ if (iaddr == NULL || iaddr->address == NULL)
+ JvThrow (ex);
+ hptr = NULL;
+ }
+ }
+ if (hptr == NULL)
+ {
+ if (iaddr != NULL && iaddr->address != NULL)
+ {
+ iaddr->hostname = iaddr->getHostAddress();
+ return NULL;
+ }
+ else
+ JvThrow (new java::net::UnknownHostException(host));
+ }
+ int count;
+ if (all)
+ {
+ char** ptr = hptr->h_addr_list;
+ count = 0;
+ while (*ptr++) count++;
+ }
+ else
+ count = 1;
+ JArray<java::net::InetAddress*> *result;
+ java::net::InetAddress** iaddrs;
+ if (all)
+ {
+ result = java::net::InetAddress::allocArray (count);
+ iaddrs = elements (result);
+ }
+ else
+ {
+ result = NULL;
+ iaddrs = &iaddr;
+ }
+
+ for (int i = 0; i < count; i++)
+ {
+ if (iaddrs[i] == NULL)
+ iaddrs[i] = new java::net::InetAddress (NULL, NULL);
+ if (i == 0)
+ iaddrs[0]->hostname = host;
+ if (iaddrs[i]->address == NULL)
+ {
+ char *bytes = hptr->h_addr_list[i];
+ iaddr->address = JvNewByteArray (hptr->h_length);
+ memcpy (elements (iaddr->address), bytes, hptr->h_length);
+ }
+ }
+ return result;
+}
+
+jstring
+java::net::InetAddress::getLocalHostname ()
+{
+ char *chars;
+#ifdef HAVE_GETHOSTNAME
+ char buffer[MAXHOSTNAMELEN];
+ if (gethostname (buffer, MAXHOSTNAMELEN))
+ return NULL;
+ chars = buffer;
+#elif HAVE_UNAME
+ struct utsname stuff;
+ if (uname (&stuff) != 0)
+ return NULL:
+ chars = stuff.nodename;
+#else
+ return NULL;
+#endif
+ // It is admittedly non-optimal to convert the hostname to Unicode
+ // only to convert it back in getByName, but simplicity wins. Note
+ // that unless there is a SecurityManager, we only get called once
+ // anyway, thanks to the InetAddress.localhost cache.
+ return JvNewStringUTF (chars);
+}
diff --git a/libjava/java/net/natPlainSocketImpl.cc b/libjava/java/net/natPlainSocketImpl.cc
new file mode 100644
index 00000000000..076ee711948
--- /dev/null
+++ b/libjava/java/net/natPlainSocketImpl.cc
@@ -0,0 +1,177 @@
+/* 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 <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <cni.h>
+#include <java/io/IOException.h>
+#include <java/io/FileDescriptor.h>
+#include <java/net/PlainSocketImpl.h>
+#include <java/net/InetAddress.h>
+
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
+union SockAddr
+{
+ struct sockaddr_in address;
+#ifdef HAVE_INET6
+ struct sockaddr_in6 address6;
+#endif
+};
+
+void
+java::net::PlainSocketImpl::create (jboolean stream)
+{
+ int sock = ::socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
+ if (sock < 0)
+ {
+ char msg[100];
+ char* strerr = strerror (errno);
+ sprintf (msg, "SocketImpl.create: %.*s", 80, strerr);
+ JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
+ }
+ fnum = sock;
+ fd = new java::io::FileDescriptor (sock);
+}
+
+void
+java::net::PlainSocketImpl::bind (java::net::InetAddress *host, jint lport)
+{
+ union SockAddr u;
+ jbyteArray haddress = host->address;
+ jbyte *bytes = elements (haddress);
+ int len = haddress->length;
+ struct sockaddr *ptr = (struct sockaddr *) &u.address;
+ if (len == 4)
+ {
+ u.address.sin_family = AF_INET;
+ memcpy (&u.address.sin_addr, bytes, len);
+ len = sizeof (struct sockaddr_in);
+ u.address.sin_port = htons (lport);
+ }
+#ifdef HAVE_INET6
+ else if (len == 16)
+ {
+ u.address6.sin6_family = AF_INET6;
+ memcpy (&u.address6.sin6_addr, bytes, len);
+ len = sizeof (struct sockaddr_in6);
+ u.address6.sin6_port = htons (lport);
+ }
+#endif
+ else
+ goto error;
+ if (::bind (fnum, ptr, len) == 0)
+ {
+ address = host;
+ localport = lport;
+ return;
+ }
+ error:
+ char msg[100];
+ char* strerr = strerror (errno);
+ sprintf (msg, "SocketImpl.bind: %.*s", 80, strerr);
+ JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
+}
+
+void
+java::net::PlainSocketImpl::connect (java::net::InetAddress *host, jint rport)
+{
+ union SockAddr u;
+ jbyteArray haddress = host->address;
+ jbyte *bytes = elements (haddress);
+ int len = haddress->length;
+ struct sockaddr *ptr = (struct sockaddr *) &u.address;
+ if (len == 4)
+ {
+ u.address.sin_family = AF_INET;
+ memcpy (&u.address.sin_addr, bytes, len);
+ len = sizeof (struct sockaddr_in);
+ u.address.sin_port = htons (rport);
+ }
+#ifdef HAVE_INET6
+ else if (len == 16)
+ {
+ u.address6.sin6_family = AF_INET6;
+ memcpy (&u.address6.sin6_addr, bytes, len);
+ len = sizeof (struct sockaddr_in6);
+ u.address6.sin6_port = htons (rport);
+ }
+#endif
+ else
+ goto error;
+ if (::connect (fnum, ptr, len) == 0)
+ {
+ address = host;
+ port = rport;
+ return;
+ }
+ error:
+ char msg[100];
+ char* strerr = strerror (errno);
+ sprintf (msg, "SocketImpl.connect: %.*s", 80, strerr);
+ JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
+}
+
+void
+java::net::PlainSocketImpl::listen (jint backlog)
+{
+ if (::listen (fnum, backlog) != 0)
+ {
+ char msg[100];
+ char* strerr = strerror (errno);
+ sprintf (msg, "SocketImpl.listen: %.*s", 80, strerr);
+ JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
+ }
+}
+
+void
+java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s)
+{
+ union SockAddr u;
+ socklen_t addrlen = sizeof(u);
+ int new_socket = ::accept (fnum, (sockaddr*) &u, &addrlen);
+ if (new_socket < 0)
+ goto error;
+ jbyteArray raddr;
+ jint rport;
+ if (u.address.sin_family == AF_INET)
+ {
+ raddr = JvNewByteArray (4);
+ memcpy (elements (raddr), &u.address.sin_addr, 4);
+ rport = ntohs (u.address.sin_port);
+ }
+#ifdef HAVE_INET6
+ {
+ raddr = JvNewByteArray (16);
+ memcpy (elements (raddr), &u.address6.sin6_addr, 16);
+ rport = ntohs (u.address6.sin6_port);
+ }
+#endif
+ else
+ goto error;
+ s->fnum = new_socket;
+ s->localport = localport;
+ s->address = new InetAddress (raddr, NULL);
+ s->port = rport;
+ s->fd = new java::io::FileDescriptor (new_socket);
+ return;
+ error:
+ char msg[100];
+ char* strerr = strerror (errno);
+ sprintf (msg, "SocketImpl.accept: %.*s", 80, strerr);
+ JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
+}
diff --git a/libjava/java/text/BreakIterator.java b/libjava/java/text/BreakIterator.java
new file mode 100644
index 00000000000..0e09d456679
--- /dev/null
+++ b/libjava/java/text/BreakIterator.java
@@ -0,0 +1,160 @@
+// BreakIterator.java - Iterate over logical breaks in 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 java.text;
+
+import java.io.Serializable;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date March 19, 1999
+ */
+/* 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 to 1.1.
+ */
+
+public abstract class BreakIterator implements Cloneable, Serializable
+{
+ // The value was discovered by writing a test program.
+ public static final int DONE = -1;
+
+ protected BreakIterator ()
+ {
+ }
+
+ public abstract int current ();
+ public abstract int first ();
+ public abstract int following (int pos);
+
+ public static synchronized Locale[] getAvailableLocales ()
+ {
+ // FIXME.
+ return null;
+ }
+
+ private static BreakIterator getInstance (String type, Locale loc)
+ {
+ String className;
+ try
+ {
+ ResourceBundle res
+ = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", loc);
+ className = res.getString(type);
+ }
+ catch (MissingResourceException x)
+ {
+ return null;
+ }
+ try
+ {
+ Class k = Class.forName(className);
+ return (BreakIterator) k.newInstance();
+ }
+ catch (ClassNotFoundException x1)
+ {
+ return null;
+ }
+ catch (InstantiationException x2)
+ {
+ return null;
+ }
+ catch (IllegalAccessException x3)
+ {
+ return null;
+ }
+ }
+
+ public static BreakIterator getCharacterInstance ()
+ {
+ return getCharacterInstance (Locale.getDefault());
+ }
+
+ public static BreakIterator getCharacterInstance (Locale loc)
+ {
+ BreakIterator r = getInstance ("CharacterIterator", loc);
+ if (r == null)
+ r = new gnu.gcj.text.CharacterBreakIterator ();
+ return r;
+ }
+
+ public static BreakIterator getLineInstance ()
+ {
+ return getLineInstance (Locale.getDefault());
+ }
+
+ public static BreakIterator getLineInstance (Locale loc)
+ {
+ BreakIterator r = getInstance ("LineIterator", loc);
+ if (r == null)
+ r = new gnu.gcj.text.LineBreakIterator ();
+ return r;
+ }
+
+ public static BreakIterator getSentenceInstance ()
+ {
+ return getSentenceInstance (Locale.getDefault());
+ }
+
+ public static BreakIterator getSentenceInstance (Locale loc)
+ {
+ BreakIterator r = getInstance ("SentenceIterator", loc);
+ if (r == null)
+ r = new gnu.gcj.text.SentenceBreakIterator ();
+ return r;
+ }
+
+ public abstract CharacterIterator getText ();
+
+ public static BreakIterator getWordInstance ()
+ {
+ return getWordInstance (Locale.getDefault());
+ }
+
+ public static BreakIterator getWordInstance (Locale loc)
+ {
+ BreakIterator r = getInstance ("WordIterator", loc);
+ if (r == null)
+ r = new gnu.gcj.text.WordBreakIterator ();
+ return r;
+ }
+
+ public boolean isBoundary (int pos)
+ {
+ if (pos == 0)
+ return true;
+ return following (pos - 1) == pos;
+ }
+
+ public abstract int last ();
+ public abstract int next ();
+ public abstract int next (int n);
+
+ public int preceding (int pos)
+ {
+ if (following (pos) == DONE)
+ last ();
+ while (previous () >= pos)
+ ;
+ return current ();
+ }
+
+ public abstract int previous ();
+
+ public void setText (String newText)
+ {
+ setText (new StringCharacterIterator (newText));
+ }
+
+ public abstract void setText (CharacterIterator newText);
+}
diff --git a/libjava/java/text/CharacterIterator.java b/libjava/java/text/CharacterIterator.java
new file mode 100644
index 00000000000..d34e988a154
--- /dev/null
+++ b/libjava/java/text/CharacterIterator.java
@@ -0,0 +1,36 @@
+// CharacterIterator.java - Protocol for iterating over Unicode characters.
+
+/* 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 java.text;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date February 22, 1999
+ */
+/* 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 to 1.1.
+ */
+
+public interface CharacterIterator extends Cloneable
+{
+ public abstract Object clone ();
+ public abstract char current ();
+ public abstract char first ();
+ public abstract int getBeginIndex ();
+ public abstract int getEndIndex ();
+ public abstract int getIndex ();
+ public abstract char last ();
+ public abstract char next ();
+ public abstract char previous ();
+ public abstract char setIndex (int idx);
+
+ public static final char DONE = '\uffff';
+}
diff --git a/libjava/java/text/ChoiceFormat.java b/libjava/java/text/ChoiceFormat.java
new file mode 100644
index 00000000000..bed62a75e53
--- /dev/null
+++ b/libjava/java/text/ChoiceFormat.java
@@ -0,0 +1,310 @@
+// ChoiceFormat.java - Formatter for `switch'-like string substitution.
+
+/* 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 java.text;
+
+import java.util.Vector;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date March 9, 1999
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.1.
+ */
+
+public class ChoiceFormat extends NumberFormat
+{
+ // Note: we assume the same kind of quoting rules apply here.
+ // This isn't explicitly documented. But for instance we accept
+ // '#' as a literal hash in a format string.
+ public void applyPattern (String newPattern)
+ {
+ int index = 0, max = newPattern.length();
+ Vector stringVec = new Vector ();
+ Vector limitVec = new Vector ();
+ StringBuffer buf = new StringBuffer ();
+
+ while (true)
+ {
+ // Find end of double.
+ int dstart = index;
+ while (index < max)
+ {
+ char c = newPattern.charAt(index);
+ if (c == '#' || c == '\u2064' || c == '<')
+ break;
+ ++index;
+ }
+
+ if (index == max)
+ throw new IllegalArgumentException ("unexpected end of text");
+ Double d = new Double (newPattern.substring(dstart, index));
+
+ if (newPattern.charAt(index) == '<')
+ d = new Double (nextDouble (d.doubleValue()));
+
+ limitVec.addElement(d);
+
+ // Scan text.
+ ++index;
+ buf.setLength(0);
+ while (index < max)
+ {
+ char c = newPattern.charAt(index);
+ if (c == '\'' && index < max + 1
+ && newPattern.charAt(index + 1) == '\'')
+ {
+ buf.append(c);
+ ++index;
+ }
+ else if (c == '\'' && index < max + 2)
+ {
+ buf.append(newPattern.charAt(index + 1));
+ index += 2;
+ }
+ else if (c == '|')
+ break;
+ else
+ buf.append(c);
+ ++index;
+ }
+
+ stringVec.addElement(buf.toString());
+ if (index == max)
+ break;
+ ++index;
+ }
+
+ strings = new String[stringVec.size()];
+ stringVec.copyInto(strings);
+
+ limits = new double[limitVec.size()];
+ for (int i = 0; i < limits.length; ++i)
+ {
+ Double d = (Double) limitVec.elementAt(i);
+ limits[i] = d.doubleValue();
+ }
+ }
+
+ public ChoiceFormat (String newPattern)
+ {
+ super ();
+ applyPattern (newPattern);
+ }
+
+ public ChoiceFormat (double[] limits, String[] strings)
+ {
+ super ();
+ setChoices (limits, strings);
+ }
+
+ public Object clone ()
+ {
+ return new ChoiceFormat (limits, strings);
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof ChoiceFormat))
+ return false;
+ ChoiceFormat cf = (ChoiceFormat) obj;
+ if (limits.length != cf.limits.length)
+ return false;
+ for (int i = limits.length - 1; i >= 0; --i)
+ {
+ if (limits[i] != cf.limits[i]
+ || !strings[i].equals(cf.strings[i]))
+ return false;
+ }
+ return true;
+ }
+
+ public StringBuffer format (long num, StringBuffer appendBuf,
+ FieldPosition pos)
+ {
+ return format ((double) num, appendBuf, pos);
+ }
+
+ public StringBuffer format (double num, StringBuffer appendBuf,
+ FieldPosition pos)
+ {
+ if (limits.length == 0)
+ return appendBuf;
+
+ int index = 0;
+ if (! Double.isNaN(num) && num >= limits[0])
+ {
+ for (; index < limits.length - 1; ++index)
+ {
+ if (limits[index] <= num
+ && index != limits.length - 2
+ && num < limits[index + 1])
+ break;
+ }
+ }
+
+ return appendBuf.append(strings[index]);
+ }
+
+ public Object[] getFormats ()
+ {
+ return (Object[]) strings.clone();
+ }
+
+ public double[] getLimits ()
+ {
+ return (double[]) limits.clone();
+ }
+
+ public int hashCode ()
+ {
+ int hash = 0;
+ for (int i = 0; i < limits.length; ++i)
+ {
+ long v = Double.doubleToLongBits(limits[i]);
+ hash ^= (v ^ (v >>> 32));
+ hash ^= strings[i].hashCode();
+ }
+ return hash;
+ }
+
+ public static final double nextDouble (double d)
+ {
+ return nextDouble (d, true);
+ }
+
+ public static final double nextDouble (double d, boolean next)
+ {
+ if (Double.isInfinite(d) || Double.isNaN(d))
+ return d;
+
+ long bits = Double.doubleToLongBits(d);
+
+ long mantMask = (1L << mantissaBits) - 1;
+ long mantissa = bits & mantMask;
+
+ long expMask = (1L << exponentBits) - 1;
+ long exponent = (bits >>> mantissaBits) & expMask;
+
+ if (next ^ (bits < 0)) // Increment magnitude
+ {
+ if (mantissa == (1L << mantissaBits) - 1)
+ {
+ mantissa = 0L;
+ exponent++;
+
+ // Check for absolute overflow.
+ if (exponent >= (1L << mantissaBits))
+ return (bits > 0) ? Double.POSITIVE_INFINITY
+ : Double.NEGATIVE_INFINITY;
+ }
+ else
+ mantissa++;
+ }
+ else // Decrement magnitude
+ {
+ if (exponent == 0L && mantissa == 0L)
+ {
+ // The only case where there is a change of sign
+ return next ? Double.MIN_VALUE : -Double.MIN_VALUE;
+ }
+ else
+ {
+ if (mantissa == 0L)
+ {
+ mantissa = (1L << mantissaBits) - 1;
+ exponent--;
+ }
+ else
+ mantissa--;
+ }
+ }
+
+ long result = bits < 0 ? 1 : 0;
+ result = (result << exponentBits) | exponent;
+ result = (result << mantissaBits) | mantissa;
+ return Double.longBitsToDouble(result);
+ }
+
+ public Number parse (String sourceStr, ParsePosition pos)
+ {
+ int index = pos.getIndex();
+ for (int i = 0; i < limits.length; ++i)
+ {
+ if (sourceStr.startsWith(strings[i], index))
+ {
+ pos.setIndex(index + strings[i].length());
+ return new Double (limits[i]);
+ }
+ }
+ pos.setErrorIndex(index);
+ return new Double (Double.NaN);
+ }
+
+ public static final double previousDouble (double d)
+ {
+ return nextDouble (d, false);
+ }
+
+ public void setChoices (double[] limits, String[] strings)
+ {
+ if (limits == null || strings == null)
+ throw new NullPointerException ();
+ if (limits.length != strings.length)
+ throw new IllegalArgumentException ();
+ this.strings = (String[]) strings.clone();
+ this.limits = (double[]) limits.clone();
+ }
+
+ private final void quoteString (StringBuffer dest, String text)
+ {
+ int max = text.length();
+ for (int i = 0; i < max; ++i)
+ {
+ char c = text.charAt(i);
+ if (c == '\'')
+ {
+ dest.append(c);
+ dest.append(c);
+ }
+ else if (c == '#' || c == '|' || c == '\u2064' || c == '<')
+ {
+ dest.append('\'');
+ dest.append(c);
+ dest.append('\'');
+ }
+ else
+ dest.append(c);
+ }
+ }
+
+ public String toPattern ()
+ {
+ StringBuffer result = new StringBuffer ();
+ for (int i = 0; i < limits.length; ++i)
+ {
+ result.append(limits[i]);
+ result.append('#');
+ quoteString (result, strings[i]);
+ }
+ return result.toString();
+ }
+
+ // Formats and limits.
+ private String[] strings;
+ private double[] limits;
+
+ // Number of mantissa bits in double.
+ private static final int mantissaBits = 52;
+ // Number of exponent bits in a double.
+ private static final int exponentBits = 11;
+}
diff --git a/libjava/java/text/DateFormat.java b/libjava/java/text/DateFormat.java
new file mode 100644
index 00000000000..bfd6b01a777
--- /dev/null
+++ b/libjava/java/text/DateFormat.java
@@ -0,0 +1,301 @@
+/* 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.text;
+
+import java.util.*;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 25, 1998.
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Mostly complete; search for FIXME to see omissions.
+ */
+
+public abstract class DateFormat extends Format implements Cloneable
+{
+ protected Calendar calendar;
+ protected NumberFormat numberFormat;
+
+ // (Values determined using a test program.)
+ public final static int FULL = 0;
+ public final static int LONG = 1;
+ public final static int MEDIUM = 2;
+ public final static int SHORT = 3;
+ public final static int DEFAULT = MEDIUM;
+
+ public final static int ERA_FIELD = 0;
+ public final static int YEAR_FIELD = 1;
+ public final static int MONTH_FIELD = 2;
+ public final static int DATE_FIELD = 3;
+ public final static int HOUR_OF_DAY1_FIELD = 4;
+ public final static int HOUR_OF_DAY0_FIELD = 5;
+ public final static int MINUTE_FIELD = 6;
+ public final static int SECOND_FIELD = 7;
+ public final static int MILLISECOND_FIELD = 8;
+ public final static int DAY_OF_WEEK_FIELD = 9;
+ public final static int DAY_OF_YEAR_FIELD = 10;
+ public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
+ public final static int WEEK_OF_YEAR_FIELD = 12;
+ public final static int WEEK_OF_MONTH_FIELD = 13;
+ public final static int AM_PM_FIELD = 14;
+ public final static int HOUR1_FIELD = 15;
+ public final static int HOUR0_FIELD = 16;
+ public final static int TIMEZONE_FIELD = 17;
+
+ protected DateFormat ()
+ {
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof DateFormat))
+ return false;
+ DateFormat d = (DateFormat) obj;
+ return calendar.equals(d.calendar) && numberFormat.equals(d.numberFormat);
+ }
+
+ public final StringBuffer format (Object obj,
+ StringBuffer buf, FieldPosition pos)
+ {
+ if (obj instanceof Number)
+ return format (new Date(((Number) obj).longValue()), buf, pos);
+ return format ((Date) obj, buf, pos);
+ }
+
+ public final String format (Date date)
+ {
+ StringBuffer sb = new StringBuffer ();
+ format (date, sb, new FieldPosition (MONTH_FIELD));
+ return sb.toString();
+ }
+
+ public abstract StringBuffer format (Date date,
+ StringBuffer buf, FieldPosition pos);
+
+ public static Locale[] getAvailableLocales ()
+ {
+ return null; // FIXME
+ }
+
+ public Calendar getCalendar ()
+ {
+ return calendar;
+ }
+
+ private static final DateFormat computeInstance (int style, Locale loc,
+ boolean use_date,
+ boolean use_time)
+ {
+ ResourceBundle res;
+ try
+ {
+ res = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", loc);
+ }
+ catch (MissingResourceException x)
+ {
+ res = null;
+ }
+
+ String pattern = null;
+ if (use_date)
+ {
+ String name, def;
+ switch (style)
+ {
+ case FULL:
+ name = "fullDateFormat";
+ def = "EEEE MMMM d, yyyy G";
+ break;
+ case LONG:
+ name = "longDateFormat";
+ def = "MMMM d, yyyy";
+ break;
+ case MEDIUM:
+ name = "mediumDateFormat";
+ def = "d-MMM-yy";
+ break;
+ case SHORT:
+ name = "shortDateFormat";
+ def = "M/d/yy";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+ try
+ {
+ pattern = res == null ? def : res.getString(name);
+ }
+ catch (MissingResourceException x)
+ {
+ pattern = def;
+ }
+ }
+
+ if (use_time)
+ {
+ if (pattern == null)
+ pattern = "";
+ else
+ pattern += " ";
+
+ String name, def;
+ switch (style)
+ {
+ case FULL:
+ name = "fullTimeFormat";
+ def = "h:mm:ss;S 'o''clock' a z";
+ break;
+ case LONG:
+ name = "longTimeFormat";
+ def = "h:mm:ss a z";
+ break;
+ case MEDIUM:
+ name = "mediumTimeFormat";
+ def = "h:mm:ss a";
+ break;
+ case SHORT:
+ name = "shortTimeFormat";
+ def = "h:mm a";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+
+ String s;
+ try
+ {
+ s = res == null ? def : res.getString(name);
+ }
+ catch (MissingResourceException x)
+ {
+ s = def;
+ }
+ pattern += s;
+ }
+
+ return new SimpleDateFormat (pattern, loc);
+ }
+
+ public static final DateFormat getDateInstance ()
+ {
+ return getDateInstance (DEFAULT, Locale.getDefault());
+ }
+
+ public static final DateFormat getDateInstance (int style)
+ {
+ return getDateInstance (style, Locale.getDefault());
+ }
+
+ public static final DateFormat getDateInstance (int style, Locale loc)
+ {
+ return computeInstance (style, loc, true, false);
+ }
+
+ public static final DateFormat getDateTimeInstance ()
+ {
+ return getDateTimeInstance (DEFAULT, Locale.getDefault());
+ }
+
+ public static final DateFormat getDateTimeInstance (int style)
+ {
+ return getDateTimeInstance (style, Locale.getDefault());
+ }
+
+ public static final DateFormat getDateTimeInstance (int style, Locale loc)
+ {
+ return computeInstance (style, loc, true, true);
+ }
+
+ public static final DateFormat getInstance ()
+ {
+ // JCL book says SHORT.
+ return getDateTimeInstance (SHORT, Locale.getDefault());
+ }
+
+ public NumberFormat getNumberFormat ()
+ {
+ return numberFormat;
+ }
+
+ public static final DateFormat getTimeInstance ()
+ {
+ return getTimeInstance (DEFAULT, Locale.getDefault());
+ }
+
+ public static final DateFormat getTimeInstance (int style)
+ {
+ return getTimeInstance (style, Locale.getDefault());
+ }
+
+ public static final DateFormat getTimeInstance (int style, Locale loc)
+ {
+ return computeInstance (style, loc, false, true);
+ }
+
+ public TimeZone getTimeZone ()
+ {
+ return calendar.getTimeZone();
+ }
+
+ public int hashCode ()
+ {
+ int hash = calendar.hashCode();
+ if (numberFormat != null)
+ hash ^= numberFormat.hashCode();
+ return hash;
+ }
+
+ public boolean isLenient ()
+ {
+ return calendar.isLenient();
+ }
+
+ public Date parse (String source) throws ParseException
+ {
+ ParsePosition pos = new ParsePosition(0);
+ Date result = parse (source, pos);
+ if (result == null)
+ {
+ int index = pos.getErrorIndex();
+ if (index < 0)
+ index = pos.getIndex();
+ throw new ParseException("invalid Date syntax", index);
+ }
+ return result;
+ }
+
+ public abstract Date parse (String source, ParsePosition pos);
+
+ public Object parseObject (String source, ParsePosition pos)
+ {
+ return parse(source, pos);
+ }
+
+ public void setCalendar (Calendar calendar)
+ {
+ this.calendar = calendar;
+ }
+
+ public void setLenient (boolean lenient)
+ {
+ calendar.setLenient(lenient);
+ }
+
+ public void setNumberFormat (NumberFormat numberFormat)
+ {
+ this.numberFormat = numberFormat;
+ }
+
+ public void setTimeZone (TimeZone timeZone)
+ {
+ calendar.setTimeZone(timeZone);
+ }
+}
diff --git a/libjava/java/text/DateFormatSymbols.java b/libjava/java/text/DateFormatSymbols.java
new file mode 100644
index 00000000000..d21cdeada10
--- /dev/null
+++ b/libjava/java/text/DateFormatSymbols.java
@@ -0,0 +1,265 @@
+/* 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.text;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 24, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3.
+ * Status: Believed complete and correct.
+ */
+
+public class DateFormatSymbols extends Object
+ implements java.io.Serializable, Cloneable
+{
+ private String[] ampms;
+ private String[] eras;
+ private String localPatternChars;
+ private String[] months;
+ private String[] shortMonths;
+ private String[] shortWeekdays;
+ private String[] weekdays;
+ private String[][] zoneStrings;
+
+ private static final String[] ampmsDefault = {"AM", "PM" };
+ private static final String[] erasDefault = {"BC", "AD" };
+ // localPatternCharsDefault is used by SimpleDateFormat.
+ protected static final String localPatternCharsDefault
+ = "GyMdkHmsSEDFwWahKz";
+ private static final String[] monthsDefault = {
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December", ""
+ };
+ private static final String[] shortMonthsDefault = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""
+ };
+ private static final String[] shortWeekdaysDefault = {
+ "", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ };
+ private static final String[] weekdaysDefault = {
+ "", "Sunday", "Monday", "Tuesday",
+ "Wednesday", "Thursday", "Friday", "Saturday"
+ };
+
+ private 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 final Object safeGetResource (ResourceBundle res,
+ String key, Object def)
+ {
+ if (res != null)
+ {
+ try
+ {
+ return res.getObject(key);
+ }
+ catch (MissingResourceException x)
+ {
+ }
+ }
+ return def;
+ }
+
+ public DateFormatSymbols (Locale locale)
+ {
+ ResourceBundle res;
+ try
+ {
+ res = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", locale);
+ }
+ catch (MissingResourceException x)
+ {
+ res = null;
+ }
+ ampms = (String[]) safeGetResource (res, "ampm", ampmsDefault);
+ eras = (String[]) safeGetResource (res, "eras", erasDefault);
+ localPatternChars = (String) safeGetResource (res, "datePatternChars",
+ localPatternCharsDefault);
+ months = (String[]) safeGetResource (res, "months", monthsDefault);
+ shortMonths = (String[]) safeGetResource (res, "shortMonths",
+ shortMonthsDefault);
+ shortWeekdays = (String[]) safeGetResource (res, "shortWeekdays",
+ shortWeekdaysDefault);
+ weekdays = (String[]) safeGetResource (res, "weekdays", weekdaysDefault);
+ zoneStrings = (String[][]) safeGetResource (res, "zoneStrings",
+ zoneStringsDefault);
+ }
+
+ public DateFormatSymbols ()
+ {
+ this (Locale.getDefault());
+ }
+
+ public String[] getAmPmStrings()
+ {
+ return ampms;
+ }
+
+ public String[] getEras()
+ {
+ return eras;
+ }
+
+
+ public String getLocalPatternChars()
+ {
+ return localPatternChars;
+ }
+
+ public String[] getMonths ()
+ {
+ return months;
+ }
+
+ public String[] getShortMonths ()
+ {
+ return shortMonths;
+ }
+
+ public String[] getShortWeekdays ()
+ {
+ return shortWeekdays;
+ }
+
+ public String[] getWeekdays ()
+ {
+ return weekdays;
+ }
+
+ public String[] [] getZoneStrings ()
+ {
+ return zoneStrings;
+ }
+
+ public void setAmPmStrings (String[] value)
+ {
+ ampms = value;
+ }
+
+ public void setEras (String[] value)
+ {
+ eras = value;
+ }
+
+ public void setLocalPatternChars (String value)
+ {
+ localPatternChars = value;
+ }
+
+ public void setMonths (String[] value)
+ {
+ months = value;
+ }
+
+ public void setShortMonths (String[] value)
+ {
+ shortMonths = value;
+ }
+
+ public void setShortWeekdays (String[] value)
+ {
+ shortWeekdays = value;
+ }
+
+ public void setWeekdays (String[] value)
+ {
+ weekdays = value;
+ }
+
+ public void setZoneStrings (String[][] value)
+ {
+ zoneStrings = value;
+ }
+
+ /* Does a "deep" equality test - recurses into arrays. */
+ protected static boolean equals (Object x, Object y)
+ {
+ if (x == y)
+ return true;
+ if (x == null || y == null)
+ return false;
+ if (! (x instanceof Object[]) || ! (y instanceof Object[]))
+ return x.equals(y);
+ Object[] xa = (Object[]) x;
+ Object[] ya = (Object[]) y;
+ if (xa.length != ya.length)
+ return false;
+ for (int i = xa.length; --i >= 0; )
+ {
+ if (! equals(xa[i], ya[i]))
+ return false;
+ }
+ return true;
+ }
+
+ private static int hashCode (Object x)
+ {
+ if (x == null)
+ return 0;
+ if (! (x instanceof Object[]))
+ return x.hashCode();
+ Object[] xa = (Object[]) x;
+ int hash = 0;
+ for (int i = 0; i < xa.length; i++)
+ hash = 37 * hashCode(xa[i]);
+ return hash;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (obj == null || ! (obj instanceof DateFormatSymbols))
+ return false;
+ DateFormatSymbols other = (DateFormatSymbols) obj;
+ return (equals(ampms, other.ampms)
+ && equals(eras, other.eras)
+ && equals(localPatternChars, other.localPatternChars)
+ && equals(months, other.months)
+ && equals(shortMonths, other.shortMonths)
+ && equals(shortWeekdays, other.shortWeekdays)
+ && equals(weekdays, other.weekdays)
+ && equals(zoneStrings, other.zoneStrings));
+ }
+
+ public int hashCode ()
+ {
+ return (hashCode(ampms)
+ ^ hashCode(eras)
+ ^ hashCode(localPatternChars)
+ ^ hashCode(months)
+ ^ hashCode(shortMonths)
+ ^ hashCode(shortWeekdays)
+ ^ hashCode(weekdays)
+ ^ hashCode(zoneStrings));
+ }
+}
diff --git a/libjava/java/text/DecimalFormat.java b/libjava/java/text/DecimalFormat.java
new file mode 100644
index 00000000000..9ea9d921ec1
--- /dev/null
+++ b/libjava/java/text/DecimalFormat.java
@@ -0,0 +1,983 @@
+// DecimalFormat.java - Localized number formatting.
+
+/* 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 java.text;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date March 4, 1999
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.2, except serialization.
+ * Note however that the docs are very unclear about how format parsing
+ * should work. No doubt there are problems here.
+ */
+
+public class DecimalFormat extends NumberFormat
+{
+ // This is a helper for applyPatternWithSymbols. It reads a prefix
+ // or a suffix. It can cause some side-effects.
+ private final int scanFix (String pattern, int index, StringBuffer buf,
+ String patChars, DecimalFormatSymbols syms,
+ boolean is_suffix)
+ throws ParseException
+ {
+ int len = pattern.length();
+ buf.setLength(0);
+ boolean multiplierSet = false;
+ while (index < len)
+ {
+ char c = pattern.charAt(index);
+ if (c == '\'' && index + 1 < len
+ && pattern.charAt(index + 1) == '\'')
+ {
+ buf.append(c);
+ ++index;
+ }
+ else if (c == '\'' && index + 2 < len
+ && pattern.charAt(index + 2) == '\'')
+ {
+ buf.append(pattern.charAt(index + 1));
+ index += 2;
+ }
+ else if (c == '\u00a4')
+ {
+ if (index + 1 < len && pattern.charAt(index + 1) == '\u00a4')
+ {
+ buf.append(syms.getInternationalCurrencySymbol());
+ ++index;
+ }
+ else
+ buf.append(syms.getCurrencySymbol());
+ }
+ else if (is_suffix && c == syms.getPercent())
+ {
+ if (multiplierSet)
+ throw new ParseException ("multiplier already set", index);
+ multiplierSet = true;
+ multiplier = 100;
+ buf.append(c);
+ }
+ else if (is_suffix && c == syms.getPerMill())
+ {
+ if (multiplierSet)
+ throw new ParseException ("multiplier already set", index);
+ multiplierSet = true;
+ multiplier = 1000;
+ buf.append(c);
+ }
+ else if (patChars.indexOf(c) != -1)
+ {
+ // This is a pattern character.
+ break;
+ }
+ else
+ buf.append(c);
+ ++index;
+ }
+
+ return index;
+ }
+
+ // A helper which reads a number format.
+ private final int scanFormat (String pattern, int index,
+ String patChars, DecimalFormatSymbols syms,
+ boolean is_positive)
+ throws ParseException
+ {
+ int max = pattern.length();
+
+ int countSinceGroup = 0;
+ int zeroCount = 0;
+ boolean saw_group = false;
+
+ //
+ // Scan integer part.
+ //
+ while (index < max)
+ {
+ char c = pattern.charAt(index);
+
+ if (c == syms.getDigit())
+ {
+ if (zeroCount > 0)
+ throw new ParseException ("digit mark following zero", index);
+ ++countSinceGroup;
+ }
+ else if (c == syms.getZeroDigit())
+ {
+ ++zeroCount;
+ ++countSinceGroup;
+ }
+ else if (c == syms.getGroupingSeparator())
+ {
+ countSinceGroup = 0;
+ saw_group = true;
+ }
+ else
+ break;
+
+ ++index;
+ }
+
+ // We can only side-effect when parsing the positive format.
+ if (is_positive)
+ {
+ groupingUsed = saw_group;
+ groupingSize = (byte) countSinceGroup;
+ minimumIntegerDigits = zeroCount;
+ }
+
+ // Early termination.
+ if (index == max || pattern.charAt(index) == syms.getGroupingSeparator())
+ {
+ if (is_positive)
+ decimalSeparatorAlwaysShown = false;
+ return index;
+ }
+
+ if (pattern.charAt(index) == syms.getDecimalSeparator())
+ {
+ ++index;
+
+ //
+ // Scan fractional part.
+ //
+ int hashCount = 0;
+ zeroCount = 0;
+ while (index < max)
+ {
+ char c = pattern.charAt(index);
+ if (c == syms.getZeroDigit())
+ {
+ if (hashCount > 0)
+ throw new ParseException ("zero mark following digit",
+ index);
+ ++zeroCount;
+ }
+ else if (c == syms.getDigit())
+ {
+ ++hashCount;
+ }
+ else if (c != syms.getExponential()
+ && c != syms.getPatternSeparator()
+ && patChars.indexOf(c) != -1)
+ throw new ParseException ("unexpected special character",
+ index);
+ else
+ break;
+
+ ++index;
+ }
+
+ if (is_positive)
+ {
+ maximumFractionDigits = hashCount + zeroCount;
+ minimumFractionDigits = zeroCount;
+ }
+
+ if (index == max)
+ return index;
+ }
+
+ if (pattern.charAt(index) == syms.getExponential())
+ {
+ //
+ // Scan exponential format.
+ //
+ zeroCount = 0;
+ ++index;
+ while (index < max)
+ {
+ char c = pattern.charAt(index);
+ if (c == syms.getZeroDigit())
+ ++zeroCount;
+ else if (c == syms.getDigit())
+ {
+ if (zeroCount > 0)
+ throw new
+ ParseException ("digit mark following zero in exponent",
+ index);
+ }
+ else if (patChars.indexOf(c) != -1)
+ throw new ParseException ("unexpected special character",
+ index);
+ else
+ break;
+
+ ++index;
+ }
+
+ if (is_positive)
+ {
+ useExponentialNotation = true;
+ minExponentDigits = (byte) zeroCount;
+ }
+ }
+
+ return index;
+ }
+
+ // This helper function creates a string consisting of all the
+ // characters which can appear in a pattern and must be quoted.
+ private final String patternChars (DecimalFormatSymbols syms)
+ {
+ StringBuffer buf = new StringBuffer ();
+ buf.append(syms.getDecimalSeparator());
+ buf.append(syms.getDigit());
+ buf.append(syms.getExponential());
+ buf.append(syms.getGroupingSeparator());
+ // Adding this one causes pattern application to fail.
+ // Of course, omitting is causes toPattern to fail.
+ // ... but we already have bugs there. FIXME.
+ // buf.append(syms.getMinusSign());
+ buf.append(syms.getPatternSeparator());
+ buf.append(syms.getPercent());
+ buf.append(syms.getPerMill());
+ buf.append(syms.getZeroDigit());
+ buf.append('\u00a4');
+ return buf.toString();
+ }
+
+ private final void applyPatternWithSymbols (String pattern,
+ DecimalFormatSymbols syms)
+ throws ParseException
+ {
+ // Initialize to the state the parser expects.
+ negativePrefix = "";
+ negativeSuffix = "";
+ positivePrefix = "";
+ positiveSuffix = "";
+ decimalSeparatorAlwaysShown = false;
+ groupingSize = 0;
+ minExponentDigits = 0;
+ multiplier = 1;
+ useExponentialNotation = false;
+ groupingUsed = false;
+ maximumFractionDigits = 0;
+ maximumIntegerDigits = 309;
+ minimumFractionDigits = 0;
+ minimumIntegerDigits = 1;
+
+ StringBuffer buf = new StringBuffer ();
+ String patChars = patternChars (syms);
+
+ int max = pattern.length();
+ int index = scanFix (pattern, 0, buf, patChars, syms, false);
+ positivePrefix = buf.toString();
+
+ index = scanFormat (pattern, index, patChars, syms, true);
+
+ index = scanFix (pattern, index, buf, patChars, syms, true);
+ positiveSuffix = buf.toString();
+
+ if (index == pattern.length())
+ {
+ // No negative info.
+ negativePrefix = null;
+ negativeSuffix = null;
+ }
+ else
+ {
+ if (pattern.charAt(index) != syms.getPatternSeparator())
+ throw new ParseException ("separator character expected", index);
+
+ index = scanFix (pattern, index + 1, buf, patChars, syms, false);
+ negativePrefix = buf.toString();
+
+ // We parse the negative format for errors but we don't let
+ // it side-effect this object.
+ index = scanFormat (pattern, index, patChars, syms, false);
+
+ index = scanFix (pattern, index, buf, patChars, syms, true);
+ negativeSuffix = buf.toString();
+
+ if (index != pattern.length())
+ throw new ParseException ("end of pattern expected", index);
+ }
+ }
+
+ public void applyLocalizedPattern (String pattern) throws ParseException
+ {
+ applyPatternWithSymbols (pattern, symbols);
+ }
+
+ public void applyPattern (String pattern) throws ParseException
+ {
+ applyPatternWithSymbols (pattern, nonLocalizedSymbols);
+ }
+
+ public Object clone ()
+ {
+ return new DecimalFormat (this);
+ }
+
+ private DecimalFormat (DecimalFormat dup)
+ {
+ decimalSeparatorAlwaysShown = dup.decimalSeparatorAlwaysShown;
+ groupingSize = dup.groupingSize;
+ minExponentDigits = dup.minExponentDigits;
+ multiplier = dup.multiplier;
+ negativePrefix = dup.negativePrefix;
+ negativeSuffix = dup.negativeSuffix;
+ positivePrefix = dup.positivePrefix;
+ positiveSuffix = dup.positiveSuffix;
+ symbols = (DecimalFormatSymbols) dup.symbols.clone();
+ useExponentialNotation = dup.useExponentialNotation;
+ }
+
+ public DecimalFormat ()
+ {
+ this ("#,##0.###");
+ }
+
+ public DecimalFormat (String pattern)
+ {
+ this (pattern, new DecimalFormatSymbols ());
+ }
+
+ public DecimalFormat (String pattern, DecimalFormatSymbols symbols)
+ {
+ this.symbols = symbols;
+ // The docs imply that the constructor turns a ParseException
+ // into an IllegalArgumentException.
+ try
+ {
+ applyPattern (pattern);
+ }
+ catch (ParseException x)
+ {
+ throw new IllegalArgumentException (x.getMessage());
+ }
+ }
+
+ private final boolean equals (String s1, String s2)
+ {
+ if (s1 == null || s2 == null)
+ return s1 == s2;
+ return s1.equals(s2);
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof DecimalFormat))
+ return false;
+ DecimalFormat dup = (DecimalFormat) obj;
+ return (decimalSeparatorAlwaysShown == dup.decimalSeparatorAlwaysShown
+ && groupingSize == dup.groupingSize
+ && minExponentDigits == dup.minExponentDigits
+ && multiplier == dup.multiplier
+ && equals(negativePrefix, dup.negativePrefix)
+ && equals(negativeSuffix, dup.negativeSuffix)
+ && equals(positivePrefix, dup.positivePrefix)
+ && equals(positiveSuffix, dup.positiveSuffix)
+ && symbols.equals(dup.symbols)
+ && useExponentialNotation == dup.useExponentialNotation);
+ }
+
+ public StringBuffer format (double number, StringBuffer dest,
+ FieldPosition fieldPos)
+ {
+ // A very special case.
+ if (Double.isNaN(number))
+ {
+ dest.append(symbols.getNaN());
+ if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
+ {
+ int index = dest.length();
+ fieldPos.setBeginIndex(index - symbols.getNaN().length());
+ fieldPos.setEndIndex(index);
+ }
+ return dest;
+ }
+
+ boolean is_neg = number < 0;
+ if (is_neg)
+ {
+ if (negativePrefix != null)
+ dest.append(negativePrefix);
+ else
+ {
+ dest.append(symbols.getMinusSign());
+ dest.append(positivePrefix);
+ }
+ number = - number;
+ }
+ else
+ dest.append(positivePrefix);
+
+ int integerBeginIndex = dest.length();
+ int integerEndIndex = 0;
+ if (Double.isInfinite (number))
+ {
+ dest.append(symbols.getInfinity());
+ integerEndIndex = dest.length();
+ }
+ else
+ {
+ number *= multiplier;
+
+ // Compute exponent.
+ long exponent = 0;
+ double baseNumber;
+ if (useExponentialNotation)
+ {
+ exponent = (long) (Math.log(number) / Math.log(10));
+ if (minimumIntegerDigits > 0)
+ exponent -= minimumIntegerDigits - 1;
+ baseNumber = (long) (number / Math.pow(10.0, exponent));
+ }
+ else
+ baseNumber = number;
+
+ // Round to the correct number of digits.
+ baseNumber += 5 * Math.pow(10.0, - maximumFractionDigits - 1);
+
+ int index = dest.length();
+ double intPart = Math.floor(baseNumber);
+ int count = 0;
+ while (count < maximumIntegerDigits
+ && (intPart > 0 || count < minimumIntegerDigits))
+ {
+ long dig = (long) (intPart % 10);
+ intPart = Math.floor(intPart / 10);
+
+ // Append group separator if required.
+ if (groupingUsed && count > 0 && count % groupingSize == 0)
+ dest.insert(index, symbols.getGroupingSeparator());
+
+ dest.insert(index, (char) (symbols.getZeroDigit() + dig));
+
+ ++count;
+ }
+
+ integerEndIndex = dest.length();
+
+ int decimal_index = integerEndIndex;
+ int consecutive_zeros = 0;
+ int total_digits = 0;
+
+ // Strip integer part from NUMBER.
+ double fracPart = baseNumber - Math.floor(baseNumber);
+ for (count = 0;
+ count < maximumFractionDigits
+ && (fracPart != 0 || count < minimumFractionDigits);
+ ++count)
+ {
+ ++total_digits;
+ fracPart *= 10;
+ long dig = (long) fracPart;
+ if (dig == 0)
+ ++consecutive_zeros;
+ else
+ consecutive_zeros = 0;
+ dest.append((char) (symbols.getZeroDigit() + dig));
+
+ // Strip integer part from FRACPART.
+ fracPart = fracPart - Math.floor (fracPart);
+ }
+
+ // Strip extraneous trailing `0's. We can't always detect
+ // these in the loop.
+ int extra_zeros = Math.min (consecutive_zeros,
+ total_digits - minimumFractionDigits);
+ if (extra_zeros > 0)
+ {
+ dest.setLength(dest.length() - extra_zeros);
+ total_digits -= extra_zeros;
+ }
+
+ // If required, add the decimal symbol.
+ if (decimalSeparatorAlwaysShown
+ || total_digits > 0)
+ {
+ dest.insert(decimal_index, symbols.getDecimalSeparator());
+ if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
+ {
+ fieldPos.setBeginIndex(decimal_index + 1);
+ fieldPos.setEndIndex(dest.length());
+ }
+ }
+
+ // Finally, print the exponent.
+ if (useExponentialNotation)
+ {
+ dest.append(symbols.getExponential());
+ dest.append(exponent < 0 ? '-' : '+');
+ index = dest.length();
+ for (count = 0;
+ exponent > 0 || count < minExponentDigits;
+ ++count)
+ {
+ long dig = exponent % 10;
+ exponent /= 10;
+ dest.insert(index, (char) (symbols.getZeroDigit() + dig));
+ }
+ }
+ }
+
+ if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
+ {
+ fieldPos.setBeginIndex(integerBeginIndex);
+ fieldPos.setEndIndex(integerEndIndex);
+ }
+
+ dest.append((is_neg && negativeSuffix != null)
+ ? negativeSuffix
+ : positiveSuffix);
+ return dest;
+ }
+
+ public StringBuffer format (long number, StringBuffer dest,
+ FieldPosition fieldPos)
+ {
+ // If using exponential notation, we just format as a double.
+ if (useExponentialNotation)
+ return format ((double) number, dest, fieldPos);
+
+ boolean is_neg = number < 0;
+ if (is_neg)
+ {
+ if (negativePrefix != null)
+ dest.append(negativePrefix);
+ else
+ {
+ dest.append(symbols.getMinusSign());
+ dest.append(positivePrefix);
+ }
+ number = - number;
+ }
+ else
+ dest.append(positivePrefix);
+
+ int integerBeginIndex = dest.length();
+ int index = dest.length();
+ int count = 0;
+ while (count < maximumIntegerDigits
+ && (number > 0 || count < minimumIntegerDigits))
+ {
+ long dig = number % 10;
+ number /= 10;
+ // NUMBER and DIG will be less than 0 if the original number
+ // was the most negative long.
+ if (dig < 0)
+ {
+ dig = - dig;
+ number = - number;
+ }
+
+ // Append group separator if required.
+ if (groupingUsed && count > 0 && count % groupingSize == 0)
+ dest.insert(index, symbols.getGroupingSeparator());
+
+ dest.insert(index, (char) (symbols.getZeroDigit() + dig));
+
+ ++count;
+ }
+
+ if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
+ {
+ fieldPos.setBeginIndex(integerBeginIndex);
+ fieldPos.setEndIndex(dest.length());
+ }
+
+ if (decimalSeparatorAlwaysShown || minimumFractionDigits > 0)
+ {
+ dest.append(symbols.getDecimalSeparator());
+ if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
+ {
+ fieldPos.setBeginIndex(dest.length());
+ fieldPos.setEndIndex(dest.length() + minimumFractionDigits);
+ }
+ }
+
+ for (count = 0; count < minimumFractionDigits; ++count)
+ dest.append(symbols.getZeroDigit());
+
+ dest.append((is_neg && negativeSuffix != null)
+ ? negativeSuffix
+ : positiveSuffix);
+ return dest;
+ }
+
+ public DecimalFormatSymbols getDecimalFormatSymbols ()
+ {
+ return symbols;
+ }
+
+ public int getGroupingSize ()
+ {
+ return groupingSize;
+ }
+
+ public int getMultiplier ()
+ {
+ return multiplier;
+ }
+
+ public String getNegativePrefix ()
+ {
+ return negativePrefix;
+ }
+
+ public String getNegativeSuffix ()
+ {
+ return negativeSuffix;
+ }
+
+ public String getPositivePrefix ()
+ {
+ return positivePrefix;
+ }
+
+ public String getPositiveSuffix ()
+ {
+ return positiveSuffix;
+ }
+
+ public int hashCode ()
+ {
+ int hash = (negativeSuffix.hashCode() ^ negativePrefix.hashCode()
+ ^positivePrefix.hashCode() ^ positiveSuffix.hashCode());
+ // FIXME.
+ return hash;
+ }
+
+ public boolean isDecimalSeparatorAlwaysShown ()
+ {
+ return decimalSeparatorAlwaysShown;
+ }
+
+ public Number parse (String str, ParsePosition pos)
+ {
+ // Our strategy is simple: copy the text into a buffer,
+ // translating or omitting locale-specific information. Then
+ // let Double or Long convert the number for us.
+
+ boolean is_neg = false;
+ int index = pos.getIndex();
+ StringBuffer buf = new StringBuffer ();
+
+ // We have to check both prefixes, because one might be empty.
+ // We want to pick the longest prefix that matches.
+ boolean got_pos = str.startsWith(positivePrefix, index);
+ String np = (negativePrefix != null
+ ? negativePrefix
+ : positivePrefix + symbols.getMinusSign());
+ boolean got_neg = str.startsWith(np, index);
+
+ if (got_pos && got_neg)
+ {
+ // By checking this way, we preserve ambiguity in the case
+ // where the negative format differs only in suffix. We
+ // check this again later.
+ if (np.length() > positivePrefix.length())
+ {
+ is_neg = true;
+ index += np.length();
+ }
+ else
+ index += positivePrefix.length();
+ }
+ else if (got_neg)
+ {
+ is_neg = true;
+ index += np.length();
+ }
+ else if (got_pos)
+ index += positivePrefix.length();
+ else
+ {
+ pos.setErrorIndex (index);
+ return null;
+ }
+
+ // FIXME: handle Inf and NaN.
+
+ // FIXME: do we have to respect minimum/maxmimum digit stuff?
+ // What about leading zeros? What about multiplier?
+
+ int start_index = index;
+ int max = str.length();
+ char zero = symbols.getZeroDigit();
+ int last_group = -1;
+ boolean int_part = true;
+ boolean exp_part = false;
+ for (; index < max; ++index)
+ {
+ char c = str.charAt(index);
+
+ // FIXME: what about grouping size?
+ if (groupingUsed && c == symbols.getGroupingSeparator())
+ {
+ if (last_group != -1
+ && (index - last_group) % groupingSize != 0)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ last_group = index;
+ }
+ else if (c >= zero && c <= zero + 9)
+ {
+ buf.append((char) (c - zero + '0'));
+ exp_part = false;
+ }
+ else if (parseIntegerOnly)
+ break;
+ else if (c == symbols.getDecimalSeparator())
+ {
+ if (last_group != -1
+ && (index - last_group) % groupingSize != 0)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ buf.append('.');
+ int_part = false;
+ }
+ else if (c == symbols.getExponential())
+ {
+ buf.append('E');
+ int_part = false;
+ exp_part = true;
+ }
+ else if (exp_part
+ && (c == '+' || c == '-' || c == symbols.getMinusSign()))
+ {
+ // For exponential notation.
+ buf.append(c);
+ }
+ else
+ break;
+ }
+
+ if (index == start_index)
+ {
+ // Didn't see any digits.
+ pos.setErrorIndex(index);
+ return null;
+ }
+
+ // Check the suffix. We must do this before converting the
+ // buffer to a number to handle the case of a number which is
+ // the most negative Long.
+ boolean got_pos_suf = str.startsWith(positiveSuffix, index);
+ String ns = (negativePrefix == null ? positiveSuffix : negativeSuffix);
+ boolean got_neg_suf = str.startsWith(ns, index);
+ if (is_neg)
+ {
+ if (! got_neg_suf)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ }
+ else if (got_pos && got_neg && got_neg_suf)
+ {
+ is_neg = true;
+ }
+ else if (got_pos != got_pos_suf && got_neg != got_neg_suf)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+
+ String suffix = is_neg ? ns : positiveSuffix;
+ if (is_neg)
+ buf.insert(0, '-');
+
+ String t = buf.toString();
+ Number result = null;
+ try
+ {
+ result = new Long (t);
+ }
+ catch (NumberFormatException x1)
+ {
+ try
+ {
+ result = new Double (t);
+ }
+ catch (NumberFormatException x2)
+ {
+ }
+ }
+ if (result == null)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+
+ pos.setIndex(index + suffix.length());
+
+ return result;
+ }
+
+ public void setDecimalFormatSymbols (DecimalFormatSymbols newSymbols)
+ {
+ symbols = newSymbols;
+ }
+
+ public void setDecimalSeparatorAlwaysShown (boolean newValue)
+ {
+ decimalSeparatorAlwaysShown = newValue;
+ }
+
+ public void setGroupingSize (int groupSize)
+ {
+ groupingSize = (byte) groupSize;
+ }
+
+ public void setMaximumFractionDigits (int newValue)
+ {
+ maximumFractionDigits = Math.min(newValue, 340);
+ }
+
+ public void setMaximumIntegerDigits (int newValue)
+ {
+ maximumIntegerDigits = Math.min(newValue, 309);
+ }
+
+ public void setMinimumFractionDigits (int newValue)
+ {
+ minimumFractionDigits = Math.min(newValue, 340);
+ }
+
+ public void setMinimumIntegerDigits (int newValue)
+ {
+ minimumIntegerDigits = Math.min(newValue, 309);
+ }
+
+ public void setMultiplier (int newValue)
+ {
+ multiplier = newValue;
+ }
+
+ public void setNegativePrefix (String newValue)
+ {
+ negativePrefix = newValue;
+ }
+
+ public void setNegativeSuffix (String newValue)
+ {
+ negativeSuffix = newValue;
+ }
+
+ public void setPositivePrefix (String newValue)
+ {
+ positivePrefix = newValue;
+ }
+
+ public void setPositiveSuffix (String newValue)
+ {
+ positiveSuffix = newValue;
+ }
+
+ private final void quoteFix (StringBuffer buf, String text, String patChars)
+ {
+ int len = text.length();
+ for (int index = 0; index < len; ++index)
+ {
+ char c = text.charAt(index);
+ if (patChars.indexOf(c) != -1)
+ {
+ buf.append('\'');
+ buf.append(c);
+ buf.append('\'');
+ }
+ else
+ buf.append(c);
+ }
+ }
+
+ private final String computePattern (DecimalFormatSymbols syms)
+ {
+ StringBuffer mainPattern = new StringBuffer ();
+ // We have to at least emit a zero for the minimum number of
+ // digits. Past that we need hash marks up to the grouping
+ // separator (and one beyond).
+ int total_digits = Math.max(minimumIntegerDigits,
+ groupingUsed ? groupingSize + 1: 0);
+ for (int i = 0; i < total_digits - minimumIntegerDigits; ++i)
+ mainPattern.append(syms.getDigit());
+ for (int i = total_digits - minimumIntegerDigits; i < total_digits; ++i)
+ mainPattern.append(syms.getZeroDigit());
+ // Inserting the gropuing operator afterwards is easier.
+ if (groupingUsed)
+ mainPattern.insert(mainPattern.length() - groupingSize,
+ syms.getGroupingSeparator());
+ // See if we need decimal info.
+ if (minimumFractionDigits > 0 || maximumFractionDigits > 0
+ || decimalSeparatorAlwaysShown)
+ mainPattern.append(syms.getDecimalSeparator());
+ for (int i = 0; i < minimumFractionDigits; ++i)
+ mainPattern.append(syms.getZeroDigit());
+ for (int i = minimumFractionDigits; i < maximumFractionDigits; ++i)
+ mainPattern.append(syms.getDigit());
+ if (useExponentialNotation)
+ {
+ mainPattern.append(syms.getExponential());
+ for (int i = 0; i < minExponentDigits; ++i)
+ mainPattern.append(syms.getZeroDigit());
+ if (minExponentDigits == 0)
+ mainPattern.append(syms.getDigit());
+ }
+
+ String main = mainPattern.toString();
+ String patChars = patternChars (syms);
+ mainPattern.setLength(0);
+
+ quoteFix (mainPattern, positivePrefix, patChars);
+ mainPattern.append(main);
+ quoteFix (mainPattern, positiveSuffix, patChars);
+
+ if (negativePrefix != null)
+ {
+ quoteFix (mainPattern, negativePrefix, patChars);
+ mainPattern.append(main);
+ quoteFix (mainPattern, negativeSuffix, patChars);
+ }
+
+ return mainPattern.toString();
+ }
+
+ public String toLocalizedPattern ()
+ {
+ return computePattern (symbols);
+ }
+
+ public String toPattern ()
+ {
+ return computePattern (nonLocalizedSymbols);
+ }
+
+ // These names are fixed by the serialization spec.
+ private boolean decimalSeparatorAlwaysShown;
+ private byte groupingSize;
+ private byte minExponentDigits;
+ private int multiplier;
+ private String negativePrefix;
+ private String negativeSuffix;
+ private String positivePrefix;
+ private String positiveSuffix;
+ private DecimalFormatSymbols symbols;
+ private boolean useExponentialNotation;
+
+ // The locale-independent pattern symbols happen to be the same as
+ // the US symbols.
+ private static final DecimalFormatSymbols nonLocalizedSymbols
+ = new DecimalFormatSymbols (Locale.US);
+}
diff --git a/libjava/java/text/DecimalFormatSymbols.java b/libjava/java/text/DecimalFormatSymbols.java
new file mode 100644
index 00000000000..783cb6f7f50
--- /dev/null
+++ b/libjava/java/text/DecimalFormatSymbols.java
@@ -0,0 +1,293 @@
+// DecimalFormatSymbols.java - Symbols used to format numbers.
+
+/* 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 java.text;
+
+import java.io.Serializable;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date February 24, 1999
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.2, except serialization.
+ */
+
+public final class DecimalFormatSymbols implements Cloneable, Serializable
+{
+ public Object clone ()
+ {
+ return new DecimalFormatSymbols (this);
+ }
+
+ private DecimalFormatSymbols (DecimalFormatSymbols orig)
+ {
+ this.currencySymbol = orig.currencySymbol;
+ this.decimalSeparator = orig.decimalSeparator;
+ this.digit = orig.digit;
+ this.exponential = orig.exponential;
+ this.groupingSeparator = orig.groupingSeparator;
+ this.infinity = orig.infinity;
+ this.intlCurrencySymbol = orig.intlCurrencySymbol;
+ this.minusSign = orig.minusSign;
+ this.NaN = orig.NaN;
+ this.patternSeparator = orig.patternSeparator;
+ this.percent = orig.percent;
+ this.perMill = orig.perMill;
+ this.zeroDigit = orig.zeroDigit;
+ }
+
+ public DecimalFormatSymbols ()
+ {
+ this (Locale.getDefault());
+ }
+
+ private final String safeGetString (ResourceBundle bundle,
+ String name, String def)
+ {
+ if (bundle != null)
+ {
+ try
+ {
+ return bundle.getString(name);
+ }
+ catch (MissingResourceException x)
+ {
+ }
+ }
+ return def;
+ }
+
+ public final char safeGetChar (ResourceBundle bundle,
+ String name, char def)
+ {
+ String r = null;
+ if (bundle != null)
+ {
+ try
+ {
+ r = bundle.getString(name);
+ }
+ catch (MissingResourceException x)
+ {
+ }
+ }
+ if (r == null || r.length() < 1)
+ return def;
+ return r.charAt(0);
+ }
+
+ public DecimalFormatSymbols (Locale loc)
+ {
+ ResourceBundle res;
+ try
+ {
+ res = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", loc);
+ }
+ catch (MissingResourceException x)
+ {
+ res = null;
+ }
+ currencySymbol = safeGetString (res, "currencySymbol", "$");
+ decimalSeparator = safeGetChar (res, "decimalSeparator", '.');
+ digit = safeGetChar (res, "digit", '#');
+ exponential = safeGetChar (res, "exponential", 'E');
+ groupingSeparator = safeGetChar (res, "groupingSeparator", ',');
+ infinity = safeGetString (res, "infinity", "\u221e");
+ // FIXME: default?
+ intlCurrencySymbol = safeGetString (res, "intlCurrencySymbol", "$");
+ minusSign = safeGetChar (res, "minusSign", '-');
+ NaN = safeGetString (res, "NaN", "\ufffd");
+ patternSeparator = safeGetChar (res, "patternSeparator", ';');
+ percent = safeGetChar (res, "percent", '%');
+ perMill = safeGetChar (res, "perMill", '\u2030');
+ zeroDigit = safeGetChar (res, "zeroDigit", '0');
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof DecimalFormatSymbols))
+ return false;
+ DecimalFormatSymbols dfs = (DecimalFormatSymbols) obj;
+ return (currencySymbol.equals(dfs.currencySymbol)
+ && decimalSeparator == dfs.decimalSeparator
+ && digit == dfs.digit
+ && exponential == dfs.exponential
+ && groupingSeparator == dfs.groupingSeparator
+ && infinity.equals(dfs.infinity)
+ && intlCurrencySymbol.equals(dfs.intlCurrencySymbol)
+ && minusSign == dfs.minusSign
+ && NaN.equals(dfs.NaN)
+ && patternSeparator == dfs.patternSeparator
+ && percent == dfs.percent
+ && perMill == dfs.perMill
+ && zeroDigit == dfs.zeroDigit);
+ }
+
+ public String getCurrencySymbol ()
+ {
+ return currencySymbol;
+ }
+
+ public char getDecimalSeparator ()
+ {
+ return decimalSeparator;
+ }
+
+ public char getDigit ()
+ {
+ return digit;
+ }
+
+ // This is our own extension.
+ char getExponential ()
+ {
+ return exponential;
+ }
+
+ public char getGroupingSeparator ()
+ {
+ return groupingSeparator;
+ }
+
+ public String getInfinity ()
+ {
+ return infinity;
+ }
+
+ public String getInternationalCurrencySymbol ()
+ {
+ return intlCurrencySymbol;
+ }
+
+ public char getMinusSign ()
+ {
+ return minusSign;
+ }
+
+ public String getNaN ()
+ {
+ return NaN;
+ }
+
+ public char getPatternSeparator ()
+ {
+ return patternSeparator;
+ }
+
+ public char getPercent ()
+ {
+ return percent;
+ }
+
+ public char getPerMill ()
+ {
+ return perMill;
+ }
+
+ public char getZeroDigit ()
+ {
+ return zeroDigit;
+ }
+
+ public int hashCode ()
+ {
+ // Compute based on zero digit, grouping separator, and decimal
+ // separator -- JCL book. This probably isn't a very good hash
+ // code.
+ return zeroDigit << 16 + groupingSeparator << 8 + decimalSeparator;
+ }
+
+ public void setCurrenySymbol (String currency)
+ {
+ currencySymbol = currency;
+ }
+
+ public void setDecimalSeparator (char decimalSep)
+ {
+ decimalSeparator = decimalSep;
+ }
+
+ public void setDigit (char digit)
+ {
+ this.digit = digit;
+ }
+
+ // This is our own extension.
+ void setExponential (char exp)
+ {
+ exponential = exp;
+ }
+
+ public void setGroupingSeparator (char groupSep)
+ {
+ groupingSeparator = groupSep;
+ }
+
+ public void setInfinity (String infinity)
+ {
+ this.infinity = infinity;
+ }
+
+ public void setInternationalCurrencySymbol (String currency)
+ {
+ intlCurrencySymbol = currency;
+ }
+
+ public void setMinusSign (char minusSign)
+ {
+ this.minusSign = minusSign;
+ }
+
+ public void setNaN (String nan)
+ {
+ NaN = nan;
+ }
+
+ public void setPatternSeparator (char patternSep)
+ {
+ patternSeparator = patternSep;
+ }
+
+ public void setPercent (char percent)
+ {
+ this.percent = percent;
+ }
+
+ public void setPerMill (char perMill)
+ {
+ this.perMill = perMill;
+ }
+
+ public void setZeroDigit (char zeroDigit)
+ {
+ this.zeroDigit = zeroDigit;
+ }
+
+ // The names of the instance variables are fixed by the
+ // serialization spec.
+ private String currencySymbol;
+ private char decimalSeparator;
+ private char digit;
+ private char exponential;
+ private char groupingSeparator;
+ private String infinity;
+ private String intlCurrencySymbol;
+ private char minusSign;
+ private String NaN;
+ private char patternSeparator;
+ private char percent;
+ private char perMill;
+ private char zeroDigit;
+}
diff --git a/libjava/java/text/FieldPosition.java b/libjava/java/text/FieldPosition.java
new file mode 100644
index 00000000000..2f8c0935b48
--- /dev/null
+++ b/libjava/java/text/FieldPosition.java
@@ -0,0 +1,65 @@
+/* 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.text;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 25, 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.
+ * Includes JDK 1.2 methods.
+ */
+
+public class FieldPosition
+{
+ int field;
+ int beginIndex;
+ int endIndex;
+
+ public FieldPosition (int field)
+ {
+ this.field = field;
+ }
+
+ public int getField ()
+ {
+ return field;
+ }
+
+ public int getBeginIndex ()
+ {
+ return beginIndex;
+ }
+
+ public int getEndIndex ()
+ {
+ return endIndex;
+ }
+
+ public void setBeginIndex (int index)
+ {
+ beginIndex = index;
+ }
+
+ public void setEndIndex (int index)
+ {
+ endIndex = index;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof FieldPosition))
+ return false;
+ FieldPosition other = (FieldPosition) obj;
+ return (field == other.field
+ && beginIndex == other.beginIndex && endIndex == other.endIndex);
+ }
+}
diff --git a/libjava/java/text/Format.java b/libjava/java/text/Format.java
new file mode 100644
index 00000000000..d2c918b9072
--- /dev/null
+++ b/libjava/java/text/Format.java
@@ -0,0 +1,51 @@
+/* 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.text;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 25, 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 Format implements java.io.Serializable, Cloneable
+{
+ public Format ()
+ {
+ }
+
+ public abstract StringBuffer format (Object obj,
+ StringBuffer sbuf, FieldPosition pos);
+
+ public final String format (Object obj)
+ {
+ StringBuffer sbuf = new StringBuffer();
+ format(obj, sbuf, new FieldPosition(0));
+ return sbuf.toString();
+ }
+
+ public abstract Object parseObject (String source, ParsePosition pos);
+
+ public Object parseObject (String source) throws ParseException
+ {
+ ParsePosition pos = new ParsePosition(0);
+ Object result = parseObject (source, pos);
+ if (result == null)
+ {
+ int index = pos.getErrorIndex();
+ if (index < 0)
+ index = pos.getIndex();
+ throw new ParseException("parseObject failed", index);
+ }
+ return result;
+ }
+}
diff --git a/libjava/java/text/MessageFormat.java b/libjava/java/text/MessageFormat.java
new file mode 100644
index 00000000000..8b422357966
--- /dev/null
+++ b/libjava/java/text/MessageFormat.java
@@ -0,0 +1,543 @@
+// MessageFormat.java - Localized message formatting.
+
+/* 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 java.text;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.Vector;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date March 3, 1999
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.2, except serialization.
+ * and parsing.
+ */
+
+final class MessageFormatElement
+{
+ // Argument number.
+ int argNumber;
+ // Formatter to be used. This is the format set by setFormat.
+ Format setFormat;
+ // Formatter to be used based on the type.
+ Format format;
+
+ // Argument will be checked to make sure it is an instance of this
+ // class.
+ Class formatClass;
+
+ // Formatter type.
+ String type;
+ // Formatter style.
+ String style;
+
+ // Text to follow this element.
+ String trailer;
+
+ // FIXME: shouldn't need this.
+ Class forName (String name)
+ {
+ try
+ {
+ return Class.forName (name);
+ }
+ catch (ClassNotFoundException x)
+ {
+ }
+ return null;
+ }
+
+ // Recompute the locale-based formatter.
+ void setLocale (Locale loc)
+ {
+ if (type == null)
+ ;
+ else if (type.equals("number"))
+ {
+ // FIXME: named class literal.
+ // formatClass = Number.class;
+ formatClass = forName ("java.lang.Number");
+
+ if (style == null)
+ format = NumberFormat.getInstance(loc);
+ else if (style.equals("currency"))
+ format = NumberFormat.getCurrencyInstance(loc);
+ else if (style.equals("percent"))
+ format = NumberFormat.getPercentInstance(loc);
+ else if (style.equals("integer"))
+ {
+ NumberFormat nf = NumberFormat.getNumberInstance(loc);
+ nf.setMaximumFractionDigits(0);
+ nf.setGroupingUsed(false);
+ format = nf;
+ }
+ else
+ {
+ format = NumberFormat.getNumberInstance(loc);
+ DecimalFormat df = (DecimalFormat) format;
+ try
+ {
+ df.applyPattern(style);
+ }
+ catch (ParseException x)
+ {
+ throw new IllegalArgumentException (x.getMessage());
+ }
+ }
+ }
+ else if (type.equals("time") || type.equals("date"))
+ {
+ // FIXME: named class literal.
+ // formatClass = Date.class;
+ formatClass = forName ("java.util.Date");
+
+ int val = DateFormat.DEFAULT;
+ if (style == null)
+ ;
+ if (style.equals("short"))
+ val = DateFormat.SHORT;
+ else if (style.equals("medium"))
+ val = DateFormat.MEDIUM;
+ else if (style.equals("long"))
+ val = DateFormat.LONG;
+ else if (style.equals("full"))
+ val = DateFormat.FULL;
+
+ if (type.equals("time"))
+ format = DateFormat.getTimeInstance(val, loc);
+ else
+ format = DateFormat.getDateInstance(val, loc);
+
+ if (style != null && val == DateFormat.DEFAULT)
+ {
+ SimpleDateFormat sdf = (SimpleDateFormat) format;
+ sdf.applyPattern(style);
+ }
+ }
+ else if (type.equals("choice"))
+ {
+ // FIXME: named class literal.
+ // formatClass = Number.class;
+ formatClass = forName ("java.lang.Number");
+
+ if (style == null)
+ throw new
+ IllegalArgumentException ("style required for choice format");
+ format = new ChoiceFormat (style);
+ }
+ }
+}
+
+public class MessageFormat extends Format
+{
+ // Helper that returns the text up to the next format opener. The
+ // text is put into BUFFER. Returns index of character after end of
+ // string. Throws IllegalArgumentException on error.
+ private static final int scanString (String pat, int index,
+ StringBuffer buffer)
+ {
+ int max = pat.length();
+ buffer.setLength(0);
+ for (; index < max; ++index)
+ {
+ char c = pat.charAt(index);
+ if (c == '\'' && index + 2 < max && pat.charAt(index + 2) == '\'')
+ {
+ buffer.append(pat.charAt(index + 1));
+ index += 2;
+ }
+ else if (c == '\'' && index + 1 < max
+ && pat.charAt(index + 1) == '\'')
+ {
+ buffer.append(c);
+ ++index;
+ }
+ else if (c == '{')
+ break;
+ else if (c == '}')
+ throw new IllegalArgumentException ();
+ else
+ buffer.append(c);
+ }
+ return index;
+ }
+
+ // This helper retrieves a single part of a format element. Returns
+ // the index of the terminating character.
+ private static final int scanFormatElement (String pat, int index,
+ StringBuffer buffer,
+ char term)
+ {
+ int max = pat.length();
+ buffer.setLength(0);
+ int brace_depth = 1;
+
+ for (; index < max; ++index)
+ {
+ char c = pat.charAt(index);
+ if (c == '\'' && index + 2 < max && pat.charAt(index + 2) == '\'')
+ {
+ buffer.append(c);
+ buffer.append(pat.charAt(index + 1));
+ buffer.append(c);
+ index += 2;
+ }
+ else if (c == '\'' && index + 1 < max
+ && pat.charAt(index + 1) == '\'')
+ {
+ buffer.append(c);
+ ++index;
+ }
+ else if (c == '{')
+ {
+ buffer.append(c);
+ ++brace_depth;
+ }
+ else if (c == '}')
+ {
+ if (--brace_depth == 0)
+ break;
+ buffer.append(c);
+ }
+ // Check for TERM after braces, because TERM might be `}'.
+ else if (c == term)
+ break;
+ else
+ buffer.append(c);
+ }
+ return index;
+ }
+
+ // This is used to parse a format element and whatever non-format
+ // text might trail it.
+ private static final int scanFormat (String pat, int index,
+ StringBuffer buffer, Vector elts,
+ Locale locale)
+ {
+ MessageFormatElement mfe = new MessageFormatElement ();
+ elts.addElement(mfe);
+
+ int max = pat.length();
+
+ // Skip the opening `{'.
+ ++index;
+
+ // Fetch the argument number.
+ index = scanFormatElement (pat, index, buffer, ',');
+ try
+ {
+ mfe.argNumber = Integer.parseInt(buffer.toString());
+ }
+ catch (NumberFormatException nfx)
+ {
+ throw new IllegalArgumentException ();
+ }
+
+ // Extract the element format.
+ if (index < max && pat.charAt(index) == ',')
+ {
+ index = scanFormatElement (pat, index + 1, buffer, ',');
+ mfe.type = buffer.toString();
+
+ // Extract the style.
+ if (index < max && pat.charAt(index) == ',')
+ {
+ index = scanFormatElement (pat, index + 1, buffer, '}');
+ mfe.style = buffer.toString ();
+ }
+ }
+
+ // Advance past the last terminator.
+ if (index >= max || pat.charAt(index) != '}')
+ throw new IllegalArgumentException ();
+ ++index;
+
+ // Now fetch trailing string.
+ index = scanString (pat, index, buffer);
+ mfe.trailer = buffer.toString ();
+
+ mfe.setLocale(locale);
+
+ return index;
+ }
+
+ public void applyPattern (String newPattern)
+ {
+ pattern = newPattern;
+
+ StringBuffer tempBuffer = new StringBuffer ();
+
+ int index = scanString (newPattern, 0, tempBuffer);
+ leader = tempBuffer.toString();
+
+ Vector elts = new Vector ();
+ while (index < newPattern.length())
+ index = scanFormat (newPattern, index, tempBuffer, elts, locale);
+
+ elements = new MessageFormatElement[elts.size()];
+ elts.copyInto(elements);
+ }
+
+ public Object clone ()
+ {
+ MessageFormat c = new MessageFormat ();
+ c.setLocale(locale);
+ c.applyPattern(pattern);
+ return (Object) c;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof MessageFormat))
+ return false;
+ MessageFormat mf = (MessageFormat) obj;
+ return (pattern.equals(mf.pattern)
+ && locale.equals(mf.locale));
+ }
+
+ public static String format (String pattern, Object arguments[])
+ {
+ MessageFormat mf = new MessageFormat (pattern);
+ StringBuffer sb = new StringBuffer ();
+ FieldPosition fp = new FieldPosition (NumberFormat.INTEGER_FIELD);
+ return mf.format(arguments, sb, fp).toString();
+ }
+
+ public final StringBuffer format (Object arguments[], StringBuffer appendBuf,
+ FieldPosition ignore)
+ {
+ appendBuf.append(leader);
+
+ for (int i = 0; i < elements.length; ++i)
+ {
+ if (elements[i].argNumber >= arguments.length)
+ throw new IllegalArgumentException ();
+ Object thisArg = arguments[elements[i].argNumber];
+
+ Format formatter = null;
+ if (elements[i].setFormat != null)
+ formatter = elements[i].setFormat;
+ else if (elements[i].format != null)
+ {
+ if (elements[i].formatClass != null
+ && ! elements[i].formatClass.isInstance(thisArg))
+ throw new IllegalArgumentException ();
+ formatter = elements[i].format;
+ }
+ else if (thisArg instanceof Number)
+ formatter = NumberFormat.getInstance(locale);
+ else if (thisArg instanceof Date)
+ formatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
+ else
+ appendBuf.append(thisArg);
+
+ if (formatter != null)
+ {
+ // Special-case ChoiceFormat.
+ if (formatter instanceof ChoiceFormat)
+ {
+ StringBuffer buf = new StringBuffer ();
+ // FIXME: don't actually know what is correct here.
+ // Can a sub-format refer to any argument, or just
+ // the single argument passed to it? Must test
+ // against JDK.
+ formatter.format(thisArg, buf, ignore);
+ MessageFormat mf = new MessageFormat ();
+ mf.setLocale(locale);
+ mf.applyPattern(buf.toString());
+ formatter = mf;
+ }
+ formatter.format(thisArg, appendBuf, ignore);
+ }
+
+ appendBuf.append(elements[i].trailer);
+ }
+
+ return appendBuf;
+ }
+
+ public final StringBuffer format (Object singleArg, StringBuffer appendBuf,
+ FieldPosition ignore)
+ {
+ Object[] args = new Object[1];
+ args[0] = singleArg;
+ return format (args, appendBuf, ignore);
+ }
+
+ public Format[] getFormats ()
+ {
+ Format[] f = new Format[elements.length];
+ for (int i = elements.length - 1; i >= 0; --i)
+ f[i] = elements[i].setFormat;
+ return f;
+ }
+
+ public Locale getLocale ()
+ {
+ return locale;
+ }
+
+ public int hashCode ()
+ {
+ // FIXME: not a very good hash.
+ return pattern.hashCode() + locale.hashCode();
+ }
+
+ private MessageFormat ()
+ {
+ }
+
+ public MessageFormat (String pattern)
+ {
+ applyPattern (pattern);
+ }
+
+ public Object[] parse (String sourceStr, ParsePosition pos)
+ {
+ // Check initial text.
+ int index = pos.getIndex();
+ if (! sourceStr.startsWith(leader, index))
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ index += leader.length();
+
+ Vector results = new Vector (elements.length, 1);
+ // Now check each format.
+ for (int i = 0; i < elements.length; ++i)
+ {
+ Format formatter = null;
+ if (elements[i].setFormat != null)
+ formatter = elements[i].setFormat;
+ else if (elements[i].format != null)
+ formatter = elements[i].format;
+
+ Object value = null;
+ if (formatter instanceof ChoiceFormat)
+ {
+ // We must special-case a ChoiceFormat because it might
+ // have recursive formatting.
+ ChoiceFormat cf = (ChoiceFormat) formatter;
+ String[] formats = (String[]) cf.getFormats();
+ double[] limits = (double[]) cf.getLimits();
+ MessageFormat subfmt = new MessageFormat ();
+ subfmt.setLocale(locale);
+ ParsePosition subpos = new ParsePosition (index);
+
+ int j;
+ for (j = 0; value == null && j < limits.length; ++j)
+ {
+ subfmt.applyPattern(formats[j]);
+ subpos.setIndex(index);
+ value = subfmt.parse(sourceStr, subpos);
+ }
+ if (value != null)
+ {
+ index = subpos.getIndex();
+ value = new Double (limits[j]);
+ }
+ }
+ else if (formatter != null)
+ {
+ pos.setIndex(index);
+ value = formatter.parseObject(sourceStr, pos);
+ if (value != null)
+ index = pos.getIndex();
+ }
+ else
+ {
+ // We have a String format. This can lose in a number
+ // of ways, but we give it a shot.
+ int next_index = sourceStr.indexOf(elements[i].trailer, index);
+ if (next_index == -1)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ value = sourceStr.substring(index, next_index);
+ index = next_index;
+ }
+
+ if (value == null
+ || ! sourceStr.startsWith(elements[i].trailer, index))
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+
+ if (elements[i].argNumber >= results.size())
+ results.setSize(elements[i].argNumber + 1);
+ results.setElementAt(value, elements[i].argNumber);
+
+ index += elements[i].trailer.length();
+ }
+
+ Object[] r = new Object[results.size()];
+ results.copyInto(r);
+ return r;
+ }
+
+ public Object[] parse (String sourceStr) throws ParseException
+ {
+ ParsePosition pp = new ParsePosition (0);
+ Object[] r = parse (sourceStr, pp);
+ if (r == null)
+ throw new ParseException ("couldn't parse string", pp.getErrorIndex());
+ return r;
+ }
+
+ public Object parseObject (String sourceStr, ParsePosition pos)
+ {
+ return parse (sourceStr, pos);
+ }
+
+ public void setFormat (int variableNum, Format newFormat)
+ {
+ elements[variableNum].setFormat = newFormat;
+ }
+
+ public void setFormats (Format[] newFormats)
+ {
+ if (newFormats.length < elements.length)
+ throw new IllegalArgumentException ();
+ int len = Math.min(newFormats.length, elements.length);
+ for (int i = 0; i < len; ++i)
+ elements[i].setFormat = newFormats[i];
+ }
+
+ public void setLocale (Locale loc)
+ {
+ locale = loc;
+ if (elements != null)
+ {
+ for (int i = 0; i < elements.length; ++i)
+ elements[i].setLocale(loc);
+ }
+ }
+
+ public String toPattern ()
+ {
+ return pattern;
+ }
+
+ // The pattern string.
+ private String pattern;
+ // The locale.
+ private Locale locale;
+ // Variables.
+ private MessageFormatElement[] elements;
+ // Leader text.
+ private String leader;
+}
diff --git a/libjava/java/text/NumberFormat.java b/libjava/java/text/NumberFormat.java
new file mode 100644
index 00000000000..6ee79b3b546
--- /dev/null
+++ b/libjava/java/text/NumberFormat.java
@@ -0,0 +1,236 @@
+/* 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.text;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.MissingResourceException;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date March 4, 1999
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.2, except serialization
+ * and getAvailableLocales.
+ */
+
+public abstract class NumberFormat extends Format implements Cloneable
+{
+ public static final int INTEGER_FIELD = 0;
+ public static final int FRACTION_FIELD = 1;
+
+ public final String format (long number)
+ {
+ StringBuffer sbuf = new StringBuffer(50);
+ format (number, sbuf, null);
+ return sbuf.toString();
+ }
+
+ public final StringBuffer format (Object obj, StringBuffer sbuf,
+ FieldPosition pos)
+ {
+ return format(((Number) obj).doubleValue(), sbuf, pos);
+ }
+
+ public abstract StringBuffer format (double number,
+ StringBuffer sbuf, FieldPosition pos);
+
+ public abstract StringBuffer format (long number,
+ StringBuffer sbuf, FieldPosition pos);
+
+ public static Locale[] getAvailableLocales ()
+ {
+ // FIXME.
+ return null;
+ }
+
+ private static final NumberFormat computeInstance (Locale loc,
+ String resource,
+ String def)
+ {
+ ResourceBundle res;
+ try
+ {
+ res = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", loc);
+ }
+ catch (MissingResourceException x)
+ {
+ res = null;
+ }
+ String fmt;
+ try
+ {
+ fmt = res == null ? def : res.getString(resource);
+ }
+ catch (MissingResourceException x)
+ {
+ fmt = def;
+ }
+ DecimalFormatSymbols dfs = new DecimalFormatSymbols (loc);
+ return new DecimalFormat (fmt, dfs);
+ }
+
+ public static final NumberFormat getCurrencyInstance ()
+ {
+ return getCurrencyInstance (Locale.getDefault());
+ }
+
+ public static NumberFormat getCurrencyInstance (Locale loc)
+ {
+ return computeInstance (loc, "currencyFormat", "$#,##0.00;($#,##0.00)");
+ }
+
+ public static final NumberFormat getInstance ()
+ {
+ return getInstance (Locale.getDefault());
+ }
+
+ public static NumberFormat getInstance (Locale loc)
+ {
+ // For now always return a number instance.
+ return getNumberInstance (loc);
+ }
+
+ public int getMaximumFractionDigits ()
+ {
+ return maximumFractionDigits;
+ }
+
+ public int getMaximumIntegerDigits ()
+ {
+ return maximumIntegerDigits;
+ }
+
+ public int getMinimumFractionDigits ()
+ {
+ return minimumFractionDigits;
+ }
+
+ public int getMinimumIntegerDigits ()
+ {
+ return minimumIntegerDigits;
+ }
+
+ public static final NumberFormat getNumberInstance ()
+ {
+ return getNumberInstance (Locale.getDefault());
+ }
+
+ public static NumberFormat getNumberInstance (Locale loc)
+ {
+ return computeInstance (loc, "numberFormat", "#,##0.###");
+ }
+
+ public static final NumberFormat getPercentInstance ()
+ {
+ return getPercentInstance (Locale.getDefault());
+ }
+
+ public static NumberFormat getPercentInstance (Locale loc)
+ {
+ return computeInstance (loc, "percentFormat", "#,##0%");
+ }
+
+ public int hashCode ()
+ {
+ int hash = super.hashCode();
+ hash ^= (maximumFractionDigits + maximumIntegerDigits
+ + minimumFractionDigits + minimumIntegerDigits);
+ if (groupingUsed)
+ hash ^= 0xf0f0;
+ if (parseIntegerOnly)
+ hash ^= 0x0f0f;
+ return hash;
+ }
+
+ public boolean isGroupingUsed ()
+ {
+ return groupingUsed;
+ }
+
+ public boolean isParseIntegerOnly ()
+ {
+ return parseIntegerOnly;
+ }
+
+ public NumberFormat ()
+ {
+ }
+
+ public abstract Number parse (String sourceStr, ParsePosition pos);
+
+ public Number parse (String sourceStr) throws ParseException
+ {
+ ParsePosition pp = new ParsePosition (0);
+ Number r = parse (sourceStr, pp);
+ if (r == null)
+ {
+ int index = pp.getErrorIndex();
+ if (index < 0)
+ index = pp.getIndex();
+ throw new ParseException ("couldn't parse number", index);
+ }
+ return r;
+ }
+
+ public final Object parseObject (String sourceStr, ParsePosition pos)
+ {
+ return parse (sourceStr, pos);
+ }
+
+ public void setGroupingUsed (boolean newValue)
+ {
+ groupingUsed = newValue;
+ }
+
+ public void setMaximumFractionDigits (int newValue)
+ {
+ maximumFractionDigits = newValue;
+ }
+
+ public void setMaximumIntegerDigits (int newValue)
+ {
+ maximumIntegerDigits = newValue;
+ }
+
+ public void setMinimumFractionDigits (int newValue)
+ {
+ minimumFractionDigits = newValue;
+ }
+
+ public void setMinimumIntegerDigits (int newValue)
+ {
+ minimumIntegerDigits = newValue;
+ }
+
+ public void setParseIntegerOnly (boolean value)
+ {
+ parseIntegerOnly = value;
+ }
+
+ public final String format (double number)
+ {
+ StringBuffer sbuf = new StringBuffer(50);
+ format (number, sbuf, null);
+ return sbuf.toString();
+ }
+
+ // These field names are fixed by the serialization spec.
+ // FIXME: serialization spec also mentions `byte' versions of the
+ // min/max fields. We have no use for those, so for now they are
+ // omitted.
+ protected boolean groupingUsed;
+ protected int maximumFractionDigits;
+ protected int maximumIntegerDigits;
+ protected int minimumFractionDigits;
+ protected int minimumIntegerDigits;
+ protected boolean parseIntegerOnly;
+}
diff --git a/libjava/java/text/ParseException.java b/libjava/java/text/ParseException.java
new file mode 100644
index 00000000000..6bc9353bcd2
--- /dev/null
+++ b/libjava/java/text/ParseException.java
@@ -0,0 +1,34 @@
+/* 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.text;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 25, 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 ParseException extends Exception
+{
+ private int errorOffset;
+
+ public ParseException (String msg, int errorOffset)
+ {
+ super(msg);
+ this.errorOffset = errorOffset;
+ }
+
+ public int getErrorOffset ()
+ {
+ return errorOffset;
+ }
+}
diff --git a/libjava/java/text/ParsePosition.java b/libjava/java/text/ParsePosition.java
new file mode 100644
index 00000000000..4603f79259b
--- /dev/null
+++ b/libjava/java/text/ParsePosition.java
@@ -0,0 +1,59 @@
+/* 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.text;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 25, 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.
+ * Includes JDK 1.2 methods.
+ */
+
+public class ParsePosition
+{
+ int index;
+ int errorIndex;
+
+ public ParsePosition (int index)
+ {
+ this.index = index;
+ errorIndex = -1;
+ }
+
+ public int getIndex ()
+ {
+ return index;
+ }
+
+ public void setIndex (int index)
+ {
+ this.index = index;
+ }
+
+ public int getErrorIndex ()
+ {
+ return errorIndex;
+ }
+
+ public void setErrorIndex (int ei)
+ {
+ errorIndex = ei;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (obj != null || ! (obj instanceof ParsePosition))
+ return false;
+ ParsePosition other = (ParsePosition) obj;
+ return index == other.index && errorIndex == other.errorIndex;
+ }
+}
diff --git a/libjava/java/text/SimpleDateFormat.java b/libjava/java/text/SimpleDateFormat.java
new file mode 100644
index 00000000000..b4012479045
--- /dev/null
+++ b/libjava/java/text/SimpleDateFormat.java
@@ -0,0 +1,522 @@
+/* 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.text;
+
+import java.util.*;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 25, 1998.
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: parse is not implemented.
+ */
+
+public class SimpleDateFormat extends DateFormat
+{
+ private Date defaultCenturyStart;
+ private DateFormatSymbols formatData;
+ private String pattern;
+
+ public SimpleDateFormat ()
+ {
+ this("dd/MM/yy HH:mm", Locale.getDefault());
+ }
+
+ public SimpleDateFormat (String pattern)
+ {
+ this(pattern, Locale.getDefault());
+ }
+
+ public SimpleDateFormat (String pattern, Locale locale)
+ {
+ this.pattern = pattern;
+ this.calendar = Calendar.getInstance(locale);
+ this.numberFormat = NumberFormat.getInstance(locale);
+ numberFormat.setGroupingUsed(false);
+ this.formatData = new DateFormatSymbols (locale);
+ }
+
+ public SimpleDateFormat (String pattern, DateFormatSymbols formatData)
+ {
+ this.pattern = pattern;
+ this.formatData = formatData;
+ this.calendar = Calendar.getInstance();
+ this.numberFormat = NumberFormat.getInstance();
+ numberFormat.setGroupingUsed(false);
+ }
+
+ public Date get2DigitYearStart()
+ {
+ return defaultCenturyStart;
+ }
+
+ public void set2DigitYearStart(Date startDate)
+ {
+ defaultCenturyStart = startDate;
+ }
+
+ public DateFormatSymbols getDateFormatSymbols ()
+ {
+ return formatData;
+ }
+
+ public void setDateFormatSymbols (DateFormatSymbols value)
+ {
+ formatData = value;
+ }
+
+ public String toPattern ()
+ {
+ return pattern;
+ }
+
+ public void applyPattern (String pattern)
+ {
+ this.pattern = pattern;
+ }
+
+ private String applyLocalizedPattern (String pattern,
+ String oldChars, String newChars)
+ {
+ int len = pattern.length();
+ StringBuffer buf = new StringBuffer(len);
+ boolean quoted = false;
+ for (int i = 0; i < len; i++)
+ {
+ char ch = pattern.charAt(i);
+ if (ch == '\'')
+ quoted = ! quoted;
+ if (! quoted)
+ {
+ int j = oldChars.indexOf(ch);
+ if (j >= 0)
+ ch = newChars.charAt(j);
+ }
+ buf.append(ch);
+ }
+ return buf.toString();
+ }
+
+ public void applyLocalizedPattern (String pattern)
+ {
+ String localChars = formatData.getLocalPatternChars();
+ String standardChars = DateFormatSymbols.localPatternCharsDefault;
+ pattern = applyLocalizedPattern (pattern, localChars, standardChars);
+ applyPattern(pattern);
+ }
+
+ public String toLocalizedPattern ()
+ {
+ String localChars = formatData.getLocalPatternChars();
+ String standardChars = DateFormatSymbols.localPatternCharsDefault;
+ return applyLocalizedPattern (pattern, standardChars, localChars);
+ }
+
+ private final void append (StringBuffer buf, int value, int numDigits)
+ {
+ numberFormat.setMinimumIntegerDigits(numDigits);
+ numberFormat.format(value, buf, null);
+ }
+
+ public StringBuffer format (Date date, StringBuffer buf, FieldPosition pos)
+ {
+ Calendar calendar = (Calendar) this.calendar.clone();
+ calendar.setTime(date);
+ int len = pattern.length();
+ int quoteStart = -1;
+ for (int i = 0; i < len; i++)
+ {
+ char ch = pattern.charAt(i);
+ if (ch == '\'')
+ {
+ // We must do a little lookahead to see if we have two
+ // single quotes embedded in quoted text.
+ if (i < len - 1 && pattern.charAt(i + 1) == '\'')
+ {
+ ++i;
+ buf.append(ch);
+ }
+ else
+ quoteStart = quoteStart < 0 ? i : -1;
+ }
+ // From JCL: any characters in the pattern that are not in
+ // the ranges of [a..z] and [A..Z] are treated as quoted
+ // text.
+ else if (quoteStart != -1
+ || ((ch < 'a' || ch > 'z')
+ && (ch < 'A' || ch > 'Z')))
+ buf.append(ch);
+ else
+ {
+ int first = i;
+ int value;
+ while (++i < len && pattern.charAt(i) == ch) ;
+ int count = i - first; // Number of repetions of ch in pattern.
+ int beginIndex = buf.length();
+ int field;
+ i--; // Skip all but last instance of ch in pattern.
+ switch (ch)
+ {
+ case 'd':
+ append(buf, calendar.get(Calendar.DATE), count);
+ field = DateFormat.DATE_FIELD;
+ break;
+ case 'D':
+ append(buf, calendar.get(Calendar.DAY_OF_YEAR), count);
+ field = DateFormat.DAY_OF_YEAR_FIELD;
+ break;
+ case 'F':
+ append(buf, calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH),count);
+ field = DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD;
+ break;
+ case 'E':
+ value = calendar.get(calendar.DAY_OF_WEEK);
+ buf.append(count <= 3 ? formatData.getShortWeekdays()[value]
+ : formatData.getWeekdays()[value]);
+ field = DateFormat.DAY_OF_WEEK_FIELD;
+ break;
+ case 'w':
+ append(buf, calendar.get(Calendar.WEEK_OF_YEAR), count);
+ field = DateFormat.WEEK_OF_YEAR_FIELD;
+ break;
+ case 'W':
+ append(buf, calendar.get(Calendar.WEEK_OF_MONTH), count);
+ field = DateFormat.WEEK_OF_MONTH_FIELD;
+ break;
+ case 'M':
+ value = calendar.get(Calendar.MONTH);
+ if (count <= 2)
+ append(buf, value + 1, count);
+ else
+ buf.append(count <= 3 ? formatData.getShortMonths()[value]
+ : formatData.getMonths()[value]);
+ field = DateFormat.MONTH_FIELD;
+ break;
+ case 'y':
+ value = calendar.get(Calendar.YEAR);
+ append(buf, count <= 2 ? value % 100 : value, count);
+ field = DateFormat.YEAR_FIELD;
+ break;
+ case 'K':
+ append(buf, calendar.get(Calendar.HOUR), count);
+ field = DateFormat.HOUR0_FIELD;
+ break;
+ case 'h':
+ value = ((calendar.get(Calendar.HOUR) + 11) % 12) + 1;
+ append(buf, value, count);
+ field = DateFormat.HOUR1_FIELD;
+ break;
+ case 'H':
+ append(buf, calendar.get(Calendar.HOUR_OF_DAY), count);
+ field = DateFormat.HOUR_OF_DAY0_FIELD;
+ break;
+ case 'k':
+ value = ((calendar.get(Calendar.HOUR_OF_DAY) + 23) % 24) + 1;
+ append(buf, value, count);
+ field = DateFormat.HOUR_OF_DAY1_FIELD;
+ break;
+ case 'm':
+ append(buf, calendar.get(Calendar.MINUTE), count);
+ field = DateFormat.MINUTE_FIELD;
+ break;
+ case 's':
+ append(buf, calendar.get(Calendar.SECOND), count);
+ field = DateFormat.SECOND_FIELD;
+ break;
+ case 'S':
+ append(buf, calendar.get(Calendar.MILLISECOND), count);
+ field = DateFormat.MILLISECOND_FIELD;
+ break;
+ case 'a':
+ value = calendar.get(calendar.AM_PM);
+ buf.append(formatData.getAmPmStrings()[value]);
+ field = DateFormat.AM_PM_FIELD;
+ break;
+ case 'z':
+ String zoneID = calendar.getTimeZone().getID();
+ String[][] zoneStrings = formatData.getZoneStrings();
+ int zoneCount = zoneStrings.length;
+ for (int j = 0; j < zoneCount; j++)
+ {
+ String[] strings = zoneStrings[j];
+ if (zoneID.equals(strings[0]))
+ {
+ j = count > 3 ? 2 : 1;
+ if (calendar.get(Calendar.DST_OFFSET) != 0)
+ j+=2;
+ zoneID = strings[j];
+ break;
+ }
+ }
+ buf.append(zoneID);
+ field = DateFormat.TIMEZONE_FIELD;
+ break;
+ default:
+ // Note that the JCL is actually somewhat
+ // contradictory here. It defines the pattern letters
+ // to be a particular list, but also says that a
+ // pattern containing an invalid pattern letter must
+ // throw an exception. It doesn't describe what an
+ // invalid pattern letter might be, so we just assume
+ // it is any letter in [a-zA-Z] not explicitly covered
+ // above.
+ throw new RuntimeException("bad format string");
+ }
+ if (pos != null && field == pos.getField())
+ {
+ pos.setBeginIndex(beginIndex);
+ pos.setEndIndex(buf.length());
+ }
+ }
+ }
+ return buf;
+ }
+
+ private final boolean expect (String source, ParsePosition pos,
+ char ch)
+ {
+ int x = pos.getIndex();
+ boolean r = x < source.length() && source.charAt(x) == ch;
+ if (r)
+ pos.setIndex(x + 1);
+ else
+ pos.setErrorIndex(x);
+ return r;
+ }
+
+ public Date parse (String source, ParsePosition pos)
+ {
+ int fmt_index = 0;
+ int fmt_max = pattern.length();
+
+ calendar.clear();
+ int quote_start = -1;
+ for (; fmt_index < fmt_max; ++fmt_index)
+ {
+ char ch = pattern.charAt(fmt_index);
+ if (ch == '\'')
+ {
+ int index = pos.getIndex();
+ if (fmt_index < fmt_max - 1
+ && pattern.charAt(fmt_index + 1) == '\'')
+ {
+ if (! expect (source, pos, ch))
+ return null;
+ ++fmt_index;
+ }
+ else
+ quote_start = quote_start < 0 ? fmt_index : -1;
+ continue;
+ }
+
+ if (quote_start != -1
+ || ((ch < 'a' || ch > 'z')
+ && (ch < 'A' || ch > 'Z')))
+ {
+ if (! expect (source, pos, ch))
+ return null;
+ continue;
+ }
+
+ // We've arrived at a potential pattern character in the
+ // pattern.
+ int first = fmt_index;
+ while (++fmt_index < fmt_max && pattern.charAt(fmt_index) == ch)
+ ;
+ int count = fmt_index - first;
+ --fmt_index;
+
+ // We can handle most fields automatically: most either are
+ // numeric or are looked up in a string vector. In some cases
+ // we need an offset. When numeric, `offset' is added to the
+ // resulting value. When doing a string lookup, offset is the
+ // initial index into the string array.
+ int calendar_field;
+ boolean is_numeric = true;
+ String[] match = null;
+ int offset = 0;
+ int zone_number = 0;
+ switch (ch)
+ {
+ case 'd':
+ calendar_field = Calendar.DATE;
+ break;
+ case 'D':
+ calendar_field = Calendar.DAY_OF_YEAR;
+ break;
+ case 'F':
+ calendar_field = Calendar.DAY_OF_WEEK_IN_MONTH;
+ break;
+ case 'E':
+ is_numeric = false;
+ offset = 1;
+ calendar_field = Calendar.DAY_OF_WEEK;
+ match = (count <= 3
+ ? formatData.getShortWeekdays()
+ : formatData.getWeekdays());
+ break;
+ case 'w':
+ calendar_field = Calendar.WEEK_OF_YEAR;
+ break;
+ case 'W':
+ calendar_field = Calendar.WEEK_OF_MONTH;
+ break;
+ case 'M':
+ calendar_field = Calendar.MONTH;
+ if (count <= 2)
+ ;
+ else
+ {
+ is_numeric = false;
+ match = (count <= 3
+ ? formatData.getShortMonths()
+ : formatData.getMonths());
+ }
+ break;
+ case 'y':
+ calendar_field = Calendar.YEAR;
+ if (count <= 2)
+ offset = 1900;
+ break;
+ case 'K':
+ calendar_field = Calendar.HOUR;
+ break;
+ case 'h':
+ calendar_field = Calendar.HOUR;
+ offset = -1;
+ break;
+ case 'H':
+ calendar_field = Calendar.HOUR_OF_DAY;
+ break;
+ case 'k':
+ calendar_field = Calendar.HOUR_OF_DAY;
+ offset = -1;
+ break;
+ case 'm':
+ calendar_field = Calendar.MINUTE;
+ break;
+ case 's':
+ calendar_field = Calendar.SECOND;
+ break;
+ case 'S':
+ calendar_field = Calendar.MILLISECOND;
+ break;
+ case 'a':
+ is_numeric = false;
+ calendar_field = Calendar.AM_PM;
+ match = formatData.getAmPmStrings();
+ break;
+ case 'z':
+ // We need a special case for the timezone, because it
+ // uses a different data structure than the other cases.
+ is_numeric = false;
+ calendar_field = Calendar.DST_OFFSET;
+ String[][] zoneStrings = formatData.getZoneStrings();
+ int zoneCount = zoneStrings.length;
+ int index = pos.getIndex();
+ boolean found_zone = false;
+ for (int j = 0; j < zoneCount; j++)
+ {
+ String[] strings = zoneStrings[j];
+ int k;
+ for (k = 1; k < strings.length; ++k)
+ {
+ if (source.startsWith(strings[k], index))
+ break;
+ }
+ if (k != strings.length)
+ {
+ if (k > 2)
+ ; // FIXME: dst.
+ zone_number = 0; // FIXME: dst.
+ // FIXME: raw offset to SimpleTimeZone const.
+ calendar.setTimeZone(new SimpleTimeZone (1, strings[0]));
+ pos.setIndex(index + strings[k].length());
+ break;
+ }
+ }
+ if (! found_zone)
+ {
+ pos.setErrorIndex(pos.getIndex());
+ return null;
+ }
+ break;
+ default:
+ pos.setErrorIndex(pos.getIndex());
+ return null;
+ }
+
+ // Compute the value we should assign to the field.
+ int value;
+ if (is_numeric)
+ {
+ numberFormat.setMinimumIntegerDigits(count);
+ Number n = numberFormat.parse(source, pos);
+ if (pos == null || ! (n instanceof Long))
+ return null;
+ value = n.intValue() + offset;
+ }
+ else if (match != null)
+ {
+ int index = pos.getIndex();
+ int i;
+ for (i = offset; i < match.length; ++i)
+ {
+ if (source.startsWith(match[i], index))
+ break;
+ }
+ if (i == match.length)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ pos.setIndex(index + match[i].length());
+ value = i;
+ }
+ else
+ value = zone_number;
+
+ // Assign the value and move on.
+ try
+ {
+ calendar.set(calendar_field, value);
+ }
+ // FIXME: what exception is thrown on an invalid
+ // non-lenient set?
+ catch (IllegalArgumentException x)
+ {
+ pos.setErrorIndex(pos.getIndex());
+ return null;
+ }
+ }
+
+ return calendar.getTime();
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof SimpleDateFormat) || ! super.equals(obj) )
+ return false;
+ SimpleDateFormat other = (SimpleDateFormat) obj;
+ return (DateFormatSymbols.equals(pattern, other.pattern)
+ && DateFormatSymbols.equals(formatData, other.formatData)
+ && DateFormatSymbols.equals(defaultCenturyStart,
+ other.defaultCenturyStart));
+ }
+
+ public int hashCode ()
+ {
+ int hash = super.hashCode();
+ if (pattern != null)
+ hash ^= pattern.hashCode();
+ return hash;
+ }
+}
diff --git a/libjava/java/text/StringCharacterIterator.java b/libjava/java/text/StringCharacterIterator.java
new file mode 100644
index 00000000000..6eaa8e71cee
--- /dev/null
+++ b/libjava/java/text/StringCharacterIterator.java
@@ -0,0 +1,142 @@
+// StringCharacterIterator.java - Iterate over string of Unicode characters.
+
+/* 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 java.text;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date February 22, 1999
+ */
+/* 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 to 1.1.
+ */
+
+public final class StringCharacterIterator implements CharacterIterator
+{
+ public Object clone ()
+ {
+ return (Object) new StringCharacterIterator (text, begin, end, pos);
+ }
+
+ public char current ()
+ {
+ // This follows JDK 1.2 semantics and not 1.1 semantics.
+ // In 1.1 we would throw an exception if begin==end.
+ return (pos < end) ? text.charAt(pos) : CharacterIterator.DONE;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof StringCharacterIterator))
+ return false;
+ StringCharacterIterator sci = (StringCharacterIterator) obj;
+ // The spec says "the same text". We take this to mean equals,
+ // not ==.
+ return (pos == sci.pos
+ && begin == sci.begin
+ && end == sci.end
+ && text.equals(sci.text));
+ }
+
+ public char first ()
+ {
+ pos = begin;
+ return current ();
+ }
+
+ public int getBeginIndex ()
+ {
+ return begin;
+ }
+
+ public int getEndIndex ()
+ {
+ return end;
+ }
+
+ public int getIndex ()
+ {
+ return pos;
+ }
+
+ public int hashCode ()
+ {
+ // FIXME: this is a terrible hash code. Find a better one.
+ return text.hashCode() + pos + begin + end;
+ }
+
+ public char last ()
+ {
+ pos = end;
+ return current ();
+ }
+
+ public char next ()
+ {
+ if (pos == end)
+ return CharacterIterator.DONE;
+ ++pos;
+ return current ();
+ }
+
+ public char previous ()
+ {
+ if (pos == begin)
+ return CharacterIterator.DONE;
+ --pos;
+ return current ();
+ }
+
+ public char setIndex (int idx)
+ {
+ // In 1.1 we would throw an error if `idx == end'.
+ if (idx < begin || idx > end)
+ throw new IllegalArgumentException ();
+ pos = idx;
+ return current ();
+ }
+
+ public StringCharacterIterator (String text)
+ {
+ // FIXME: remove check for null once we have compiler/runtime
+ // support for NullPointerException.
+ this (text, 0, text == null ? 0 : text.length(), 0);
+ }
+ public StringCharacterIterator (String text, int pos)
+ {
+ // FIXME: remove check for null once we have compiler/runtime
+ // support for NullPointerException.
+ this (text, 0, text == null ? 0 : text.length(), pos);
+ }
+ public StringCharacterIterator (String text, int begin, int end, int pos)
+ {
+ if (text == null)
+ throw new NullPointerException ();
+ if (begin < 0 || begin > end || end > text.length()
+ // In 1.1 we would also throw if `pos == end'.
+ || pos < begin || pos > end)
+ throw new IllegalArgumentException ();
+
+ this.text = text;
+ this.begin = begin;
+ this.end = end;
+ this.pos = pos;
+ }
+
+ // String to iterate over.
+ private String text;
+ // Current position.
+ private int pos;
+ // Start position in string.
+ private int begin;
+ // End position in string.
+ private int end;
+}
diff --git a/libjava/java/util/BitSet.java b/libjava/java/util/BitSet.java
new file mode 100644
index 00000000000..e5886951714
--- /dev/null
+++ b/libjava/java/util/BitSet.java
@@ -0,0 +1,183 @@
+// BitSet - A vector of bits.
+
+/* 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.util;
+import java.io.Serializable;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 23, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * hashCode algorithm taken from JDK 1.2 docs.
+ */
+
+public final class BitSet implements Cloneable, Serializable
+{
+ public void and (BitSet bs)
+ {
+ if (bs == null)
+ throw new NullPointerException ();
+ int max = Math.min(bits.length, bs.bits.length);
+ int i;
+ for (i = 0; i < max; ++i)
+ bits[i] &= bs.bits[i];
+ for ( ; i < bits.length; ++i)
+ bits[i] = 0;
+ }
+
+ public BitSet ()
+ {
+ this (64);
+ }
+
+ public BitSet (int nbits)
+ {
+ if (nbits < 0)
+ throw new NegativeArraySizeException ();
+ int length = nbits / 64;
+ if (nbits % 64 != 0)
+ ++length;
+ bits = new long[length];
+ }
+
+ public void clear (int pos)
+ {
+ if (pos < 0)
+ throw new IndexOutOfBoundsException ();
+ int bit = pos % 64;
+ int offset = pos / 64;
+ ensure (offset);
+ bits[offset] &= ~ (1 << bit);
+ }
+
+ public Object clone ()
+ {
+ BitSet bs = new BitSet (bits.length * 64);
+ System.arraycopy(bits, 0, bs.bits, 0, bits.length);
+ return bs;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof BitSet))
+ return false;
+ BitSet bs = (BitSet) obj;
+ int max = Math.min(bits.length, bs.bits.length);
+ int i;
+ for (i = 0; i < max; ++i)
+ if (bits[i] != bs.bits[i])
+ return false;
+ // If one is larger, check to make sure all extra bits are 0.
+ for (int j = i; j < bits.length; ++j)
+ if (bits[j] != 0)
+ return false;
+ for (int j = i; j < bs.bits.length; ++j)
+ if (bs.bits[j] != 0)
+ return false;
+ return true;
+ }
+
+ public boolean get (int pos)
+ {
+ if (pos < 0)
+ throw new IndexOutOfBoundsException ();
+
+ int bit = pos % 64;
+ int offset = pos / 64;
+
+ if (offset >= bits.length)
+ return false;
+
+ return (bits[offset] & (1 << bit)) == 0 ? false : true;
+ }
+
+ public int hashCode ()
+ {
+ long h = 1234;
+ for (int i = bits.length - 1; i >= 0; --i)
+ h ^= bits[i] * (i + 1);
+ return (int) ((h >> 32) ^ h);
+ }
+
+ public void or (BitSet bs)
+ {
+ if (bs == null)
+ throw new NullPointerException ();
+ ensure (bs.bits.length - 1);
+ int i;
+ for (i = 0; i < bs.bits.length; ++i)
+ bits[i] |= bs.bits[i];
+ }
+
+ public void set (int pos)
+ {
+ if (pos < 0)
+ throw new IndexOutOfBoundsException ();
+ int bit = pos % 64;
+ int offset = pos / 64;
+ ensure (offset);
+ bits[offset] |= 1 << bit;
+ }
+
+ public int size ()
+ {
+ return bits.length * 64;
+ }
+
+ public String toString ()
+ {
+ StringBuffer result = new StringBuffer ("{");
+ boolean first = true;
+ for (int i = 0; i < bits.length; ++i)
+ {
+ int bit = 1;
+ long word = bits[i];
+ for (int j = 0; j < 64; ++j)
+ {
+ if ((word & bit) != 0)
+ {
+ if (! first)
+ result.append(", ");
+ result.append(64 * i + j);
+ first = false;
+ }
+ bit <<= 1;
+ }
+ }
+
+ return result.append("}").toString();
+ }
+
+ public void xor (BitSet bs)
+ {
+ if (bs == null)
+ throw new NullPointerException ();
+ ensure (bs.bits.length - 1);
+ int i;
+ for (i = 0; i < bs.bits.length; ++i)
+ bits[i] ^= bs.bits[i];
+ }
+
+ // Make sure the vector is big enough.
+ private final void ensure (int lastElt)
+ {
+ if (lastElt + 1 > bits.length)
+ {
+ long[] nd = new long[lastElt + 1];
+ System.arraycopy(bits, 0, nd, 0, bits.length);
+ bits = nd;
+ }
+ }
+
+ // The actual bits.
+ private long[] bits;
+}
diff --git a/libjava/java/util/Calendar.java b/libjava/java/util/Calendar.java
new file mode 100644
index 00000000000..8649adf600d
--- /dev/null
+++ b/libjava/java/util/Calendar.java
@@ -0,0 +1,258 @@
+/* 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.util;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 24, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
+ * and "The Java Language Specification", ISBN 0-201-63451-1.
+ * Status: Unimplemented: getAvailableLocales.
+ * No Locale knowledge.
+ */
+
+public abstract class Calendar implements java.io.Serializable, Cloneable
+{
+ public final static int JANUARY = 0;
+ public final static int FEBRUARY = 1;
+ public final static int MARCH = 2;
+ public final static int APRIL = 3;
+ public final static int MAY = 4;
+ public final static int JUNE = 5;
+ public final static int JULY = 6;
+ public final static int AUGUST = 7;
+ public final static int SEPTEMBER = 8;
+ public final static int OCTOBER = 9;
+ public final static int NOVEMBER = 10;
+ public final static int DECEMBER = 11;
+ public final static int UNDECIMBER = 12;
+
+ public final static int SUNDAY = 1;
+ public final static int MONDAY = 2;
+ public final static int TUESDAY = 3;
+ public final static int WEDNESDAY = 4;
+ public final static int THURSDAY = 5;
+ public final static int FRIDAY = 6;
+ public final static int SATURDAY = 7;
+
+ public final static int AM = 0;
+ public final static int PM = 1;
+
+ public final static int FIELD_COUNT = 17;
+
+ // These constants are not docuemnted, but were determined using
+ // a simple test program.
+ public final static int ERA = 0;
+ public final static int YEAR = 1;
+ public final static int MONTH = 2;
+ public final static int WEEK_OF_YEAR = 3;
+ public final static int WEEK_OF_MONTH = 4;
+ public final static int DATE = 5;
+ public final static int DAY_OF_MONTH = 5;
+ public final static int DAY_OF_YEAR = 6;
+ public final static int DAY_OF_WEEK = 7;
+ public final static int DAY_OF_WEEK_IN_MONTH = 8;
+ public final static int AM_PM = 9;
+ public final static int HOUR = 10;
+ public final static int HOUR_OF_DAY = 11;
+ public final static int MINUTE = 12;
+ public final static int SECOND = 13;
+ public final static int MILLISECOND = 14;
+ public final static int ZONE_OFFSET = 15;
+ public final static int DST_OFFSET = 16;
+
+ // The fields are as specified in Sun's "Serialized Form"
+ // in the JDK 1.2 beta 4 API specification.
+ protected boolean areFieldsSet;
+ protected int[] fields;
+ private int firstDayOfWeek;
+ protected boolean[] isSet;
+ protected boolean isTimeSet;
+ private boolean lenient;
+ private int minimalDaysInFirstWeek;
+ private int nextStamp;
+ //private int serialVersionOnStream;
+ protected long time;
+ private TimeZone zone;
+
+ protected Calendar ()
+ {
+ this (null, null);
+ }
+
+ protected Calendar (TimeZone tx, Locale loc)
+ {
+ fields = new int[FIELD_COUNT];
+ isSet = new boolean[FIELD_COUNT];
+ firstDayOfWeek = SUNDAY; // Locale-dependent. FIXME.
+ this.zone = zone != null ? zone : TimeZone.getDefault();
+ }
+
+ public Object clone ()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ throw new RuntimeException("internal error - "+ex);
+ }
+ }
+
+ public static Calendar getInstance ()
+ {
+ return new GregorianCalendar ();
+ }
+
+ public static Calendar getInstance (TimeZone zone)
+ {
+ return new GregorianCalendar (zone);
+ }
+
+ public static Calendar getInstance (Locale locale)
+ {
+ return new GregorianCalendar (locale);
+ }
+
+ public static Calendar getInstance (TimeZone zone, Locale locale)
+ {
+ return new GregorianCalendar (zone, locale);
+ }
+
+ public boolean isLenient() { return lenient; }
+ public void setLenient (boolean lenient) { this.lenient = lenient; }
+
+ public int getFirstDayOfWeek ()
+ {
+ return firstDayOfWeek;
+ }
+
+ public void setFirstDayOfWeek (int value)
+ {
+ firstDayOfWeek = value;
+ }
+
+ public int getMinimalDaysInFirstWeek ()
+ {
+ return minimalDaysInFirstWeek;
+ }
+
+ public void setMinimalDaysInFirstWeek (int value)
+ {
+ minimalDaysInFirstWeek = value;
+ }
+
+ public TimeZone getTimeZone ()
+ {
+ return zone;
+ }
+
+ public void setTimeZone (TimeZone tz)
+ {
+ zone = tz;
+ }
+
+ abstract public void add(int fld, int amount);
+ abstract public void roll (int fld, boolean up);
+
+ public final void set (int year, int month, int date)
+ {
+ set(YEAR, year);
+ set(MONTH, month);
+ set(DATE, date);
+ }
+
+ public final void set (int year, int month, int date, int hour, int minute)
+ {
+ set(year, month, date);
+ set(HOUR_OF_DAY, hour);
+ set(MINUTE, minute);
+ }
+
+ public final void set (int year, int month, int date,
+ int hour, int minute, int second)
+ {
+ set(year, month, date, hour, minute);
+ set(SECOND, second);
+ }
+
+ public final void set (int fld, int value)
+ {
+ fields[fld] = value;
+ isTimeSet = false;
+ }
+
+ public final void clear (int fld)
+ {
+ fields[fld] = 0;
+ isSet[fld] = false;
+ areFieldsSet = false;
+ }
+
+ public final void clear ()
+ {
+ for (int fld = FIELD_COUNT; --fld >= 0; )
+ {
+ fields[fld] = 0;
+ isSet[fld] = false;
+ }
+ areFieldsSet = false;
+ }
+
+ protected void complete()
+ {
+ if (!isTimeSet) computeTime();
+ if (!areFieldsSet) computeFields();
+ }
+
+ protected abstract void computeFields();
+ protected abstract void computeTime();
+
+ protected final int internalGet (int fld) { return fields[fld]; }
+
+ public final int get(int fld)
+ {
+ complete();
+ return fields[fld];
+ }
+
+ public abstract boolean after (Object cal);
+ public abstract boolean before (Object cal);
+ public abstract boolean equals (Object obj);
+
+ protected long getTimeInMillis()
+ {
+ if (!isTimeSet) computeTime();
+ return time;
+ }
+
+ public final Date getTime() { return new Date(getTimeInMillis()); }
+
+ public final void setTime (Date date)
+ {
+ setTimeInMillis(date.getTime());
+ }
+
+ protected void setTimeInMillis (long millis)
+ {
+ time = millis;
+ isTimeSet = true;
+ clear();
+ }
+
+ abstract public int getMaximum(int fld);
+ abstract public int getMinimum(int fld);
+ abstract public int getGreatestMinimum(int fld);
+ abstract public int getLeastMaximum(int fld);
+
+ public final boolean isSet(int fld) { return isSet[fld]; }
+}
diff --git a/libjava/java/util/ConcurrentModificationException.java b/libjava/java/util/ConcurrentModificationException.java
new file mode 100644
index 00000000000..478fdffebb7
--- /dev/null
+++ b/libjava/java/util/ConcurrentModificationException.java
@@ -0,0 +1,33 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 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.
+ */
+
+/* Added in JDK 1.2 */
+public class ConcurrentModificationException extends RuntimeException
+{
+ public ConcurrentModificationException()
+ {
+ super();
+ }
+
+ public ConcurrentModificationException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/util/Date.java b/libjava/java/util/Date.java
new file mode 100644
index 00000000000..3d237804e4c
--- /dev/null
+++ b/libjava/java/util/Date.java
@@ -0,0 +1,460 @@
+/* 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.util;
+import java.text.*;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 24, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
+ * "The Java Language Specification", ISBN 0-201-63451-1,
+ * and O'Reilly's "Java in a Nutshell".
+ * Status: Need to re-write toString().
+ * Missing: ToGMTString and toLocaleString.
+ * Serialization spec: Specifies readObject/writeObject.
+ */
+
+public class Date implements java.io.Serializable, Cloneable
+{
+ private long millis;
+
+ public Date() { millis = System.currentTimeMillis(); }
+
+ public Date(long millis) { this.millis = millis; }
+
+ public Date(int year, int month, int date, int hours,
+ int minutes, int seconds)
+ {
+ setTime(year, month, date, hours, minutes, seconds);
+ }
+
+ public Date(int year, int month, int date, int hours, int minutes)
+ {
+ setTime(year, month, date, hours, minutes, 0);
+ }
+
+ public Date(int year, int month, int date)
+ {
+ setTime(year, month, date, 0, 0, 0);
+ }
+
+ public Date (String s) { this(parse(s)); }
+
+ private static int skipParens(String string, int offset)
+ {
+ int len = string.length();
+ int p = 0;
+ int i;
+
+ for (i = offset; i < len; ++i)
+ {
+ if (string.charAt(i) == '(')
+ ++p;
+ else if (string.charAt(i) == ')')
+ {
+ --p;
+ if (p == 0)
+ return i + 1;
+ // If we've encounted unbalanced parens, just return the
+ // leftover one as an ordinary character. It will be
+ // caught later in parsing and cause an
+ // IllegalArgumentException.
+ if (p < 0)
+ return i;
+ }
+ }
+
+ // Not sure what to do if `p != 0' here.
+ return i;
+ }
+
+ private static int parseTz(String tok, char sign)
+ throws IllegalArgumentException
+ {
+ int num;
+
+ try
+ {
+ // parseInt doesn't handle '+' so strip off sign.
+ num = Integer.parseInt(tok.substring(1));
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new IllegalArgumentException(tok);
+ }
+
+ // Convert hours to minutes.
+ if (num < 24)
+ num *= 60;
+ else
+ num = (num / 100) * 60 + num % 100;
+
+ return sign == '-' ? -num : num;
+ }
+
+ private static int parseMonth(String tok)
+ {
+ // Initialize strings for month names.
+ // We could possibly use the fields of DateFormatSymbols but that is
+ // localized and thus might not match the English words specified.
+ String months[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY",
+ "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER",
+ "NOVEMBER", "DECEMBER" };
+
+ int i;
+ for (i = 0; i < 12; i++)
+ if (months[i].startsWith(tok))
+ return i;
+
+ // Return -1 if not found.
+ return -1;
+ }
+
+ private static boolean parseDayOfWeek(String tok)
+ {
+ // Initialize strings for days of the week names.
+ // We could possibly use the fields of DateFormatSymbols but that is
+ // localized and thus might not match the English words specified.
+ String daysOfWeek[] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
+ "THURSDAY", "FRIDAY", "SATURDAY" };
+
+ int i;
+ for (i = 0; i < 7; i++)
+ if (daysOfWeek[i].startsWith(tok))
+ return true;
+
+ return false;
+ }
+
+ public static long parse(String string)
+ {
+ // Initialize date/time fields before parsing begins.
+ int year = -1;
+ int month = -1;
+ int day = -1;
+ int hour = -1;
+ int minute = -1;
+ int second = -1;
+ int timezone = 0;
+ boolean localTimezone = true;
+
+ // Trim out any nested stuff in parentheses now to make parsing easier.
+ StringBuffer buf = new StringBuffer();
+ int off = 0;
+ int openParenOffset, tmpMonth;
+ while ((openParenOffset = string.indexOf('(', off)) >= 0)
+ {
+ // Copy part of string leading up to open paren.
+ buf.append(string.substring(off, openParenOffset));
+ off = skipParens(string, openParenOffset);
+ }
+ buf.append(string.substring(off));
+
+ // Make all chars upper case to simplify comparisons later.
+ // Also ignore commas; treat them as delimiters.
+ StringTokenizer strtok =
+ new StringTokenizer(buf.toString().toUpperCase(), " \t\n\r,");
+
+ while (strtok.hasMoreTokens())
+ {
+ String tok = strtok.nextToken();
+ char firstch = tok.charAt(0);
+ if ((firstch == '+' || firstch == '-') && year >= 0)
+ {
+ timezone = parseTz(tok, firstch);
+ localTimezone = false;
+ }
+ else if (firstch >= '0' && firstch <= '9')
+ {
+ while (tok != null && tok.length() > 0)
+ {
+ // A colon or slash may be valid in the number.
+ // Find the first of these before calling parseInt.
+ int colon = tok.indexOf(':');
+ int slash = tok.indexOf('/');
+ int hyphen = tok.indexOf('-');
+ // We choose tok.length initially because it makes
+ // processing simpler.
+ int punctOffset = tok.length();
+ if (colon >= 0)
+ punctOffset = Math.min(punctOffset, colon);
+ if (slash >= 0)
+ punctOffset = Math.min(punctOffset, slash);
+ if (hyphen >= 0)
+ punctOffset = Math.min(punctOffset, hyphen);
+ // Following code relies on -1 being the exceptional
+ // case.
+ if (punctOffset == tok.length())
+ punctOffset = -1;
+
+ int num;
+ try
+ {
+ num = Integer.parseInt(punctOffset < 0 ? tok :
+ tok.substring(0, punctOffset));
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new IllegalArgumentException(tok);
+ }
+
+ // TBD: Spec says year can be followed by a slash. That might
+ // make sense if using YY/MM/DD formats, but it would fail in
+ // that format for years <= 70. Also, what about 1900? That
+ // is interpreted as the year 3800; seems that the comparison
+ // should be num >= 1900 rather than just > 1900.
+ // What about a year of 62 - 70? (61 or less could be a (leap)
+ // second). 70/MM/DD cause an exception but 71/MM/DD is ok
+ // even though there's no ambiguity in either case.
+ // For the parse method, the spec as written seems too loose.
+ // Until shown otherwise, we'll follow the spec as written.
+ if (num > 70 && (punctOffset < 0 || punctOffset == slash))
+ year = num > 1900 ? num - 1900 : num;
+ else if (punctOffset > 0 && punctOffset == colon)
+ {
+ if (hour < 0)
+ hour = num;
+ else
+ minute = num;
+ }
+ else if (punctOffset > 0 && punctOffset == slash)
+ {
+ if (month < 0)
+ month = num - 1;
+ else
+ day = num;
+ }
+ else if (hour >= 0 && minute < 0)
+ minute = num;
+ else if (minute >= 0 && second < 0)
+ second = num;
+ else if (day < 0)
+ day = num;
+ else
+ throw new IllegalArgumentException(tok);
+
+ // Advance string if there's more to process in this token.
+ if (punctOffset < 0 || punctOffset + 1 >= tok.length())
+ tok = null;
+ else
+ tok = tok.substring(punctOffset + 1);
+ }
+ }
+ else if (firstch >= 'A' && firstch <= 'Z')
+ {
+ if (tok.equals("AM"))
+ {
+ if (hour < 1 || hour > 12)
+ throw new IllegalArgumentException(tok);
+ if (hour == 12)
+ hour = 0;
+ }
+ else if (tok.equals("PM"))
+ {
+ if (hour < 1 || hour > 12)
+ throw new IllegalArgumentException(tok);
+ if (hour < 12)
+ hour += 12;
+ }
+ else if (parseDayOfWeek(tok))
+ ; // Ignore it; throw the token away.
+ else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))
+ localTimezone = false;
+ else if (tok.startsWith("UT") || tok.startsWith("GMT"))
+ {
+ int signOffset = 3;
+ if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C')
+ signOffset = 2;
+
+ char sign = tok.charAt(signOffset);
+ if (sign != '+' && sign != '-')
+ throw new IllegalArgumentException(tok);
+
+ timezone = parseTz(tok.substring(signOffset), sign);
+ localTimezone = false;
+ }
+ else if ((tmpMonth = parseMonth(tok)) >= 0)
+ month = tmpMonth;
+ else if (tok.length() == 3 && tok.charAt(2) == 'T')
+ {
+ // Convert timezone offset from hours to minutes.
+ char ch = tok.charAt(0);
+ if (ch == 'E')
+ timezone = -5 * 60;
+ else if (ch == 'C')
+ timezone = -6 * 60;
+ else if (ch == 'M')
+ timezone = -7 * 60;
+ else if (ch == 'P')
+ timezone = -8 * 60;
+ else
+ throw new IllegalArgumentException(tok);
+
+ // Shift 60 minutes for Daylight Savings Time.
+ if (tok.charAt(1) == 'D')
+ timezone += 60;
+ else if (tok.charAt(1) != 'S')
+ throw new IllegalArgumentException(tok);
+
+ localTimezone = false;
+ }
+ else
+ throw new IllegalArgumentException(tok);
+ }
+ else
+ throw new IllegalArgumentException(tok);
+ }
+
+ // Unspecified minutes and seconds should default to 0.
+ if (minute < 0)
+ minute = 0;
+ if (second < 0)
+ second = 0;
+
+ // Throw exception if any other fields have not been recognized and set.
+ if (year < 0 || month < 0 || day < 0 || hour < 0)
+ throw new IllegalArgumentException("Missing field");
+
+ // Return the time in either local time or relative to GMT as parsed.
+ // If no time-zone was specified, get the local one (in minutes) and
+ // convert to milliseconds before adding to the UTC.
+ return UTC(year, month, day, hour, minute, second) + (localTimezone ?
+ new Date(year, month, day).getTimezoneOffset() * 60 * 1000:
+ -timezone * 60 * 1000);
+ }
+
+ public boolean after (Date when) { return this.millis > when.millis; }
+ public boolean before (Date when) { return this.millis < when.millis; }
+
+ public boolean equals(Object obj)
+ {
+ return (obj != null && obj instanceof Date
+ && ((Date)obj).millis == this.millis);
+ }
+
+ public long getTime() { return millis; }
+
+ public int hashCode()
+ {
+ return (int)(millis^(millis>>>32));
+ }
+
+ private void setTime(int year, int month, int date,
+ int hours, int minutes, int seconds)
+ {
+ Calendar cal = new GregorianCalendar(year+1900, month, date,
+ hours, minutes, seconds);
+ millis = cal.getTimeInMillis();
+ }
+
+ public void setTime(long millis) { this.millis = millis; }
+
+ private int getField (int fld)
+ {
+ Calendar cal = new GregorianCalendar();
+ cal.setTime(this);
+ return cal.get(fld);
+ }
+
+ public int getYear ()
+ {
+ return getField(Calendar.YEAR) - 1900;
+ }
+
+ public int getMonth ()
+ {
+ return getField(Calendar.MONTH);
+ }
+
+ public int getDate ()
+ {
+ return getField(Calendar.DATE);
+ }
+
+ public int getDay ()
+ {
+ return getField(Calendar.DAY_OF_WEEK) - 1;
+ }
+
+ public int getHours ()
+ {
+ return getField(Calendar.HOUR_OF_DAY);
+ }
+
+ public int getMinutes ()
+ {
+ return getField(Calendar.MINUTE);
+ }
+
+ public int getSeconds ()
+ {
+ return getField(Calendar.SECOND);
+ }
+
+ private void setField (int fld, int value)
+ {
+ Calendar cal = new GregorianCalendar();
+ cal.setTime(this);
+ cal.set(fld, value);
+ millis = cal.getTimeInMillis();
+ }
+
+ public void setYear (int year)
+ {
+ setField(Calendar.YEAR, 1900 + year);
+ }
+
+ public void setMonth (int month)
+ {
+ setField(Calendar.MONTH, month);
+ }
+
+ public void setDate (int date)
+ {
+ setField(Calendar.DATE, date);
+ }
+
+ public void setHours (int hours)
+ {
+ setField(Calendar.HOUR_OF_DAY, hours);
+ }
+
+ public void setMinutes (int minutes)
+ {
+ setField(Calendar.MINUTE, minutes);
+ }
+
+ public void setSeconds (int seconds)
+ {
+ setField(Calendar.SECOND, seconds);
+ }
+
+ public int getTimezoneOffset ()
+ {
+ Calendar cal = new GregorianCalendar();
+ cal.setTime(this);
+ return - (cal.get(Calendar.ZONE_OFFSET)
+ + cal.get(Calendar.DST_OFFSET)/(60*1000));
+ }
+
+ public native String toString ();
+
+ // TODO: toLocaleString
+ // TODO: toGMTString
+
+ public static long UTC (int year, int month, int date,
+ int hours, int minutes, int seconds)
+ {
+ GregorianCalendar cal = new GregorianCalendar (TimeZone.zoneGMT);
+ cal.set(year+1900, month, date, hours, minutes, seconds);
+ return cal.getTimeInMillis();
+ }
+}
diff --git a/libjava/java/util/Dictionary.java b/libjava/java/util/Dictionary.java
new file mode 100644
index 00000000000..2c27112106d
--- /dev/null
+++ b/libjava/java/util/Dictionary.java
@@ -0,0 +1,34 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date August 31, 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
+ */
+
+/* The JDK 1.2 beta doc indicates that Dictionary is obsolete and that the
+ * new java.util.Map interface should be used instead.
+ */
+public abstract class Dictionary
+{
+ public abstract Enumeration elements();
+ public abstract Object get(Object key) throws NullPointerException;
+ public abstract boolean isEmpty();
+ public abstract Enumeration keys();
+ public abstract Object put(Object key, Object elem)
+ throws NullPointerException;
+ public abstract Object remove(Object key) throws NullPointerException;
+ public abstract int size();
+}
diff --git a/libjava/java/util/EmptyStackException.java b/libjava/java/util/EmptyStackException.java
new file mode 100644
index 00000000000..9c4c0b0b4f8
--- /dev/null
+++ b/libjava/java/util/EmptyStackException.java
@@ -0,0 +1,27 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 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 class EmptyStackException extends RuntimeException
+{
+ public EmptyStackException()
+ {
+ super();
+ }
+}
diff --git a/libjava/java/util/Enumeration.java b/libjava/java/util/Enumeration.java
new file mode 100644
index 00000000000..233288843e0
--- /dev/null
+++ b/libjava/java/util/Enumeration.java
@@ -0,0 +1,24 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date August 25, 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 interface Enumeration
+{
+ public boolean hasMoreElements();
+ public Object nextElement() throws NoSuchElementException;
+}
diff --git a/libjava/java/util/EventListener.java b/libjava/java/util/EventListener.java
new file mode 100644
index 00000000000..394d98c28ff
--- /dev/null
+++ b/libjava/java/util/EventListener.java
@@ -0,0 +1,24 @@
+// EventListener.java - Listen for events from event source.
+
+/* 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.util;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date December 12, 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 interface EventListener
+{
+}
diff --git a/libjava/java/util/EventObject.java b/libjava/java/util/EventObject.java
new file mode 100644
index 00000000000..178ecff3e79
--- /dev/null
+++ b/libjava/java/util/EventObject.java
@@ -0,0 +1,42 @@
+// EventObject.java - Represent events fired by objects.
+
+/* 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.util;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date December 12, 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, but not fully correct.
+ */
+
+public class EventObject implements java.io.Serializable
+{
+ public EventObject (Object source)
+ {
+ this.source = source;
+ }
+
+ public Object getSource ()
+ {
+ return source;
+ }
+
+ public String toString ()
+ {
+ // FIXME.
+ return getSource().toString();
+ }
+
+ // Source of the event.
+ protected transient Object source;
+}
diff --git a/libjava/java/util/GregorianCalendar.java b/libjava/java/util/GregorianCalendar.java
new file mode 100644
index 00000000000..d20c06ef825
--- /dev/null
+++ b/libjava/java/util/GregorianCalendar.java
@@ -0,0 +1,257 @@
+/* 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.util;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 24, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
+ * and "The Java Language Specification", ISBN 0-201-63451-1.
+ * Status: "leniency" is not handled, and neither is roll-over in
+ * add and roll. This is partly because of unclear specification.
+ * hashCode has no spec.
+ */
+
+public class GregorianCalendar extends Calendar {
+ public static final int BC = 0;
+ public static final int AD = 1;
+
+ // The fields are as specified in Sun's "Serialized Form"
+ // in the JDK 1.2 beta 4 API specification.
+ // Value from a simple test program (getGregorianChange.getTime()).
+ long gregorianCutover = -12219292800000L;
+
+ private final static int[] mins = {
+ 0 /* ERA */,
+ 1 /* YEAR */,
+ 0 /* MONTH */,
+ 0 /* WEEK_OF_YEAR */,
+ 0 /* WEEK_OF_MONTH */,
+ 1 /* DATE */,
+ 1 /* DAY_OF_YEAR */,
+ 1 /* DAY_OF_WEEK */,
+ -1 /* DAY_OF_WEEK_IN_MONTH */,
+ 0 /* AM_PM */,
+ 0 /* HOUR */,
+ 0 /* HOUR_OF_DAY */,
+ 0 /* MINUTE */,
+ 0 /* SECOND */,
+ 0 /* MILLISECOND */,
+ -43200000 /* ZONE_OFFSET */,
+ 0 /* DST_OFFSET */
+ };
+
+ private final static int[] maxs = {
+ 1 /* ERA */,
+ 5000000 /* YEAR */,
+ 11 /* MONTH */,
+ 54 /* WEEK_OF_YEAR */,
+ 6 /* WEEK_OF_MONTH */,
+ 31 /* DATE */,
+ 366 /* DAY_OF_YEAR */,
+ 7 /* DAY_OF_WEEK */,
+ 6 /* DAY_OF_WEEK_IN_MONTH */,
+ 1 /* AM_PM */,
+ 12 /* HOUR */,
+ 23 /* HOUR_OF_DAY */,
+ 59 /* MINUTE */,
+ 59 /* SECOND */,
+ 999 /* MILLISECOND */,
+ 43200000 /* ZONE_OFFSET */,
+ 3600000 /* DST_OFFSET */
+ };
+
+ private final static int[] leastMaximums = {
+ 1 /* ERA */,
+ 5000000 /* YEAR */,
+ 11 /* MONTH */,
+ 53 /* WEEK_OF_YEAR */,
+ 6 /* WEEK_OF_MONTH */,
+ 28 /* DATE */,
+ 365 /* DAY_OF_YEAR */,
+ 7 /* DAY_OF_WEEK */,
+ 4 /* DAY_OF_WEEK_IN_MONTH */,
+ 1 /* AM_PM */,
+ 11 /* HOUR */,
+ 23 /* HOUR_OF_DAY */,
+ 59 /* MINUTE */,
+ 59 /* SECOND */,
+ 999 /* MILLISECOND */,
+ 43200000 /* ZONE_OFFSET */,
+ 3600000 /* DST_OFFSET */
+ };
+
+ public GregorianCalendar ()
+ {
+ this(null, null);
+ }
+
+ public GregorianCalendar (TimeZone zone)
+ {
+ this (zone, null);
+ }
+
+ public GregorianCalendar (Locale locale)
+ {
+ this (null, locale);
+ }
+
+ public GregorianCalendar (TimeZone zone, Locale locale)
+ {
+ super (zone, locale);
+ }
+
+ public GregorianCalendar (int year, int month, int date)
+ {
+ this((TimeZone) null);
+ set (year, month, date);
+ }
+
+ public GregorianCalendar (int year, int month, int date,
+ int hour, int minute)
+ {
+ this((TimeZone) null);
+ set (year, month, date, hour, minute);
+ }
+
+ public GregorianCalendar (int year, int month, int date,
+ int hour, int minute, int second)
+ {
+ this((TimeZone) null);
+ set (year, month, date, hour, minute, second);
+ }
+
+ public int getMinimum(int calfield) { return mins[calfield]; }
+ public int getGreatestMinimum(int calfield) { return mins[calfield]; }
+ public int getMaximum(int calfield) { return maxs[calfield]; }
+ public int getLeastMaximum(int calfield) { return leastMaximums[calfield]; }
+
+ protected native void computeFields();
+
+ protected native void computeTime();
+
+ public void add (int fld, int amount)
+ {
+ if (fld >= ZONE_OFFSET)
+ throw new IllegalArgumentException("bad field to add");
+ fields[fld] += amount;
+ adjust(fld);
+ }
+
+ public void roll (int fld, boolean up)
+ {
+ if (fld >= ZONE_OFFSET)
+ throw new IllegalArgumentException("bad field to roll");
+
+ int old = fields[fld];
+ if (up)
+ {
+ fields[fld] = old == getMaximum(fld) ? getMinimum(fld)
+ : old + 1;
+ }
+ else
+ {
+ fields[fld] = old == getMinimum(fld) ? getMaximum(fld)
+ : old - 1;
+ }
+ }
+
+ private void adjust (int fld)
+ {
+ int value = fields[fld];
+ int radix = maxs[fld] + 1;
+ switch (fld)
+ {
+ case MONTH:
+ case SECOND:
+ case MILLISECOND:
+ if (value >= radix)
+ {
+ int next = value / radix;
+ fields[fld] = value - radix * next;
+ fields[fld - 1] += next;
+ adjust(fld - 1);
+ }
+ else if (value < 0) // min[fld]
+ {
+ int next = (value - radix - 1) / radix;
+ fields[fld] = value - radix * next;
+ fields[fld - 1] += next;
+ adjust(fld - 1);
+ }
+ break;
+ }
+ }
+
+ public final Date getGregorianChange() { return new Date(gregorianCutover); }
+ public void setGregorianChange (Date date)
+ { gregorianCutover = date.getTime(); }
+
+ public boolean isLeapYear(int year)
+ {
+ if ((year % 4) != 0)
+ return false;
+ if ((year % 100) != 0 || (year % 400) == 0)
+ return true;
+ // year divisible by 100 but not 400.
+ GregorianCalendar date = new GregorianCalendar(year, FEBRUARY, 28);
+ return gregorianCutover < date.getTimeInMillis();
+ }
+
+ public boolean after (Object cal)
+ {
+ return cal instanceof Calendar
+ && getTimeInMillis() > ((Calendar) cal).getTimeInMillis();
+ }
+
+ public boolean before (Object cal)
+ {
+ return cal instanceof Calendar
+ && getTimeInMillis() < ((Calendar) cal).getTimeInMillis();
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (obj == null || ! (obj instanceof GregorianCalendar))
+ return false;
+ GregorianCalendar other = (GregorianCalendar) obj;
+
+ for (int i = FIELD_COUNT; --i >= 0; )
+ {
+ boolean set = isSet[i];
+ if (set != other.isSet[i]
+ || (set && fields[i] != other.fields[i]))
+ return false;
+ }
+ if (areFieldsSet != other.areFieldsSet
+ || isTimeSet != other.isTimeSet
+ || (isTimeSet && time != other.time)
+ || getFirstDayOfWeek() != other.getFirstDayOfWeek()
+ || getMinimalDaysInFirstWeek() != other.getMinimalDaysInFirstWeek()
+ || isLenient() != other.isLenient()
+ || ! getTimeZone().equals(other.getTimeZone()))
+ return false;
+ return true;
+ }
+
+ public int hashCode ()
+ {
+ int hashcode = 0;
+ for (int i = FIELD_COUNT; --i >= 0; )
+ {
+ if (isSet[i])
+ hashcode += 37 * fields[i];
+ }
+ if (isTimeSet)
+ hashcode += 89 * time;
+ return hashcode;
+ }
+}
diff --git a/libjava/java/util/Hashtable.java b/libjava/java/util/Hashtable.java
new file mode 100644
index 00000000000..51ab2b16ac3
--- /dev/null
+++ b/libjava/java/util/Hashtable.java
@@ -0,0 +1,398 @@
+/* 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.util;
+
+import java.io.Serializable;
+
+/**
+ * @author Warren Levy <warrenl@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
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct
+ */
+
+class HashtableEntry
+{
+ public Object key;
+ public Object value;
+ public HashtableEntry nextEntry = null;
+
+ public HashtableEntry(Object key, Object value)
+ {
+ this.key = key;
+ this.value = value;
+ }
+}
+
+class HashtableEnumeration implements Enumeration
+{
+ // TBD: Enumeration is not safe if new elements are put in the table as
+ // this could cause a rehash and we'd completely lose our place. Even
+ // without a rehash, it is undetermined if a new element added would
+ // appear in the enumeration. The spec says nothing about this, but
+ // the "Java Class Libraries" book infers that modifications to the
+ // hashtable during enumeration causes indeterminate results. Don't do it!
+ // A safer way would be to make a copy of the table (e.g. into a vector)
+ // but this is a fair bit more expensive.
+ private HashtableEntry[] bucket;
+ private int bucketIndex;
+ private HashtableEntry elem;
+ private int enumCount;
+ private int size;
+ private boolean values;
+
+ public HashtableEnumeration(HashtableEntry[] bkt, int sz, boolean isValues)
+ {
+ bucket = bkt;
+ bucketIndex = -1;
+ enumCount = 0;
+ elem = null;
+ size = sz;
+ values = isValues;
+ }
+
+ public boolean hasMoreElements()
+ {
+ return enumCount < size;
+ }
+
+ public Object nextElement()
+ {
+ if (!hasMoreElements())
+ throw new NoSuchElementException();
+
+ // Find next element
+ if (elem != null) // In the middle of a bucket
+ elem = elem.nextEntry;
+ while (elem == null) // Find the next non-empty bucket
+ elem = bucket[++bucketIndex];
+
+ enumCount++;
+ return values ? elem.value : elem.key;
+ }
+}
+
+// TBD: The algorithm used here closely reflects what is described in
+// the "Java Class Libraries" book. The "Java Language Spec" is much
+// less specific about the implementation. Because of this freedom
+// provided by the actual spec, hash table algorithms should be
+// investigated to see if there is a better alternative to this one.
+
+// TODO12:
+// public class Hashtable extends Dictionary
+// implements Map, Cloneable, Serializable
+
+public class Hashtable extends Dictionary implements Cloneable, Serializable
+{
+ private HashtableEntry bucket[];
+ private float loadFactor;
+ private int hsize = 0;
+
+ public Hashtable()
+ {
+ // The "Java Class Libraries" book (p. 919) says that initial size in this
+ // case is 101 (a prime number to increase the odds of even distribution).
+ this(101, 0.75F);
+ }
+
+ public Hashtable(int initialSize)
+ {
+ this(initialSize, 0.75F);
+ }
+
+ public Hashtable(int initialSize, float loadFactor)
+ {
+ if (initialSize < 0 || loadFactor <= 0.0 || loadFactor > 1.0)
+ throw new IllegalArgumentException();
+
+ bucket = new HashtableEntry[initialSize];
+ this.loadFactor = loadFactor;
+ }
+
+ // TODO12:
+ // public Hashtable(Map t)
+ // {
+ // }
+
+ public synchronized void clear()
+ {
+ // Aid the GC by nulling out the entries in the hash table.
+ for (int i = 0; i < bucket.length; i++)
+ {
+ HashtableEntry elem = bucket[i];
+ bucket[i] = null; // May already be null.
+ while (elem != null)
+ {
+ HashtableEntry next = elem.nextEntry;
+ elem.nextEntry = null; // May already be null.
+ elem = next;
+ }
+ }
+ hsize = 0;
+ }
+
+ public synchronized Object clone()
+ {
+ // New hashtable will have same initialCapacity and loadFactor.
+ Hashtable newTable = new Hashtable(bucket.length, loadFactor);
+
+ HashtableEntry newElem, prev = null;
+ for (int i = 0; i < bucket.length; i++)
+ for (HashtableEntry elem = bucket[i]; elem != null; elem = elem.nextEntry)
+ {
+ // An easy but expensive method is newTable.put(elem.key, elem.value);
+ // Since the hash tables are the same size, the buckets and collisions
+ // will be the same in the new one, so we can just clone directly.
+ // This is much cheaper than using put.
+ newElem = new HashtableEntry(elem.key, elem.value);
+ if (newTable.bucket[i] == null)
+ prev = newTable.bucket[i] = newElem;
+ else
+ prev = prev.nextEntry = newElem;
+ }
+
+ newTable.hsize = this.hsize;
+ return newTable;
+ }
+
+ public synchronized boolean contains(Object value) throws NullPointerException
+ {
+ // An exception is thrown here according to the JDK 1.2 doc.
+ if (value == null)
+ throw new NullPointerException();
+
+ for (int i = 0; i < bucket.length; i++)
+ for (HashtableEntry elem = bucket[i]; elem != null; elem = elem.nextEntry)
+ if (elem.value.equals(value))
+ return true;
+
+ return false;
+ }
+
+ public synchronized boolean containsKey(Object key)
+ {
+ // The Map interface mandates that we throw this.
+ if (key == null)
+ throw new NullPointerException ();
+
+ for (HashtableEntry elem = bucket[Math.abs(key.hashCode()
+ % bucket.length)];
+ elem != null; elem = elem.nextEntry)
+ if (elem.key.equals(key))
+ return true;
+
+ return false;
+ }
+
+ public synchronized Enumeration elements()
+ {
+ return new HashtableEnumeration(bucket, hsize, true);
+ }
+
+ public synchronized Object get(Object key)
+ {
+ // The Dictionary interface mandates that get() throw a
+ // NullPointerException if key is null.
+ if (key == null)
+ throw new NullPointerException ();
+
+ for (HashtableEntry elem = bucket[Math.abs (key.hashCode()
+ % bucket.length)];
+ elem != null; elem = elem.nextEntry)
+ if (elem.key.equals(key))
+ return elem.value;
+
+ return null;
+ }
+
+ public boolean isEmpty()
+ {
+ return this.hsize <= 0;
+ }
+
+ public synchronized Enumeration keys()
+ {
+ return new HashtableEnumeration(bucket, hsize, false);
+ }
+
+ public synchronized Object put(Object key, Object value)
+ throws NullPointerException
+ {
+ if (key == null || value == null)
+ throw new NullPointerException();
+
+ HashtableEntry prevElem = null;
+ final int index = Math.abs(key.hashCode() % bucket.length);
+
+ for (HashtableEntry elem = bucket[index]; elem != null;
+ prevElem = elem, elem = elem.nextEntry)
+ if (elem.key.equals(key))
+ {
+ // Update with the new value and then return the old one.
+ Object oldVal = elem.value;
+ elem.value = value;
+ return oldVal;
+ }
+
+ // At this point, we know we need to add a new element.
+ HashtableEntry newElem = new HashtableEntry(key, value);
+ if (bucket[index] == null)
+ bucket[index] = newElem;
+ else
+ prevElem.nextEntry = newElem;
+
+ if (++hsize > loadFactor * bucket.length)
+ rehash();
+
+ return null;
+ }
+
+ protected void rehash()
+ {
+ // Create a new table which is twice the size (plus one) of the old.
+ // One is added to make the new array length odd so it thus has at least
+ // a (small) possibility of being a prime number.
+ HashtableEntry oldBucket[] = bucket;
+ bucket = new HashtableEntry[bucket.length * 2 + 1];
+
+ // Copy over each entry into the new table
+ HashtableEntry elem;
+ for (int i = 0; i < oldBucket.length; i++)
+ for (elem = oldBucket[i]; elem != null; elem = elem.nextEntry)
+ {
+ // Calling put(elem.key, elem.value); would seem like the easy way
+ // but it is dangerous since put increases 'hsize' and calls rehash!
+ // This could become infinite recursion under the right
+ // circumstances. Instead, we'll add the element directly; this is a
+ // bit more efficient than put since the data is already verified.
+ final int index = Math.abs(elem.key.hashCode() % bucket.length);
+ HashtableEntry newElem = new HashtableEntry(elem.key, elem.value);
+ if (bucket[index] == null)
+ bucket[index] = newElem;
+ else
+ {
+ // Since this key can't already be in the table, just add this
+ // in at the top of the bucket.
+ newElem.nextEntry = bucket[index];
+ bucket[index] = newElem;
+ }
+ }
+ }
+
+ public synchronized Object remove(Object key)
+ {
+ // TBD: Hmm, none of the various docs say to throw an exception here.
+ if (key == null)
+ return null;
+
+ Object retval;
+ HashtableEntry prevElem = null;
+ final int index = Math.abs(key.hashCode() % bucket.length);
+
+ for (HashtableEntry elem = bucket[index]; elem != null;
+ prevElem = elem, elem = elem.nextEntry)
+ if (elem.key.equals(key))
+ {
+ retval = elem.value;
+ if (prevElem == null)
+ bucket[index] = elem.nextEntry;
+ else
+ prevElem.nextEntry = elem.nextEntry;
+ --hsize;
+ return retval;
+ }
+
+ return null;
+ }
+
+ public int size()
+ {
+ return this.hsize;
+ }
+
+ public synchronized String toString()
+ {
+ // Following the Java Lang Spec 21.5.4 (p. 636).
+
+ Enumeration keys = keys();
+ Enumeration values = elements();
+
+ // Prepend first element with open bracket
+ StringBuffer result = new StringBuffer("{");
+
+ // add first element if one exists
+ // TBD: Seems like it is more efficient to catch the exception than
+ // to call hasMoreElements each time around.
+ try
+ {
+ result.append(keys.nextElement().toString() + "=" +
+ values.nextElement().toString());
+ }
+ catch (NoSuchElementException ex)
+ {
+ }
+
+ // Prepend subsequent elements with ", "
+ try
+ {
+ while (true)
+ result.append(", " + keys.nextElement().toString() + "=" +
+ values.nextElement().toString());
+ }
+ catch (NoSuchElementException ex)
+ {
+ }
+
+ // Append last element with closing bracket
+ result.append("}");
+ return result.toString();
+ }
+
+ // TODO12:
+ // public Set entrySet()
+ // {
+ // }
+
+ // TODO12:
+ // public Set keySet()
+ // {
+ // }
+
+ // Since JDK 1.2:
+ // This method is identical to contains but is part of the 1.2 Map interface.
+ // TBD: Should contains return containsValue instead? Depends on which
+ // will be called more typically.
+ public synchronized boolean containsValue(Object value)
+ {
+ return this.contains(value);
+ }
+
+ // TODO12:
+ // public boolean equals(Object o)
+ // {
+ // }
+
+ // TODO12:
+ // public boolean hashCode()
+ // {
+ // }
+
+ // TODO12:
+ // public void putAll(Map t)
+ // {
+ // }
+
+ // TODO12:
+ // public Collection values()
+ // {
+ // }
+}
diff --git a/libjava/java/util/ListResourceBundle.java b/libjava/java/util/ListResourceBundle.java
new file mode 100644
index 00000000000..a855c459297
--- /dev/null
+++ b/libjava/java/util/ListResourceBundle.java
@@ -0,0 +1,52 @@
+/* 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.util;
+
+/**
+ * @author Anthony Green <green@cygnus.com>
+ * @date November 26, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
+ * and "The Java Language Specification", ISBN 0-201-63451-1. */
+
+public abstract class ListResourceBundle extends ResourceBundle
+{
+ public final Object handleGetObject(String key)
+ {
+ Object a[][] = getContents();
+
+ for (int i = 0; i < a.length; i++)
+ {
+ if (key.compareTo((String) a[i][0]) == 0)
+ return a[i][1];
+ }
+ throw new MissingResourceException("can't find handle",
+ getClass().getName(),
+ key);
+ }
+
+ public Enumeration getKeys()
+ {
+ Object a[][] = getContents();
+
+ Vector keys = new Vector(a.length);
+
+ for (int i = 0; i < a.length; i++)
+ keys.addElement(a[i][0]);
+
+ return keys.elements();
+ }
+
+ protected abstract Object[][] getContents();
+
+ public ListResourceBundle()
+ {
+ }
+}
diff --git a/libjava/java/util/Locale.java b/libjava/java/util/Locale.java
new file mode 100644
index 00000000000..e47cd1d59d7
--- /dev/null
+++ b/libjava/java/util/Locale.java
@@ -0,0 +1,125 @@
+/* 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.util;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 24, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
+ * and "The Java Language Specification", ISBN 0-201-63451-1.
+ * Status: None of the getDisplayXXX or getISO3XXX methods are implemented.
+ */
+public final class Locale implements java.io.Serializable, Cloneable
+{
+ // The fields are as specified in Sun's "Serialized Form"
+ // in the JDK 1.2 beta 4 API specification.
+ private String country;
+ private int hashcode;
+ private String language;
+ private String variant;
+ private static Locale defaultLocale;
+
+ // FIXME: many are still missing.
+ public static final Locale CANADA = new Locale ("en", "CA");
+ public static final Locale FRANCE = new Locale ("fr", "FR");
+ public static final Locale JAPAN = new Locale ("ja", "JP");
+ public static final Locale UK = new Locale ("en", "GB");
+ public static final Locale US = new Locale ("en", "US");
+
+ public Locale (String languageCode, String countryCode)
+ {
+ language = languageCode.toLowerCase();
+ country = countryCode.toUpperCase();
+ hashcode = languageCode.hashCode() ^ countryCode.hashCode();
+ }
+
+ public Locale (String languageCode, String countryCode,
+ String variantCode)
+ {
+ this (languageCode, countryCode);
+ variant = variantCode;
+ hashcode ^= variantCode.hashCode();
+ }
+
+ public Object clone ()
+ {
+ return (Object) new Locale (language, country, variant);
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof Locale))
+ return false;
+ Locale loc = (Locale) obj;
+ if ((language == null && loc.language != null)
+ || (country == null && loc.country != null)
+ || (variant == null && loc.variant != null))
+ return false;
+ return (language.equals(loc.language)
+ && country.equals(loc.country)
+ && variant.equals(loc.variant));
+ }
+
+ public String getCountry ()
+ {
+ return country;
+ }
+
+ public String getLanguage ()
+ {
+ return language;
+ }
+
+ public String getVariant ()
+ {
+ return variant;
+ }
+
+ public int hashCode ()
+ {
+ return hashcode;
+ }
+
+ private static synchronized Locale setDefault()
+ {
+ if (defaultLocale != null)
+ return defaultLocale;
+ String language = System.getProperty("user.language");
+ String country = System.getProperty("user.region");
+ defaultLocale = new Locale (language == null ? "en" : language,
+ country == null ? "" : country);
+ return defaultLocale;
+ }
+
+ public static Locale getDefault ()
+ {
+ return defaultLocale == null ? setDefault() : defaultLocale;
+ }
+
+ public static void setDefault (Locale newLocale)
+ {
+ defaultLocale = newLocale;
+ }
+
+ public String toString ()
+ {
+ StringBuffer result = new StringBuffer(20);
+ result.append(language);
+ result.append('_');
+ result.append(country);
+ if (variant != null && variant.length() > 0)
+ {
+ result.append('_');
+ result.append(variant);
+ }
+ return result.toString();
+ }
+}
diff --git a/libjava/java/util/MissingResourceException.java b/libjava/java/util/MissingResourceException.java
new file mode 100644
index 00000000000..e24cd6aa6dd
--- /dev/null
+++ b/libjava/java/util/MissingResourceException.java
@@ -0,0 +1,43 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 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 class MissingResourceException extends RuntimeException
+{
+ private String className;
+ private String key;
+
+ public MissingResourceException(String msg, String cName, String k)
+ {
+ super(msg);
+ className = cName;
+ key = k;
+ }
+
+ public String getClassName()
+ {
+ return className;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+}
+
diff --git a/libjava/java/util/NoSuchElementException.java b/libjava/java/util/NoSuchElementException.java
new file mode 100644
index 00000000000..2e6d0247c97
--- /dev/null
+++ b/libjava/java/util/NoSuchElementException.java
@@ -0,0 +1,32 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 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 class NoSuchElementException extends RuntimeException
+{
+ public NoSuchElementException()
+ {
+ super();
+ }
+
+ public NoSuchElementException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/util/Observable.java b/libjava/java/util/Observable.java
new file mode 100644
index 00000000000..627892ef061
--- /dev/null
+++ b/libjava/java/util/Observable.java
@@ -0,0 +1,98 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 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 class Observable
+{
+ /* tracks whether this object has changed */
+ private boolean changed;
+
+ /* list of the Observers registered as interested in this Observable */
+ private Vector observerVec;
+
+ /* TBD: This might be better implemented as an Observer[]
+ * but that would mean writing more code rather than making use of
+ * the existing Vector class (this also implies a larger text code
+ * space in resulting executables). The tradeoff is one of speed
+ * (manipulating the Observer[] directly) vs. size/reuse. In the future,
+ * we may decide to make the tradeoff and reimplement with an Observer[].
+ */
+
+ public Observable()
+ {
+ changed = false;
+ observerVec = new Vector();
+ }
+
+ public synchronized void addObserver(Observer obs)
+ {
+ // JDK 1.2 spec says not to add this if it is already there
+ if (!observerVec.contains(obs))
+ observerVec.addElement(obs);
+ }
+
+ protected synchronized void clearChanged()
+ {
+ changed = false;
+ }
+
+ public synchronized int countObservers()
+ {
+ return observerVec.size();
+ }
+
+ public synchronized void deleteObserver(Observer obs)
+ {
+ observerVec.removeElement(obs);
+ }
+
+ public synchronized void deleteObservers()
+ {
+ observerVec.removeAllElements();
+ }
+
+ public synchronized boolean hasChanged()
+ {
+ return changed;
+ }
+
+ public void notifyObservers()
+ {
+ notifyObservers(null);
+ }
+
+ public void notifyObservers(Object arg)
+ {
+ if (changed)
+ {
+ /* The JDK 1.2 spec states that though the order of notification
+ * is unspecified in subclasses, in Observable it is in the order
+ * of registration.
+ */
+ for (int i = 0, numObs = observerVec.size(); i < numObs; i++)
+ ((Observer) (observerVec.elementAt(i))).update(this, arg);
+ changed = false;
+ }
+ }
+
+ protected synchronized void setChanged()
+ {
+ changed = true;
+ }
+}
diff --git a/libjava/java/util/Observer.java b/libjava/java/util/Observer.java
new file mode 100644
index 00000000000..c131f3bbc13
--- /dev/null
+++ b/libjava/java/util/Observer.java
@@ -0,0 +1,24 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date August 25, 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 Observer
+{
+ public void update(Observable observed, Object arg);
+}
diff --git a/libjava/java/util/Properties.java b/libjava/java/util/Properties.java
new file mode 100644
index 00000000000..aac72147720
--- /dev/null
+++ b/libjava/java/util/Properties.java
@@ -0,0 +1,376 @@
+// Properties - Property list representation.
+
+/* 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.util;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.PushbackReader;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 26, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * Status: Complete to JDK 1.1.
+ */
+
+public class Properties extends Hashtable
+{
+ protected Properties defaults;
+
+ public String getProperty (String propName)
+ {
+ return getProperty (propName, null);
+ }
+
+ public String getProperty (String propName, String defVal)
+ {
+ String r = (String) get (propName);
+ if (r == null)
+ {
+ if (defaults != null)
+ r = defaults.getProperty(propName, defVal);
+ else
+ r = defVal;
+ }
+ return r;
+ }
+
+ public void list (PrintStream out)
+ {
+ Enumeration e = propertyNames ();
+ while (e.hasMoreElements())
+ {
+ String key = (String) e.nextElement();
+ String value = getProperty(key);
+ if (value != null)
+ {
+ if (value.length() > 40)
+ {
+ // JDK compatibility.
+ value = value.substring(0, 37) + "...";
+ }
+ out.print(key);
+ out.print("=");
+ out.println(value);
+ }
+ }
+ }
+
+ public void list (PrintWriter writer)
+ {
+ Enumeration e = propertyNames ();
+ while (e.hasMoreElements())
+ {
+ String key = (String) e.nextElement();
+ String value = getProperty(key);
+ if (value != null)
+ {
+ if (value.length() > 40)
+ {
+ // JDK compatibility.
+ value = value.substring(0, 37) + "...";
+ }
+ writer.print(key);
+ writer.print("=");
+ writer.println(value);
+ }
+ }
+ }
+
+ private final boolean skip_ws (PushbackReader reader) throws IOException
+ {
+ while (true)
+ {
+ int c = reader.read();
+ if (c == -1)
+ return false;
+ // FIXME: we use our own definition of whitespace.
+ // Character.isWhitespace includes newlines, which we don't
+ // want. Character.isSpaceChar doesn't include \t.
+ if (c == ' ' || c == '\t')
+ {
+ reader.unread(c);
+ return true;
+ }
+ }
+ }
+
+ // Note: this method needs to be rewritten for JDK 1.2.
+ // We rather arbitrarily decide that an EOF in the middle of a line
+ // means that the whole line should be ignored. The spec doesn't
+ // specifically address this, but this interpretation seems valid.
+ public synchronized void load (InputStream in) throws IOException
+ {
+ PushbackReader reader = new PushbackReader (new InputStreamReader (in));
+
+ StringBuffer key = new StringBuffer ();
+ StringBuffer value = new StringBuffer ();
+
+ nextLine:
+ while (true)
+ {
+ key.setLength(0);
+ value.setLength(0);
+
+ // Skip leading whitespace.
+ if (! skip_ws (reader))
+ return;
+
+ // Read key until key terminator.
+ boolean first_char = true;
+ int c;
+ while (true)
+ {
+ c = reader.read();
+ if (c == -1)
+ return;
+ if (c == '\\')
+ {
+ first_char = false;
+ c = reader.read();
+ if (c == -1)
+ return;
+ }
+
+ // If we found a comment, just read to end of line and
+ // then keep going.
+ if (first_char == true && (c == '#' || c == '!'))
+ {
+ while (c != -1 && c != '\r' && c != '\n')
+ c = reader.read();
+ if (c == -1)
+ return;
+ continue nextLine;
+ }
+
+ if (c == '\r' || c == '\n')
+ {
+ if (first_char)
+ continue nextLine;
+ reader.unread(c);
+ break;
+ }
+ // FIXME: again, our own definitino of whitespace.
+ if (c == ' ' || c == '\t' || c == ':' || c == '=')
+ break;
+
+ first_char = false;
+ key.append(c);
+ }
+
+ // Found end of key. Skip whitespace. If the terminator
+ // was whitespace, also skip a single instance of a "real"
+ // terminator, and then more whitespace.
+ if (! skip_ws (reader))
+ return;
+ if (c != ':' && c != '=')
+ {
+ c = reader.read();
+ if (c == -1)
+ return;
+ if (c == ':' || c == '=')
+ {
+ // Skip more whitespace.
+ if (! skip_ws (reader))
+ return;
+ }
+ else
+ reader.unread(c);
+ }
+
+ // Now read the value.
+ while (true)
+ {
+ c = reader.read();
+ if (c == -1)
+ return;
+ if (c == '\r' || c == '\n')
+ break;
+ if (c == '\\')
+ {
+ c = reader.read();
+ switch (c)
+ {
+ case -1:
+ return;
+ case 't':
+ c = '\t';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'u':
+ c = 0;
+ for (int i = 0; i < 4; ++i)
+ {
+ int x = reader.read();
+ if (x == -1)
+ return;
+ int d = Character.digit((char) x, 16);
+ // FIXME: what to do here? We call it an
+ // error.
+ if (d == -1)
+ throw new IOException ();
+ c <<= 4;
+ c |= d;
+ }
+ break;
+ default:
+ // Nothing.
+ }
+ }
+ else
+ value.append(c);
+ }
+
+ put (key.toString(), value.toString());
+ }
+ }
+
+ public Properties ()
+ {
+ defaults = null;
+ }
+
+ public Properties (Properties defs)
+ {
+ defaults = defs;
+ }
+
+ private final void addHashEntries (Hashtable base)
+ {
+ if (defaults != null)
+ defaults.addHashEntries(base);
+ Enumeration keys = keys ();
+ while (keys.hasMoreElements())
+ base.put(keys.nextElement(), base);
+ }
+
+ public Enumeration propertyNames ()
+ {
+ // We make a new Hashtable that holds all the keys. Then we
+ // return an enumeration for this hash. We do this because we
+ // don't want modifications to be reflected in the enumeration
+ // (per JCL), and because there doesn't seem to be a
+ // particularly better way to ensure that duplicates are
+ // ignored.
+ Hashtable t = new Hashtable ();
+ addHashEntries (t);
+ return t.keys();
+ }
+
+ public synchronized void save (OutputStream out, String comment)
+ {
+ // Use a buffer because writing a single string through
+ // OutputStreamWriter is fairly expensive.
+ BufferedWriter output
+ = new BufferedWriter (new OutputStreamWriter (out));
+ String newline = System.getProperty("line.separator");
+
+ try
+ {
+ if (comment != null)
+ {
+ // FIXME: what if COMMENT contains newlines?
+ output.write("#");
+ output.write(comment);
+ output.write(newline);
+ }
+ output.write("# ");
+ output.write(new Date().toString());
+ output.write(newline);
+
+ Enumeration keys = keys ();
+ while (keys.hasMoreElements())
+ {
+ String key = (String) keys.nextElement();
+ String value = (String) get (key);
+
+ // FIXME: JCL says that the key can contain many Unicode
+ // characters. But it also doesn't say we should encode
+ // it in any way.
+ // FIXME: if key contains ':', '=', or whitespace, must
+ // quote it here.
+ output.write(key);
+ output.write("=");
+
+ boolean leading = true;
+ for (int i = 0; i < value.length(); ++i)
+ {
+ boolean new_lead = false;
+ char c = value.charAt(i);
+ switch (c)
+ {
+ case '\n':
+ output.write("\\n");
+ break;
+ case '\r':
+ output.write("\\r");
+ break;
+ case '\t':
+ output.write("\\t");
+ break;
+ case '\\':
+ output.write("\\\\");
+ break;
+
+ case '#':
+ case '!':
+ case '=':
+ case ':':
+ output.write("\\");
+ output.write(c);
+ break;
+
+ case ' ':
+ new_lead = leading;
+ if (leading)
+ output.write("\\");
+ output.write(c);
+ break;
+
+ default:
+ if (c < '\u0020' || c > '\u007e')
+ {
+ output.write("\\u");
+ output.write(Character.forDigit(c >>> 12, 16));
+ output.write(Character.forDigit((c >>> 8) & 0xff,
+ 16));
+ output.write(Character.forDigit((c >>> 4) & 0xff,
+ 16));
+ output.write(Character.forDigit(c & 0xff, 16));
+ }
+ else
+ output.write(c);
+ }
+ leading = new_lead;
+ }
+ output.write(newline);
+ }
+
+ output.flush();
+ }
+ catch (IOException ignore)
+ {
+ }
+ }
+}
diff --git a/libjava/java/util/Random.java b/libjava/java/util/Random.java
new file mode 100644
index 00000000000..26010ce96f9
--- /dev/null
+++ b/libjava/java/util/Random.java
@@ -0,0 +1,148 @@
+/* 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.util;
+
+import java.io.Serializable;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date August 25, 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
+ */
+
+/* This class is completely specified by the spec to ensure absolute
+ * portability between all implementations of Java
+ */
+public class Random implements Serializable
+{
+ /* Used by next() to hold the state of the pseudorandom number generator */
+ protected long seed;
+
+ /* Used by nextGaussian() to hold a precomputed value */
+ /* to be delivered by that method the next time it is called */
+ protected double nextNextGaussian;
+
+ /* Used by nextGaussian() to keep track of whether it is has precomputed */
+ /* and stashed away the next value to be delivered by that method */
+ protected boolean haveNextNextGaussian = false;
+
+ public Random()
+ {
+ this(System.currentTimeMillis());
+ }
+
+ public Random(long seed)
+ {
+ setSeed(seed);
+ }
+
+ protected synchronized int next(int bits)
+ {
+ seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
+ return (int)(seed >>> (48 - bits));
+ }
+
+ // JDK1.2
+ public boolean nextBoolean()
+ {
+ return next(1) != 0;
+ }
+
+ /* The method nextBytes() is not fully specified in the published specs.
+ * At first I implemented it simply via:
+ * for (int i = 0; i < buf.length; i++)
+ * buf[i] = (byte)next(8);
+ * but a simple test did not yield the same results as the std implementation.
+ * There seemed to be a relationship where each i byte above was at pos 4*i+3
+ * in the std. For efficiency, by reducing calls to the expensive math
+ * routines, the std probably was calling next(32) once rather than next(8)
+ * 4 times. Changing the algorithm to the one below based on that assumption
+ * then yielded identical results to the std.
+ */
+ public void nextBytes(byte[] buf)
+ {
+ int randInt = 0;
+
+ for (int i = 0; i < buf.length; i++)
+ {
+ int shift = (i % 4) * 8;
+ if (shift == 0)
+ randInt = next(32);
+ buf[i] = (byte) (randInt >> shift);
+ }
+ }
+
+ public double nextDouble()
+ {
+ return (((long)next(26) << 27) + next(27)) / (double)(1L << 53);
+ }
+
+ public float nextFloat()
+ {
+ return next(24) / ((float)(1 << 24));
+ }
+
+ public synchronized double nextGaussian()
+ {
+ if (haveNextNextGaussian)
+ {
+ haveNextNextGaussian = false;
+ return nextNextGaussian;
+ }
+ else
+ {
+ double v1, v2, s;
+ do
+ {
+ v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
+ v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
+ s = v1 * v1 + v2 * v2;
+ } while (s >= 1);
+ double norm = Math.sqrt(-2 * Math.log(s)/s);
+ nextNextGaussian = v2 * norm;
+ haveNextNextGaussian = true;
+ return v1 * norm;
+ }
+ }
+
+ public int nextInt()
+ {
+ return next(32);
+ }
+
+ // JDK1.2
+ public int nextInt(int n)
+ {
+ if (n <= 0)
+ throw new IllegalArgumentException("n must be positive");
+
+ int bits, val;
+ do
+ {
+ bits = next(31);
+ val = bits % n;
+ } while (bits - val + (n-1) < 0);
+ return val;
+ }
+
+ public long nextLong()
+ {
+ return ((long)next(32) << 32) + next(32);
+ }
+
+ public synchronized void setSeed(long seed)
+ {
+ this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
+ haveNextNextGaussian = false;
+ }
+}
diff --git a/libjava/java/util/ResourceBundle.java b/libjava/java/util/ResourceBundle.java
new file mode 100644
index 00000000000..ba1d3f9fdcb
--- /dev/null
+++ b/libjava/java/util/ResourceBundle.java
@@ -0,0 +1,188 @@
+/* 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.util;
+
+/**
+ * @author Anthony Green <green@cygnus.com>
+ * @date November 26, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
+ * and "The Java Language Specification", ISBN 0-201-63451-1. */
+
+public abstract class ResourceBundle
+{
+ protected ResourceBundle parent;
+
+ public ResourceBundle ()
+ {
+ }
+
+ public final String getString (String key) throws MissingResourceException
+ {
+ return (String) getObject(key);
+ }
+
+ public final String[] getStringArray (String key)
+ throws MissingResourceException
+ {
+ return (String[]) getObject(key);
+ }
+
+ public final Object getObject(String key) throws MissingResourceException
+ {
+ Object result;
+
+ try
+ {
+ return handleGetObject (key);
+ }
+ catch (MissingResourceException ex)
+ {
+ if (parent != null)
+ return parent.getObject(key);
+ else
+ throw ex;
+ }
+ }
+
+ public static final ResourceBundle getBundle(String baseName)
+ throws MissingResourceException
+ {
+ return getBundle(baseName, Locale.getDefault());
+ }
+
+ // Start searching with the name bundleName. Continue searching by
+ // stripping off the '_' delimited tails until the search name is
+ // the same as stopHere.
+ private static final ResourceBundle trySomeGetBundle (String bundleName,
+ String stopHere)
+ {
+ Class rbc;
+
+ while (true)
+ {
+ try
+ {
+ rbc = Class.forName(bundleName);
+ try
+ {
+ return (ResourceBundle) rbc.newInstance();
+ }
+ catch (IllegalAccessException ex)
+ {
+ // Fall through
+ }
+ catch (InstantiationException ex)
+ {
+ // Fall through
+ }
+ return null;
+ }
+ catch (ClassNotFoundException ex)
+ {
+ if (bundleName.compareTo(stopHere) == 0)
+ return null;
+ else
+ {
+ int last = bundleName.lastIndexOf('_');
+
+ // No more underscores?
+ if (last == -1)
+ return null;
+
+ // Loop around, testing this new shorter name.
+ bundleName = bundleName.substring(0, last);
+ }
+ }
+ }
+ }
+
+ // Search for bundles, but stop at baseName_language.
+ private static final ResourceBundle partialGetBundle (String baseName,
+ Locale locale)
+ {
+ ResourceBundle rb;
+
+ String bundleName = (baseName
+ + "_"
+ + locale.getLanguage() + "_"
+ + locale.getCountry() + "_"
+ + locale.getVariant());
+
+ String stopHere = (baseName
+ + "_"
+ + locale.getLanguage());
+
+
+ rb = trySomeGetBundle(bundleName, stopHere);
+
+ return rb;
+ }
+
+ public static final ResourceBundle getBundle (String baseName,
+ Locale locale)
+ throws MissingResourceException
+ {
+ ResourceBundle rb;
+ Class rbc;
+
+ // FIXME: We can't currently rely on NullPointerException being
+ // thrown when we invoke a method on a null object.
+ if (locale == null)
+ throw new NullPointerException ();
+
+ rb = partialGetBundle(baseName, locale);
+ if (rb != null)
+ return rb;
+
+ if (! locale.equals(Locale.getDefault()))
+ {
+ rb = partialGetBundle(baseName, Locale.getDefault());
+ if (rb != null)
+ return rb;
+ }
+
+ // Try just the baseName.
+ try
+ {
+ rbc = Class.forName (baseName);
+ try
+ {
+ return (ResourceBundle) rbc.newInstance();
+ }
+ catch (IllegalAccessException ex)
+ {
+ // Fall through.
+ }
+ catch (InstantiationException ex)
+ {
+ // Fall through.
+ }
+ }
+ catch (ClassNotFoundException ex)
+ {
+ // Fall through.
+ }
+
+ throw new MissingResourceException("can't load bundle",
+ baseName,
+ "bundle");
+ }
+
+ protected void setParent(ResourceBundle parent)
+ {
+ this.parent = parent;
+ }
+
+ protected abstract Object handleGetObject(String key)
+ throws MissingResourceException;
+
+ public abstract Enumeration getKeys();
+}
diff --git a/libjava/java/util/SimpleTimeZone.java b/libjava/java/util/SimpleTimeZone.java
new file mode 100644
index 00000000000..6082b1816e5
--- /dev/null
+++ b/libjava/java/util/SimpleTimeZone.java
@@ -0,0 +1,182 @@
+/* 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.util;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 24, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3.
+ * Status: Does not know how to figure out if daylight savings time
+ * is in effect; hence only correct for zones without DST.
+ * No known spec for hashCode.
+ */
+
+public class SimpleTimeZone extends TimeZone
+{
+ // The fields are as specified in Sun's "Serialized Form"
+ // in the JDK 1.2 beta 4 API specification.
+
+ int dstSavings = 60 * 60 * 1000;
+
+ int rawOffset;
+
+ // int serialVersionOnStream;
+
+ int startDay;
+ int startDayOfWeek;
+ int startMode; /// Seems to be JDK 1.2 only.
+
+ int startMonth;
+
+ int startTime;
+
+ int startYear;
+
+ int endDay;
+
+ int endDayOfWeek;
+
+ int endMode; // Seems to be JDK 1.2 only.
+
+ int endMonth;
+
+ int endTime;
+
+ // byte[] monthLength;
+
+ boolean useDaylight;
+
+ public SimpleTimeZone (int rawOffset, String ID)
+ {
+ setID(ID);
+ this.rawOffset = rawOffset;
+ }
+
+ public SimpleTimeZone (int rawOffset, String ID,
+ int startMonth, int startDay,
+ int startDayOfWeek, int startTime,
+ int endMonth, int endDay,
+ int endDayOfWeek, int endTime)
+ {
+ this(rawOffset, ID);
+ setStartRule (startMonth, startDay, startDayOfWeek, startTime);
+ setEndRule (endMonth, endDay, endDayOfWeek, endTime);
+ }
+
+ public int getRawOffset() { return rawOffset; }
+ public void setRawOffset (int offsetMillis) { rawOffset = offsetMillis; }
+
+ public int getOffset (int era, int year, int month, int day,
+ int dayOfWeek, int millis)
+ {
+ int offset = getRawOffset();
+ if (useDaylight)
+ {
+ if (startYear != 0
+ && (year < startYear || era == GregorianCalendar.BC))
+ return offset;
+ boolean midYearSummer = startMonth < endMonth;
+ if (midYearSummer ? (month < startMonth || month > endMonth)
+ : (month < startMonth && month > endMonth))
+ return offset; // Definitely not DST.
+ if (midYearSummer ? (month > startMonth && month < endMonth)
+ : (month > startMonth || month < endMonth))
+ return offset + dstSavings; // Definitely DST.
+ // Now it gets more complicated. Bail for now.
+ throw new Error("not implemented - SimpleTimeZone.getOffset");
+ }
+ return offset;
+ }
+
+ public boolean useDaylightTime() { return useDaylight; }
+
+ public boolean inDaylightTime(Date date)
+ {
+ if (! useDaylight)
+ return false;
+ throw new Error("not implemented - SimpleTimeZone.inDaylightTime");
+ }
+
+ public int getDSTSavings () { return dstSavings; }
+
+ public void setDSTSavings (int millisSavedDuringDST)
+ { dstSavings = millisSavedDuringDST; }
+
+ public void setStartRule (int month, int dayOfWeekInMonth,
+ int dayOfWeek, int time)
+ {
+ this.startMonth = month;
+ this.startDay = dayOfWeekInMonth;
+ this.startDayOfWeek = dayOfWeek;
+ this.startTime = time;
+ this.useDaylight = true;
+ }
+
+ public void setEndRule (int month, int dayOfWeekInMonth,
+ int dayOfWeek, int time)
+ {
+ this.endMonth = month;
+ this.endDay = dayOfWeekInMonth;
+ this.endDayOfWeek = dayOfWeek;
+ this.endTime = time;
+ this.useDaylight = true;
+ }
+
+ public void setStartYear (int year)
+ {
+ this.startYear = startYear;
+ }
+
+ public boolean hasSameRules (TimeZone other)
+ {
+ if (this == other)
+ return true;
+ if (! (other instanceof SimpleTimeZone))
+ return false;
+ SimpleTimeZone o = (SimpleTimeZone) other;
+ if (rawOffset != o.rawOffset)
+ return false;
+ if (useDaylight != o.useDaylight)
+ return false;
+ if (! useDaylight)
+ return true;
+ return startDay == o.startDay
+ && startDayOfWeek == o.startDayOfWeek
+ && startMonth == o.startMonth
+ && startTime == o.startTime
+ && endDay == o.endDay
+ && endDayOfWeek == o.endDayOfWeek
+ && endMonth == o.endMonth
+ && endTime == o.endTime
+ && startYear == o.startYear
+ && startMode == o.startMode
+ && endMode == o.endMode;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof SimpleTimeZone))
+ return false;
+ SimpleTimeZone other = (SimpleTimeZone) obj;
+ return getID() == other.getID() && hasSameRules(other);
+ }
+
+ public int hashCode ()
+ {
+ // FIXME - this does not folow any spec (since none is public)!
+ int hash = rawOffset;
+ if (useDaylight)
+ hash += dstSavings + startYear + startMode + endMode
+ + startDay + startDayOfWeek + startMonth + startTime
+ + endDay + endDayOfWeek + endMonth + endTime;
+ return hash;
+ }
+}
diff --git a/libjava/java/util/Stack.java b/libjava/java/util/Stack.java
new file mode 100644
index 00000000000..bc4588898cb
--- /dev/null
+++ b/libjava/java/util/Stack.java
@@ -0,0 +1,74 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date August 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 Stack extends Vector
+{
+ // Could use Vector methods internally for the following methods
+ // but have used Vector fields directly for efficiency (i.e. this
+ // often reduces out duplicate bounds checking).
+
+ public boolean empty()
+ {
+ return elementCount == 0;
+ }
+
+ public synchronized Object peek()
+ {
+ if (elementCount == 0)
+ throw new EmptyStackException();
+
+ return elementData[elementCount - 1];
+ }
+
+ public synchronized Object pop()
+ {
+ if (elementCount == 0)
+ throw new EmptyStackException();
+
+ Object obj = elementData[--elementCount];
+
+ // Set topmost element to null to assist the gc in cleanup
+ elementData[elementCount] = null;
+ return obj;
+ }
+
+ public Object push(Object obj)
+ {
+ // When growing the Stack, use the Vector routines in case more
+ // memory is needed.
+ // Note: spec indicates that this method *always* returns obj passed in!
+
+ addElement(obj);
+ return obj;
+ }
+
+ public synchronized int search(Object obj)
+ {
+ // Return the position of obj on the stack as measured from the top;
+ // i.e. the top element is 1, the next element down is 2, etc.
+ // If obj is not on the stack, return -1
+
+ for (int i = elementCount-1; i >=0; --i)
+ if (elementData[i].equals(obj))
+ return elementCount - i;
+
+ return -1;
+ }
+}
diff --git a/libjava/java/util/StringTokenizer.java b/libjava/java/util/StringTokenizer.java
new file mode 100644
index 00000000000..4516057f2d9
--- /dev/null
+++ b/libjava/java/util/StringTokenizer.java
@@ -0,0 +1,185 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date August 24, 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 StringTokenizer implements Enumeration
+{
+ /* String to be parsed */
+ private String inputString;
+
+ /* String to be parsed put into a char array for efficient access */
+ private char[] chArray;
+
+ /* Set of delimiter characters for separating tokens */
+ private String delimiters;
+
+ /* Whether delimiters in this instance are treated as tokens themselves */
+ private boolean returnDelimiters;
+
+ /* Index into the input string to start parsing for the next token */
+ private int inputStringIndex;
+
+ public StringTokenizer(String str)
+ {
+ this(str, " \t\n\r", false);
+ }
+
+ public StringTokenizer(String str, String delims)
+ {
+ this(str, delims, false);
+ }
+
+ public StringTokenizer(String str, String delims, boolean retDelim)
+ {
+ inputString = str;
+ delimiters = delims;
+ returnDelimiters = retDelim;
+ inputStringIndex = 0;
+
+ // Work on a copy of the remaining string in a char array
+ // to gain efficiency of using primitives
+ chArray = new char[inputString.length()];
+ inputString.getChars(0, inputString.length(), chArray, 0);
+ }
+
+ public int countTokens()
+ {
+ int count = 0;
+ int delimiterCount = 0;
+ boolean tokenFound = false; // Set when a non-delimiter is found
+ int offset = inputStringIndex;
+
+ // Note for efficiency, we count up the delimiters rather than check
+ // returnDelimiters every time we encounter one. That way, we can
+ // just do the conditional once at the end of the method
+ while (offset < chArray.length)
+ {
+ if (isDelimiter(chArray[offset++]))
+ {
+ if (tokenFound)
+ {
+ // Got to the end of a token
+ count++;
+ tokenFound = false;
+ }
+
+ delimiterCount++; // Increment for this delimiter
+ }
+ else
+ {
+ tokenFound = true;
+
+ // Get to the end of the token
+ while (offset < chArray.length && !isDelimiter(chArray[offset]))
+ offset++;
+ }
+ }
+
+ // Make sure to count the last token
+ if (tokenFound)
+ count++;
+
+ // if counting delmiters add them into the token count
+ return returnDelimiters ? count + delimiterCount : count;
+ }
+
+ public boolean hasMoreElements()
+ {
+ return hasMoreTokens();
+ }
+
+ public boolean hasMoreTokens()
+ {
+ int offset = inputStringIndex;
+
+ while (offset < chArray.length)
+ if (!isDelimiter(chArray[offset++]) || returnDelimiters)
+ {
+ // update the current position with the start of the next token
+ inputStringIndex = --offset;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public Object nextElement()
+ {
+ return nextToken();
+ }
+
+ public String nextToken()
+ {
+ int offset = inputStringIndex;
+ int startSubstr = -1;
+
+ // Make sure we have more chars left to parse
+ // and then find the start of the next token
+ while (offset < chArray.length && startSubstr < 0)
+ {
+ // Find the start of the token; skipping initial delimiters
+ if (!isDelimiter(chArray[offset++]))
+ startSubstr = offset - 1;
+ else if (returnDelimiters)
+ {
+ // The single char delimiter is treated as a token
+ inputStringIndex = offset; // update the current position
+
+ return inputString.substring(offset - 1, inputStringIndex);
+ }
+ }
+
+ // Now look for the end of the token
+ while (offset < chArray.length)
+ {
+ if (isDelimiter(chArray[offset++]))
+ {
+ // Found the end of token
+ inputStringIndex = offset - 1; // update the current position
+
+ return inputString.substring(startSubstr, inputStringIndex);
+ }
+ }
+
+ // Got to the end of the string without finding the start of a token
+ if (startSubstr < 0)
+ throw new NoSuchElementException();
+
+ // Got to the end of the string before a delimiter
+ inputStringIndex = offset; // update the current position
+
+ return inputString.substring(startSubstr, inputStringIndex);
+ }
+
+ public String nextToken(String delims)
+ {
+ // First replace with new set of delimiters
+ delimiters = delims;
+
+ return nextToken();
+ }
+
+ // This private method could be inlined but the other methods are
+ // more readable this way, so we'll take the hit on efficiency.
+ private boolean isDelimiter(char ch)
+ {
+ return delimiters.indexOf(ch) >= 0;
+ }
+}
diff --git a/libjava/java/util/TimeZone.java b/libjava/java/util/TimeZone.java
new file mode 100644
index 00000000000..ad2dd628b1f
--- /dev/null
+++ b/libjava/java/util/TimeZone.java
@@ -0,0 +1,120 @@
+/* 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.util;
+
+/**
+ * @author Per Bothner <bothner@cygnus.com>
+ * @date October 24, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3.
+ * Status: getAvailableIDs, getDefault, getTimeZone only know about GMT.
+ */
+
+public abstract class TimeZone implements java.io.Serializable, Cloneable
+{
+ public static final int SHORT = 0;
+ public static final int LONG = 1;
+
+ // The fields are as specified in Sun's "Serialized Form"
+ // in the JDK 1.2 beta 4 API specification.
+ String ID;
+
+ static final TimeZone zoneGMT = new SimpleTimeZone(0, "GMT");
+
+ private static TimeZone zoneDefault;
+
+ public TimeZone ()
+ {
+ }
+
+ public abstract int getOffset (int era, int year, int month,
+ int day, int dayOfWeek, int milliseconds);
+
+ public abstract void setRawOffset (int offsetMillis);
+
+ public abstract int getRawOffset ();
+
+ public String getID () { return ID; }
+
+ public void setID (String ID) { this.ID = ID; }
+
+ public final String getDisplayName()
+ {
+ return ID; // FIXME
+ }
+
+ // public final String getDisplayName (Local locale) { ... } FIXME
+
+ public final String getDisplayName (boolean daylight, int style)
+ {
+ return ID; // FIXME
+ }
+
+ /*
+ public final String getDisplayName (boolean daylight, int style, Locale locale)
+ {
+ return ID; // FIXME
+ }
+ */
+
+ public abstract boolean useDaylightTime();
+
+ public abstract boolean inDaylightTime (Date date);
+
+ public static TimeZone getTimeZone (String ID)
+ {
+ return zoneGMT; // FIXME
+ }
+
+ public static String[] getAvailableIDs()
+ { // FIXME - only knows about GMT
+ String[] zones = new String[1];
+ zones[0] = "GMT";
+ return zones;
+ }
+
+ public static String[] getAvailableIDs(int rawOffset)
+ {
+ return rawOffset == 0 ? getAvailableIDs() : new String[0]; // FIXME
+ }
+
+ private static synchronized TimeZone setDefault()
+ {
+ if (zoneDefault == null)
+ {
+ try
+ {
+ String id = System.getProperty("user.timezone");
+ if (id != null && ! id.equals("GMT"))
+ zoneDefault = getTimeZone(id);
+ }
+ catch (Exception ex)
+ {
+ }
+ if (zoneDefault == null)
+ zoneDefault = zoneGMT;
+ }
+ return zoneDefault;
+ }
+
+ public static TimeZone getDefault()
+ {
+ return zoneDefault == null ? setDefault() : zoneDefault;
+ }
+
+ public static void setDefault (TimeZone zone) { zoneDefault = zone; }
+
+ public boolean hasSameRules (TimeZone other)
+ {
+ return this == other;
+ }
+
+ // public Object clone ();
+}
diff --git a/libjava/java/util/TooManyListenersException.java b/libjava/java/util/TooManyListenersException.java
new file mode 100644
index 00000000000..13bbc4ecae3
--- /dev/null
+++ b/libjava/java/util/TooManyListenersException.java
@@ -0,0 +1,32 @@
+/* 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.util;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date September 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 class TooManyListenersException extends Exception
+{
+ public TooManyListenersException()
+ {
+ super();
+ }
+
+ public TooManyListenersException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/util/Vector.java b/libjava/java/util/Vector.java
new file mode 100644
index 00000000000..aaa9ea27632
--- /dev/null
+++ b/libjava/java/util/Vector.java
@@ -0,0 +1,450 @@
+/* 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.util;
+
+import java.io.Serializable;
+
+/**
+ * @author Warren Levy <warrenl@cygnus.com>
+ * @date August 17, 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
+ */
+
+class VectorEnumeration implements Enumeration
+{
+ private int enumIndex;
+ private Vector enumVec;
+
+ public VectorEnumeration(Vector vec)
+ {
+ enumVec = vec;
+ enumIndex = 0;
+ }
+
+ public boolean hasMoreElements()
+ {
+ return enumIndex < enumVec.size();
+ }
+
+ public Object nextElement()
+ {
+ if (!hasMoreElements())
+ throw new NoSuchElementException();
+
+ return enumVec.elementData[enumIndex++];
+ }
+}
+
+// TODO12:
+// public class Vector extends AbstractList
+// implements List, Cloneable, Serializable
+
+public class Vector implements Cloneable, Serializable
+{
+ /* The size of the increment to use when growing this vector.
+ The default of 0 means to double the capacity when growing. */
+ protected int capacityIncrement;
+
+ /* The number of elements currently in elementData */
+ protected int elementCount;
+
+ /* The buffer in which elements of this vector are stored */
+ protected Object[] elementData;
+
+ public Vector()
+ {
+ this(10, 0);
+ }
+
+ public Vector(int initCap)
+ {
+ this(initCap, 0);
+ }
+
+ public Vector(int initCap, int capIncrement)
+ {
+ if (initCap < 0)
+ throw new IllegalArgumentException ();
+ elementData = new Object[initCap];
+ capacityIncrement = capIncrement;
+ elementCount = 0;
+ }
+
+ public final synchronized void addElement(Object obj)
+ {
+ // Make sure there's room for a new element
+ if (elementCount == elementData.length)
+ ensureCapacity(elementCount+1);
+
+ elementData[elementCount++] = obj;
+ }
+
+ public final int capacity()
+ {
+ return elementData.length;
+ }
+
+ public synchronized Object clone()
+ {
+ // New vector needs to have same size, capacity and capacityIncrement
+ Vector newVec = new Vector(elementData.length, capacityIncrement);
+
+ System.arraycopy(elementData, 0, newVec.elementData, 0, elementCount);
+ newVec.elementCount = elementCount;
+ return newVec;
+ }
+
+ public final boolean contains(Object obj)
+ {
+ for (int i = 0; i < elementCount; i++)
+ {
+ if (obj == null
+ ? elementData[i] == null
+ : obj.equals(elementData[i]))
+ return true;
+ }
+
+ return false;
+ }
+
+ public final synchronized void copyInto(Object[] objArray)
+ {
+ System.arraycopy(elementData, 0, objArray, 0, elementCount);
+ }
+
+ public final synchronized Object elementAt(int idx)
+ {
+ if (idx < 0 || idx >= size())
+ throw new ArrayIndexOutOfBoundsException();
+
+ return elementData[idx];
+ }
+
+ public final synchronized Enumeration elements()
+ {
+ return new VectorEnumeration(this);
+ }
+
+ public final synchronized void ensureCapacity(int minCap)
+ {
+ // Increasing the vector could make it much larger than minCap;
+ // e.g. if minCap is just larger than the vector, size may double.
+ // If someone cares about this possibility they should set capacityIncrement
+ if (minCap > elementData.length)
+ {
+ // Increase the vector; double it if capacityIncrement is zero
+ int newSize = elementData.length;
+ newSize +=
+ (capacityIncrement > 0) ? capacityIncrement : elementData.length;
+
+ // Make sure newSize is at least minCap
+ if (newSize < minCap)
+ newSize = minCap;
+
+ Object[] newArray = new Object[newSize];
+ System.arraycopy(elementData, 0, newArray, 0, elementCount);
+ elementData = newArray;
+ }
+ }
+
+ public final synchronized Object firstElement()
+ {
+ if (elementCount == 0)
+ throw new NoSuchElementException();
+
+ return elementData[0];
+ }
+
+ public final int indexOf(Object obj)
+ {
+ return indexOf(obj, 0);
+ }
+
+ public final synchronized int indexOf(Object obj, int idx)
+ {
+ if (idx < 0)
+ throw new IllegalArgumentException ();
+ for (int i = idx; i < elementCount; i++)
+ {
+ if (obj == null
+ ? elementData[i] == null
+ : obj.equals(elementData[i]))
+ return i;
+ }
+
+ return -1;
+ }
+
+ public final synchronized void insertElementAt(Object obj, int idx)
+ {
+ if (idx < 0 || idx > size())
+ throw new ArrayIndexOutOfBoundsException();
+ else if (idx == size()) // Spec says just use addElement()
+ addElement(obj);
+ else
+ {
+ // Make sure there's room for a new element
+ if (elementCount == elementData.length)
+ ensureCapacity(elementCount+1);
+
+ // Shift the existing elements up and increment elementCount
+ for (int i = elementCount++; i > idx; --i)
+ elementData[i] = elementData[i-1];
+
+ elementData[idx] = obj;
+ }
+ }
+
+ public final boolean isEmpty()
+ {
+ return elementCount == 0;
+ }
+
+ public final synchronized Object lastElement()
+ {
+ if (elementCount == 0)
+ throw new NoSuchElementException();
+
+ return elementData[elementCount - 1];
+ }
+
+ public final int lastIndexOf(Object obj)
+ {
+ return lastIndexOf(obj, size()-1);
+ }
+
+ public final synchronized int lastIndexOf(Object obj, int idx)
+ {
+ if (idx < 0)
+ throw new IllegalArgumentException ();
+ for (int i = idx; i >= 0; --i)
+ {
+ if (obj == null
+ ? elementData[i] == null
+ : obj.equals(elementData[i]))
+ return i;
+ }
+
+ return -1;
+ }
+
+ public final synchronized void removeAllElements()
+ {
+ // Remove elements now to assist the gc in early cleanup
+ for (int i = elementCount-1; i >= 0; --i)
+ elementData[i] = null;
+ elementCount = 0;
+ }
+
+ public final synchronized boolean removeElement(Object obj)
+ {
+ for (int i = 0; i < elementCount; i++)
+ {
+ if (obj == null
+ ? elementData[i] == null
+ : obj.equals(elementData[i]))
+ {
+ int j;
+
+ // Decrement count first to ensure we don't walk off end of array
+ --elementCount;
+
+ for (j = i; j < elementCount; j++)
+ elementData[j] = elementData[j+1];
+
+ // At this point, j was incrememented and points to old last element
+ // Remove element now to assist the gc in early cleanup
+ elementData[j] = null;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public final synchronized void removeElementAt(int idx)
+ {
+ int i;
+
+ if (idx < 0 || idx >= size())
+ throw new ArrayIndexOutOfBoundsException();
+
+ // Decrement count first to ensure we don't walk off the end of the array
+ --elementCount;
+
+ for (i = idx; i < elementCount; i++)
+ elementData[i] = elementData[i+1];
+
+ // At this point, i was incrememented and now points to the old last element
+ // Remove element now to assist the gc in early cleanup
+ elementData[i] = null;
+ }
+
+ public final synchronized void setElementAt(Object obj, int idx)
+ {
+ if (idx < 0 || idx >= size())
+ throw new ArrayIndexOutOfBoundsException();
+
+ elementData[idx] = obj;
+ }
+
+ public final synchronized void setSize(int newSize)
+ {
+ if (newSize < 0)
+ throw new ArrayIndexOutOfBoundsException();
+
+ // Java Lang Spec p. 658 says to remove the excess elements and discard
+ // when new size is smaller than old size.
+ // When truncating, we could alternatively just reset elementCount instead
+ // of freeing up the memory if the spec hadn't specified. The spec makes
+ // sense though; if someone cares enough to call a setSize() function
+ // they probably are doing so to free memory.
+ if (newSize < elementCount)
+ {
+ elementCount = newSize;
+ trimToSize();
+ }
+ else if (newSize > elementCount) // Skip == case
+ {
+ // TBD: ensureCapacity() may create a vector much larger than newSize;
+ // do we want to make the vector exactly newSize? Spec is unclear.
+ ensureCapacity(newSize);
+
+ // Make sure to null out new elements of grown vector
+ for (int i = elementCount; i < newSize; i++)
+ elementData[i] = null;
+ elementCount = newSize;
+ }
+ }
+
+ public final int size()
+ {
+ return elementCount;
+ }
+
+ public final synchronized String toString()
+ {
+ // Following the Java Lang Spec p. 656
+
+ // Prepend first element with open bracket
+ StringBuffer result = new StringBuffer("[");
+
+ if (elementCount > 0) // add first element if one exists
+ result.append(elementData[0].toString());
+
+ // Prepend subsequent elements with ", "
+ for (int i = 1; i < elementCount; i++)
+ result.append(", ").append(elementData[i].toString());
+
+ // Append last element with closing bracket
+ result.append("]");
+ return result.toString();
+ }
+
+ public final synchronized void trimToSize()
+ {
+ // Give up excess storage capacity to save memory
+ //
+ // Don't bother checking for the case where size() == the capacity of the
+ // vector since that is a much less likely case; it's more efficient to
+ // not do the check and lose a bit of performance in that infrequent case
+ Object[] newArray = new Object[elementCount];
+ System.arraycopy(elementData, 0, newArray, 0, elementCount);
+ elementData = newArray;
+ }
+
+ // TODO12:
+ // public Vector(Collection c)
+ // {
+ // }
+
+ // TODO12:
+ // public public boolean add(Object o)
+ // {
+ // }
+
+ // TODO12:
+ // public void add(int index, Object element)
+ // {
+ // }
+
+ // TODO12:
+ // public boolean addAll(Collection c)
+ // {
+ // }
+
+ // TODO12:
+ // public boolean addAll(int index, Collection c)
+ // {
+ // }
+
+ // TODO12:
+ // public void clear()
+ // {
+ // }
+
+ // TODO12:
+ // public boolean containsAll(Collection c)
+ // {
+ // }
+
+ // TODO12:
+ // public boolean equals(Object o)
+ // {
+ // }
+
+ // TODO12:
+ // public int hashCode()
+ // {
+ // }
+
+ // TODO12:
+ // public Object get(int index)
+ // {
+ // }
+
+ // TODO12:
+ // public boolean remove(Object o)
+ // {
+ // }
+
+ // TODO12:
+ // public Object remove(int index)
+ // {
+ // }
+
+ // TODO12:
+ // public boolean removeAll(Collection c)
+ // {
+ // }
+
+ // TODO12:
+ // public boolean retainAll(Collection c)
+ // {
+ // }
+
+ // TODO12:
+ // public Object set(int index, Object element)
+ // {
+ // }
+
+ // TODO12:
+ // public Object[] toArray()
+ // {
+ // }
+
+ // TODO12:
+ // public Object[] toArray(Object[] a)
+ // {
+ // }
+}
diff --git a/libjava/java/util/natDate.cc b/libjava/java/util/natDate.cc
new file mode 100644
index 00000000000..27f91f6fa19
--- /dev/null
+++ b/libjava/java/util/natDate.cc
@@ -0,0 +1,45 @@
+/* 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>
+
+// We want to make sure to pick up the POSIX ctime_r. Some systems,
+// such as Solaris 2.6, have their own version as well.
+#ifdef HAVE_CTIME_R
+#define _POSIX_PTHREAD_SEMANTICS
+#endif
+
+#include <cni.h>
+#include <java/util/Date.h>
+#include <java/lang/String.h>
+
+#include <time.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+jstring
+java::util::Date::toString()
+{
+#ifdef HAVE_CTIME_R
+ time_t t = millis / 1000;
+ char buf[30];
+ return JvNewStringLatin1 (ctime_r (&t, buf));
+#elif defined (HAVE_CTIME)
+ // FIXME: this isn't thread-safe.
+ time_t t = millis / 1000;
+ return JvNewStringLatin1 (ctime (&t));
+#else
+ return NULL;
+#endif
+}
diff --git a/libjava/java/util/natGregorianCalendar.cc b/libjava/java/util/natGregorianCalendar.cc
new file mode 100644
index 00000000000..cfa98bdc58d
--- /dev/null
+++ b/libjava/java/util/natGregorianCalendar.cc
@@ -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. */
+
+#include <config.h>
+
+// We want to make sure to pick up the POSIX `_r' functions. Some
+// systems, such as Solaris 2.6, require this define in order to
+// declare the functions in the appropriate header.
+#if defined (HAVE_GMTIME_R) || defined (HAVE_LOCALTIME_R)
+# define _POSIX_PTHREAD_SEMANTICS
+# ifndef _REENTRANT
+# define _REENTRANT
+# endif /* _REENTRANT */
+#endif
+
+#ifdef ECOS
+#include <string.h>
+#endif
+
+#include <cni.h>
+#include <java/util/TimeZone.h>
+#include <java/util/GregorianCalendar.h>
+#include <time.h>
+
+void
+java::util::GregorianCalendar::computeTime ()
+{
+ struct tm tim;
+ tim.tm_sec = elements(fields)[SECOND];
+ tim.tm_min = elements(fields)[MINUTE];
+ tim.tm_hour = elements(fields)[HOUR_OF_DAY];
+ tim.tm_mday = elements(fields)[DATE];
+ tim.tm_mon = elements(fields)[MONTH];
+ tim.tm_year = elements(fields)[YEAR] - 1900;
+ tim.tm_isdst = 0; // FIXME
+#ifndef ECOS
+ // FIXME: None of the standard C library access to the ECOS calendar
+ // is yet available.
+ time_t t = mktime (&tim);
+#else
+ time_t t = 0;
+#endif
+
+ // Adjust for local timezone (introduced by mktime) and our
+ // timezone.
+#if defined (STRUCT_TM_HAS_GMTOFF)
+ t += tim.tm_gmtoff;
+#elif defined (HAVE_TIMEZONE)
+ t -= timezone;
+#endif
+ java::util::TimeZone *zone = getTimeZone ();
+ t += zone->getRawOffset();
+
+ // Adjust for milliseconds.
+ time = t * 1000 + elements(fields)[MILLISECOND];
+
+ isTimeSet = true;
+}
+
+void
+java::util::GregorianCalendar::computeFields ()
+{
+ time_t t = time / 1000;
+ int millis = time % 1000;
+ if (t < 0 && millis != 0)
+ {
+ t--;
+ millis = t - 1000 * t;
+ }
+ elements(fields)[MILLISECOND] = millis;
+ struct tm tim;
+ java::util::TimeZone *zone = getTimeZone ();
+
+ // FIXME: None of the standard C library access to the ECOS calendar
+ // is yet available.
+#ifdef ECOS
+ memset (&tim, 0, sizeof tim);
+#else
+ if (zone->getRawOffset() == 0 || ! zone->useDaylightTime())
+ {
+#if defined(__JV_POSIX_THREADS__) && defined(HAVE_GMTIME_R)
+ gmtime_r (&t, &tim);
+#else
+ // Get global lock (because gmtime uses a global buffer). FIXME
+ tim = *(struct tm*) gmtime (&t);
+ // Release global lock. FIXME
+#endif
+ }
+ else
+ {
+#if defined(__JV_POSIX_THREADS__) && defined(HAVE_LOCALTIME_R)
+ localtime_r (&t, &tim);
+#else
+ // Get global lock (because localtime uses a global buffer). FIXME
+ tim = *(struct tm*) localtime (&t);
+ // Release global lock. FIXME
+#endif
+ }
+#endif /* ECOS */
+ elements(fields)[SECOND] = tim.tm_sec;
+ elements(fields)[MINUTE] = tim.tm_min;
+ elements(fields)[HOUR_OF_DAY] = tim.tm_hour;
+ elements(fields)[AM_PM] = tim.tm_hour < 12 ? AM : PM;
+ elements(fields)[HOUR] = tim.tm_hour % 12;
+ elements(fields)[DATE] = tim.tm_mday;
+ elements(fields)[MONTH] = tim.tm_mon;
+ elements(fields)[YEAR] = 1900 + tim.tm_year;
+ elements(fields)[DAY_OF_WEEK] = tim.tm_wday + 1;
+ elements(fields)[DAY_OF_WEEK_IN_MONTH] = ((tim.tm_mday - 1) / 7) + 1;
+ elements(fields)[DAY_OF_YEAR] = tim.tm_yday + 1;
+ elements(fields)[WEEK_OF_MONTH]
+ = (tim.tm_mday + 6 + (5 - tim.tm_wday + getFirstDayOfWeek()) % 7) / 7;
+ elements(fields)[WEEK_OF_YEAR]
+ = (tim.tm_yday + 7 + (5 - tim.tm_wday + getFirstDayOfWeek()) % 7) / 7;
+ elements(fields)[ERA] = AD;
+ elements(fields)[DST_OFFSET] = tim.tm_isdst <= 0 ? 0 : 60*60*1000;
+ elements(fields)[ZONE_OFFSET] = getTimeZone()->getRawOffset();
+ areFieldsSet = true;
+}
diff --git a/libjava/java/util/zip/Adler32.java b/libjava/java/util/zip/Adler32.java
new file mode 100644
index 00000000000..8e4ab9ae193
--- /dev/null
+++ b/libjava/java/util/zip/Adler32.java
@@ -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. */
+
+package java.util.zip;
+
+/**
+ * @author Per Bothner
+ * @date April 6, 1999.
+ */
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * The actual Adler32 algorithm is taken from RFC 1950.
+ * Status: Believed complete and correct.
+ */
+
+public class Adler32 implements Checksum
+{
+ private static int BASE = 65521; /* largest prime smaller than 65536 */
+
+ int s1;
+ int s2;
+
+ public Adler32 ()
+ {
+ reset();
+ }
+
+ public void reset () { s1 = 1; s2 = 0; }
+
+ public void update (int bval)
+ {
+ s1 = (s1 + (bval & 0xFF)) % BASE;
+ s2 = (s1 + s2) % BASE;
+ }
+
+ public void update (byte[] buffer)
+ {
+ update(buffer, 0, buffer.length);
+ }
+
+ public void update (byte[] buf, int off, int len)
+ {
+ int s1 = this.s1;
+ int s2 = this.s2;
+ while (len > 0)
+ {
+ // We can defer the modulo operation.
+ int n = 4000;
+ if (n > len)
+ n = len;
+ len -= n;
+ while (--n >= 0)
+ {
+ s1 = s1 + (buf[off++] & 0xFF);
+ s2 = s2 + s1;
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ this.s1 = s1;
+ this.s2 = s2;
+ }
+
+ public long getValue()
+ {
+ return ((long) s2 << 16) + s1;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libjava/java/util/zip/CRC32.java b/libjava/java/util/zip/CRC32.java
new file mode 100644
index 00000000000..ab19b58b1e9
--- /dev/null
+++ b/libjava/java/util/zip/CRC32.java
@@ -0,0 +1,70 @@
+/* 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 java.util.zip;
+
+/**
+ * @author Per Bothner
+ * @date April 1, 1999.
+ */
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * The actual CRC32 algorithm is taken from RFC 1952.
+ * Status: Believed complete and correct.
+ */
+
+public class CRC32 implements Checksum
+{
+ int crc = 0;
+
+ static int[] crc_table = make_crc_table();
+
+ /* Make the table for a fast CRC. */
+ static int[] make_crc_table ()
+ {
+ int[] crc_table = new int[256];
+ for (int n = 0; n < 256; n++)
+ {
+ int c = n;
+ for (int k = 8; --k >= 0; )
+ {
+ if ((c & 1) != 0)
+ c = 0xedb88320 ^ (c >>> 1);
+ else
+ c = c >>> 1;
+ }
+ crc_table[n] = c;
+ }
+ return crc_table;
+ }
+
+ public long getValue ()
+ {
+ return (long) crc & 0xffffffffL;
+ }
+
+ public void reset () { crc = 0; }
+
+ public void update (int bval)
+ {
+ int c = ~crc;
+ c = crc_table[(c ^ bval) & 0xff] ^ (c >>> 8);
+ crc = ~c;
+ }
+
+ public void update (byte[] buf, int off, int len)
+ {
+ int c = ~crc;
+ while (--len >= 0)
+ c = crc_table[(c ^ buf[off++]) & 0xff] ^ (c >>> 8);
+ crc = ~c;
+ }
+ public void update (byte[] buf) { update(buf, 0, buf.length); }
+}
diff --git a/libjava/java/util/zip/Checksum.java b/libjava/java/util/zip/Checksum.java
new file mode 100644
index 00000000000..85cdae238e0
--- /dev/null
+++ b/libjava/java/util/zip/Checksum.java
@@ -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 java.util.zip;
+
+/**
+ * @author Per Bothner
+ * @date January 9, 1999.
+ */
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public interface Checksum
+{
+ public long getValue ();
+
+ public void reset ();
+
+ public void update (int bval);
+
+ public void update (byte[] buf, int off, int len);
+}
diff --git a/libjava/java/util/zip/Deflater.java b/libjava/java/util/zip/Deflater.java
new file mode 100644
index 00000000000..81312e2a84f
--- /dev/null
+++ b/libjava/java/util/zip/Deflater.java
@@ -0,0 +1,13 @@
+/* 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 java.util.zip;
+
+public class Deflater
+{
+}
diff --git a/libjava/java/util/zip/DeflaterOutputStream.java b/libjava/java/util/zip/DeflaterOutputStream.java
new file mode 100644
index 00000000000..4f0b8b454a5
--- /dev/null
+++ b/libjava/java/util/zip/DeflaterOutputStream.java
@@ -0,0 +1,46 @@
+/* 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 java.util.zip;
+import java.io.*;
+
+/** JUST AN INCOMPLETE STUB! */
+
+public class DeflaterOutputStream extends FilterOutputStream
+{
+ protected byte[] buf;
+
+ protected Deflater def;
+
+ public DeflaterOutputStream(OutputStream out)
+ {
+ this(out, null, 512);
+ }
+
+ public DeflaterOutputStream(OutputStream out, Deflater defl)
+ {
+ this(out, defl, 512);
+ }
+
+ public DeflaterOutputStream(OutputStream out, Deflater defl, int bufsize)
+ {
+ super(out);
+ buf = new byte[bufsize];
+ def = defl;
+ }
+
+ public void finish () throws IOException
+ {
+ }
+
+ public void close () throws IOException
+ {
+ finish();
+ out.close();
+ }
+}
diff --git a/libjava/java/util/zip/ZipConstants.java b/libjava/java/util/zip/ZipConstants.java
new file mode 100644
index 00000000000..4aec92e02c4
--- /dev/null
+++ b/libjava/java/util/zip/ZipConstants.java
@@ -0,0 +1,13 @@
+/* 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 java.util.zip;
+
+public interface ZipConstants
+{
+}
diff --git a/libjava/java/util/zip/ZipEntry.java b/libjava/java/util/zip/ZipEntry.java
new file mode 100644
index 00000000000..d472de50cd9
--- /dev/null
+++ b/libjava/java/util/zip/ZipEntry.java
@@ -0,0 +1,84 @@
+/* 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 java.util.zip;
+
+/**
+ * @author Per Bothner
+ * @date January 6, 1999.
+ */
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public class ZipEntry
+{
+ // These values were determined using a simple test program.
+ public static final int STORED = 0;
+ public static final int DEFLATED = 8;
+
+ String comment;
+ long compressedSize = -1;
+ long crc = -1;
+ byte[] extra;
+ int method = -1;
+ String name;
+ long size = -1;
+ long time = -1;
+
+ ZipEntry next;
+
+ public ZipEntry (String name)
+ {
+ this.name = name;
+ }
+
+ public String getComment () { return comment; }
+
+ public long getCompressedSize () { return compressedSize; }
+
+ public long getCrc () { return crc; }
+
+ public byte[] getExtra() { return extra; }
+
+ public int getMethod () { return method; }
+
+ public String getName () { return name; }
+
+ public long getSize () { return size; }
+
+ public long getTime () { return time; }
+
+ public boolean isDirectory ()
+ {
+ if (name != null)
+ {
+ int nlen = name.length();
+ if (nlen > 0 && name.charAt(nlen-1) == '/')
+ return true;
+ }
+ return false;
+ }
+
+ public void setComment (String comment) { this.comment = comment; }
+
+ public void setCrc (long crc) { this.crc = crc; }
+
+ public void setExtra (byte[] extra) { this.extra = extra; }
+
+ public void setMethod(int method) { this.method = method; }
+
+ public void setSize (long size) { this.size = size; }
+
+ public void setTime (long time) { this.time = time; }
+
+ public String toString () { return name; }
+}
diff --git a/libjava/java/util/zip/ZipException.java b/libjava/java/util/zip/ZipException.java
new file mode 100644
index 00000000000..5c038a5e840
--- /dev/null
+++ b/libjava/java/util/zip/ZipException.java
@@ -0,0 +1,33 @@
+// ZipException.java
+
+/* 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. */
+
+package java.util.zip;
+
+/**
+ * @author Per Bothner
+ * @date January 9, 1999.
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification.
+ * Believed complete and correct.
+ */
+
+public class ZipException extends java.io.IOException
+{
+ public ZipException ()
+ {
+ super();
+ }
+
+ public ZipException (String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/util/zip/ZipFile.java b/libjava/java/util/zip/ZipFile.java
new file mode 100644
index 00000000000..75f0a3d94f0
--- /dev/null
+++ b/libjava/java/util/zip/ZipFile.java
@@ -0,0 +1,81 @@
+/* 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 java.util.zip;
+import java.io.*;
+
+/** JUST AN INCOMPLETE STUB! */
+
+public class ZipFile implements ZipConstants
+{
+
+ String name;
+ ZipEntry entries;
+
+ public ZipFile (String fname) throws IOException
+ {
+ name = fname;
+ // FIXME
+ }
+
+ public ZipFile (File f) throws IOException
+ {
+ this(f.getPath());
+ }
+
+ public java.util.Enumeration entries()
+ {
+ return new ZipEnumeration(this);
+ }
+
+ public void close() throws IOException
+ {
+ // FIXME
+ }
+
+ public ZipEntry getEntry(String name)
+ {
+ for (ZipEntry entry = entries; entry != null; entry = entry.next)
+ {
+ if (name.equals(entry.getName()))
+ return entry;
+ }
+ return null;
+ }
+
+ public InputStream getInputStream(ZipEntry ze) throws IOException
+ {
+ return null; // FIXME
+ }
+
+ public String getName () { return name; }
+}
+
+class ZipEnumeration implements java.util.Enumeration
+{
+ ZipEntry entry;
+
+ ZipEnumeration (ZipFile zfile)
+ {
+ entry = zfile.entries;
+ }
+
+ public boolean hasMoreElements ()
+ {
+ return entry != null;
+ }
+
+ public Object nextElement ()
+ {
+ ZipEntry cur = entry;
+ if (cur == null)
+ throw new java.util.NoSuchElementException();
+ entry = cur.next;
+ return cur;
+ }
+}
diff --git a/libjava/java/util/zip/ZipOutputStream.java b/libjava/java/util/zip/ZipOutputStream.java
new file mode 100644
index 00000000000..42cfb00169e
--- /dev/null
+++ b/libjava/java/util/zip/ZipOutputStream.java
@@ -0,0 +1,26 @@
+/* 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 java.util.zip;
+import java.io.*;
+
+/** JUST AN INCOMPLETE STUB! */
+
+public class ZipOutputStream extends DeflaterOutputStream
+ implements ZipConstants
+{
+ public ZipOutputStream (OutputStream out)
+ {
+ super(out);
+ }
+
+ public void putNextEntry (ZipEntry entry) throws IOException
+ {
+ throw new Error ("java.util.zip.ZipOutputStream.putNextEntry: not implemented");
+ }
+}