From a016eeaba0366c86f96c62fd3adca6fe9f58a086 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 13 Jul 2008 17:54:44 -0600 Subject: [PATCH 01/29] fix Long.toString for Long.MIN_VALUE case --- classpath/java/lang/Long.java | 7 ++++--- test/Misc.java | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/classpath/java/lang/Long.java b/classpath/java/lang/Long.java index bfa2c28396..76366be3ac 100644 --- a/classpath/java/lang/Long.java +++ b/classpath/java/lang/Long.java @@ -60,16 +60,17 @@ public final class Long extends Number implements Comparable { } boolean negative = v < 0; - if (negative) v = -v; int size = (negative ? 1 : 0); - for (long n = v; n > 0; n /= radix) ++size; + for (long n = v; n != 0; n /= radix) ++size; char[] array = new char[size]; int i = array.length - 1; - for (long n = v; n > 0; n /= radix) { + for (long n = v; n != 0; n /= radix) { long digit = n % radix; + if (negative) digit = -digit; + if (digit >= 0 && digit <= 9) { array[i] = (char) ('0' + digit); } else { diff --git a/test/Misc.java b/test/Misc.java index c9ce726936..5be739c5d5 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -102,7 +102,10 @@ public class Misc { expect(foo > 0); } - expect(String.valueOf(25214903884l).equals("25214903884")); + expect(String.valueOf(25214903884L).equals("25214903884")); + + expect(String.valueOf(-9223372036854775808L).equals + ("-9223372036854775808")); { boolean p = true; int[] array = new int[] { 1, 2 }; From 2e0ca311483443cf617f36f15bf6291036b3d013 Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 18:14:37 -0600 Subject: [PATCH 02/29] implement File.list and File.mkdirs --- classpath/java-io.cpp | 37 +++++++++++++++++++++++ classpath/java/io/File.java | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index f700dc69dd..481032209a 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "jni.h" #include "jni-util.h" @@ -202,6 +203,42 @@ Java_java_io_File_exists(JNIEnv* e, jclass, jstring path) } } +extern "C" JNIEXPORT jlong JNICALL +Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path) +{ + const char* chars = e->GetStringUTFChars(path, 0); + if (chars) { + jlong handle = reinterpret_cast(opendir(chars)); + e->ReleaseStringUTFChars(path, chars); + return handle; + } else { + return 0; + } +} + +extern "C" JNIEXPORT jstring JNICALL +Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle) +{ + struct dirent * directoryEntry; + + if (handle!=0) { + directoryEntry = readdir(reinterpret_cast(handle)); + if (directoryEntry == NULL) { + return NULL; + } + return e->NewStringUTF(directoryEntry->d_name); + } + return NULL; +} + +extern "C" JNIEXPORT void JNICALL +Java_java_io_File_closeDir(JNIEnv* , jclass, jlong handle) +{ + if (handle!=0) { + closedir(reinterpret_cast(handle)); + } +} + extern "C" JNIEXPORT jint JNICALL Java_java_io_FileInputStream_open(JNIEnv* e, jclass, jstring path) { diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index ec74eb157c..3cc8c6ee29 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -126,4 +126,64 @@ public class File { return false; } } + + public boolean mkdirs() { + File parent = getParentFile(); + if (parent != null) { + if (!parent.exists()) { + if (!parent.mkdirs()) { + return false; + } + } + } + return mkdir(); + } + + public String[] list() { + return list(null); + } + + public String[] list(FilenameFilter filter) { + long handle = 0; + try { + handle = openDir(path); + Pair list = null; + int count = 0; + for (String s = readDir(handle); s != null; s = readDir(handle)) { + if (filter == null || filter.accept(this, s)) { + list = new Pair(s, list); + ++ count; + } + } + + String[] result = new String[count]; + for (int i = count; i >= 0; --i) { + result[i] = list.value; + list = list.next; + } + + return result; + } finally { + if (handle != 0) { + closeDir(handle); + } + } + } + + private static native long openDir(String path); + + private static native String readDir(long handle); + + private static native long closeDir(long handle); + + private static class Pair { + public final String value; + public final Pair next; + + public Pair(String value, Pair next) { + this.value = value; + this.next = next; + } + } + } From e1d712ef71892aa5a86f3b0ba639734d1768531b Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 18:16:55 -0600 Subject: [PATCH 03/29] java.util.BitSet implementation --- classpath/java/util/BitSet.java | 169 ++++++++++++++++++++++++++++++++ test/BitsetTest.java | 64 ++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 classpath/java/util/BitSet.java create mode 100644 test/BitsetTest.java diff --git a/classpath/java/util/BitSet.java b/classpath/java/util/BitSet.java new file mode 100644 index 0000000000..89060a4893 --- /dev/null +++ b/classpath/java/util/BitSet.java @@ -0,0 +1,169 @@ +package java.util; + +import java.io.Serializable; + +/** + * @author zsombor + * + */ +public class BitSet implements Serializable, Cloneable { + + final static int BITS_PER_LONG = 64; + final static int BITS_PER_LONG_SHIFT = 6; + final static long MASK = 0xFFFFFFFFFFFFFFFFL; + + private long[] bits; + + private static int longPosition(int index) { + return index >> BITS_PER_LONG_SHIFT; + } + + private static long bitPosition(int index) { + return 1L << (index % BITS_PER_LONG); + } + + public BitSet(int bitLength) { + if (bitLength % BITS_PER_LONG == 0) { + enlarge(longPosition(bitLength)); + } else { + enlarge(longPosition(bitLength) + 1); + } + } + + public BitSet() { + enlarge(1); + } + + public void and(BitSet otherBits) { + int max = Math.max(bits.length, otherBits.bits.length); + for (int i = 0; i < max; i++) { + bits[i] &= otherBits.bits[i]; + } + } + + public void andNot(BitSet otherBits) { + int max = Math.max(bits.length, otherBits.bits.length); + enlarge(max); + for (int i = 0; i < max; i++) { + bits[i] &= ~otherBits.bits[i]; + } + } + + public void or(BitSet otherBits) { + int max = Math.max(bits.length, otherBits.bits.length); + enlarge(max); + for (int i = 0; i < max; i++) { + bits[i] |= otherBits.bits[i]; + } + } + + public void xor(BitSet otherBits) { + int max = Math.max(bits.length, otherBits.bits.length); + enlarge(max); + for (int i = 0; i < max; i++) { + bits[i] ^= otherBits.bits[i]; + } + } + + private void enlarge(int newSize) { + if (bits == null || bits.length <= newSize) { + long[] newBits = new long[newSize + 1]; + if (bits != null) { + System.arraycopy(bits, 0, newBits, 0, bits.length); + } + bits = newBits; + } + } + + public void clear(int index) { + int pos = longPosition(index); + if (pos < bits.length) { + bits[pos] &= (MASK ^ bitPosition(index)); + } + } + + public boolean get(int index) { + int pos = longPosition(index); + if (pos < bits.length) { + return (bits[pos] & bitPosition(index)) != 0; + } + return false; + } + + public void set(int index) { + int pos = longPosition(index); + enlarge(pos); + bits[pos] |= bitPosition(index); + } + + public void set(int start, int end) { + for (int i = start; i < end; i++) { + set(i); + } + } + + public void clear(int start, int end) { + for (int i = start; i < end; i++) { + clear(i); + } + } + + public boolean isEmpty() { + for (int i = 0; i < bits.length; i++) { + if (bits[i] != 0) { + return false; + } + } + return true; + } + + public boolean intersects(BitSet otherBits) { + int max = Math.max(bits.length, otherBits.bits.length); + for (int i = 0; i < max; i++) { + if ((bits[i] & otherBits.bits[i]) != 0) { + return true; + } + } + return false; + } + + public int length() { + return bits.length << BITS_PER_LONG_SHIFT; + } + + public int nextSetBit(int fromIndex) { + return nextBit(fromIndex, false); + } + + private int nextBit(int fromIndex, boolean bitClear) { + int pos = longPosition(fromIndex); + if (pos >= bits.length) { + return -1; + } + int current = fromIndex; + do { + long currValue = bits[pos]; + if (currValue == 0) { + pos++; + current = pos << BITS_PER_LONG_SHIFT; + } else { + do { + long bitPos = bitPosition(current); + if (((currValue & bitPos) != 0) ^ bitClear) { + return current; + } else { + current++; + } + } while (current % BITS_PER_LONG != 0); + } + pos++; + } while (pos < bits.length); + + return -1; + } + + public int nextClearBit(int fromIndex) { + return nextBit(fromIndex, true); + } + +} diff --git a/test/BitsetTest.java b/test/BitsetTest.java new file mode 100644 index 0000000000..5f4793e205 --- /dev/null +++ b/test/BitsetTest.java @@ -0,0 +1,64 @@ +import java.util.BitSet; + +public class BitsetTest { + + public static void main(String[] args) { + BitSet bits = new BitSet(16); + bits.set(5); + bits.set(1); + + BitSet other = new BitSet(16); + other.set(5); + + assertTrue("bit 1 is set", bits.get(1)); + assertTrue("bit 5 is set", bits.get(5)); + assertTrue("bit 0 is not set", !bits.get(0)); + assertTrue("bit 16 is not set", !bits.get(16)); + + bits.and(other); + + assertTrue("bit 5 is set", bits.get(5)); + assertTrue("bit 1 is not set", !bits.get(1)); + + bits.set(100); + + assertTrue("bit 100 is set", bits.get(100)); + assertTrue("bit 101 is not set", !bits.get(101)); + + other.set(101); + + bits.or(other); + + assertTrue("bit 101 is set", bits.get(101)); + + assertEquals("first bit is 5", 5, bits.nextSetBit(0)); + assertEquals("first bit is 5 from 3", 5, bits.nextSetBit(4)); + assertEquals("first bit is 5 from 5", 5, bits.nextSetBit(5)); + assertEquals("second bit is 100", 100, bits.nextSetBit(6)); + assertEquals("second bit is 100 from 100", 100, bits.nextSetBit(100)); + assertEquals("third bit is 101", 101, bits.nextSetBit(101)); + assertEquals("there is no 4th bit", -1, bits.nextSetBit(102)); + + assertEquals("first empty bit is 0", 0, bits.nextClearBit(0)); + assertEquals("after 5, 6 is empty", 6, bits.nextClearBit(5)); + assertEquals("after 100, 102 is empty", 102, bits.nextClearBit(100)); + + } + + static void assertTrue(String msg, boolean flag) { + if (flag) { + System.out.println(msg + " : OK."); + } else { + throw new RuntimeException("Error:"+msg); + } + } + + static void assertEquals(String msg, int expected, int actual) { + if (expected==actual) { + System.out.println(msg + " : OK. ["+actual+']'); + } else { + throw new RuntimeException("Error:"+msg+" expected:"+expected+", actual:"+actual); + } + } + +} From 0e539615e76949c3cf279bc27e6f7c5038107cab Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 18:21:04 -0600 Subject: [PATCH 04/29] add Thread.name field --- classpath/java/lang/Thread.java | 15 +++++++++++---- src/machine.cpp | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 2f7826d32c..cae4e92234 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -20,9 +20,11 @@ public class Thread implements Runnable { private boolean interrupted; private Object sleepLock; private ClassLoader classLoader; + private String name; - public Thread(Runnable task) { - this.task = task; + public Thread(Runnable task, String name) { + this(task); + this.name = name; Thread current = currentThread(); @@ -39,8 +41,8 @@ public class Thread implements Runnable { classLoader = current.classLoader; } - public Thread(Runnable task, String name) { - this(task); + public Thread(Runnable task) { + this(task, "Thread["+task+"]"); } public synchronized void start() { @@ -118,4 +120,9 @@ public class Thread implements Runnable { public static native int activeCount(); public static native int enumerate(Thread[] array); + + public String getName() { + return name; + } + } diff --git a/src/machine.cpp b/src/machine.cpp index 8703d103c4..1e6556e3f5 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1847,7 +1847,7 @@ Thread::init() threadPeer(this, javaThread) = reinterpret_cast(this); } else { this->javaThread = makeThread - (this, reinterpret_cast(this), 0, 0, 0, 0, m->loader); + (this, reinterpret_cast(this), 0, 0, 0, 0, m->loader, 0); } } From dcccddeb551754218d9a9bc8f4cfaec46cdeda65 Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 18:24:23 -0600 Subject: [PATCH 05/29] add FilenameFilter interface --- classpath/java/io/FilenameFilter.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 classpath/java/io/FilenameFilter.java diff --git a/classpath/java/io/FilenameFilter.java b/classpath/java/io/FilenameFilter.java new file mode 100644 index 0000000000..718f3973d8 --- /dev/null +++ b/classpath/java/io/FilenameFilter.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public interface FilenameFilter { + + boolean accept(File dir, String name); + +} From 975c2c12a8127811cad94b6eb17adc94f1245833 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 13 Jul 2008 18:25:26 -0600 Subject: [PATCH 06/29] add license header to BitSet.java --- classpath/java/util/BitSet.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/classpath/java/util/BitSet.java b/classpath/java/util/BitSet.java index 89060a4893..eff0cfafdf 100644 --- a/classpath/java/util/BitSet.java +++ b/classpath/java/util/BitSet.java @@ -1,3 +1,13 @@ +/* Copyright (c) 2008, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + package java.util; import java.io.Serializable; From e507a2608143c21567c55d358af38ba17aebb71f Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 18:27:05 -0600 Subject: [PATCH 07/29] add System.getProperties --- classpath/java/lang/System.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index 78cecb92ff..ac3ee11b3a 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -17,6 +17,7 @@ import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileDescriptor; +import java.util.Properties; public abstract class System { private static Property properties; @@ -76,6 +77,14 @@ public abstract class System { return null; } + public static Properties getProperties () { + Properties prop = new Properties(); + for (Property p = properties; p != null; p = p.next) { + prop.put(p.name, p.value); + } + return prop; + } + private static native String getProperty(String name, boolean[] found); private static native String getVMProperty(String name, boolean[] found); From 6409747f1792f6f7170818636e0d02cfa860b43d Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 18:27:42 -0600 Subject: [PATCH 08/29] add Properties.getProperty(String,String) --- classpath/java/util/Properties.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/classpath/java/util/Properties.java b/classpath/java/util/Properties.java index 06c3b0b07b..310665567f 100644 --- a/classpath/java/util/Properties.java +++ b/classpath/java/util/Properties.java @@ -37,6 +37,14 @@ public class Properties extends Hashtable { return (String)get(key); } + public String getProperty(String key, String defaultValue) { + String value = (String) get(key); + if (value == null) { + return defaultValue; + } + return value; + } + public void setProperty(String key, String value) { put(key, value); } From d28a860138513fceed4e4f8e49384020d69686ef Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 18:28:27 -0600 Subject: [PATCH 09/29] add Arrays.fill --- classpath/java/util/Arrays.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/classpath/java/util/Arrays.java b/classpath/java/util/Arrays.java index d51b8e6b7a..af87139c8f 100644 --- a/classpath/java/util/Arrays.java +++ b/classpath/java/util/Arrays.java @@ -106,4 +106,17 @@ public class Arrays { } }; } + + public static void fill(int[] array, int value) { + for (int i=0;i Date: Sun, 13 Jul 2008 18:34:59 -0600 Subject: [PATCH 10/29] fix recursive invocation of Thread constructor --- classpath/java/lang/Thread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index cae4e92234..731331051d 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -23,7 +23,7 @@ public class Thread implements Runnable { private String name; public Thread(Runnable task, String name) { - this(task); + this.task = task; this.name = name; Thread current = currentThread(); From 074f1a38532e2d78f27eda10499f68e9dd3961ff Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 18:46:27 -0600 Subject: [PATCH 11/29] trivial AccessController implementation --- classpath/java/security/AccessController.java | 15 +++++++++++++++ classpath/java/security/PrivilegedAction.java | 7 +++++++ 2 files changed, 22 insertions(+) create mode 100644 classpath/java/security/AccessController.java create mode 100644 classpath/java/security/PrivilegedAction.java diff --git a/classpath/java/security/AccessController.java b/classpath/java/security/AccessController.java new file mode 100644 index 0000000000..3e058771dc --- /dev/null +++ b/classpath/java/security/AccessController.java @@ -0,0 +1,15 @@ +package java.security; + +/** + * No real access control is implemented here. + * + * @author zsombor + * + */ +public class AccessController { + + public static Object doPrivileged (PrivilegedAction action) { + return action.run(); + } + +} diff --git a/classpath/java/security/PrivilegedAction.java b/classpath/java/security/PrivilegedAction.java new file mode 100644 index 0000000000..c76abc542a --- /dev/null +++ b/classpath/java/security/PrivilegedAction.java @@ -0,0 +1,7 @@ +package java.security; + +public interface PrivilegedAction { + + T run(); + +} From 2fe571c46193933d9ad51b325ab9ac6ab6b0eebd Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 18:55:05 -0600 Subject: [PATCH 12/29] add StringBuffer.append(char[]) --- classpath/java/lang/StringBuffer.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/classpath/java/lang/StringBuffer.java b/classpath/java/lang/StringBuffer.java index 2d7a1ff8cc..c3de7b00da 100644 --- a/classpath/java/lang/StringBuffer.java +++ b/classpath/java/lang/StringBuffer.java @@ -70,6 +70,11 @@ public class StringBuffer implements CharSequence { return this; } + public synchronized StringBuffer append(char[] b) { + sb.append(b, 0, b.length); + return this; + } + public synchronized StringBuffer insert(int i, String s) { sb.insert(i, s); return this; From d1b6de81310510b44ea663a88362ba75ad318eae Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 13 Jul 2008 18:56:18 -0600 Subject: [PATCH 13/29] add license headers --- classpath/java/security/AccessController.java | 10 ++++++++++ classpath/java/security/PrivilegedAction.java | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/classpath/java/security/AccessController.java b/classpath/java/security/AccessController.java index 3e058771dc..804dfe70a7 100644 --- a/classpath/java/security/AccessController.java +++ b/classpath/java/security/AccessController.java @@ -1,3 +1,13 @@ +/* Copyright (c) 2008, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + package java.security; /** diff --git a/classpath/java/security/PrivilegedAction.java b/classpath/java/security/PrivilegedAction.java index c76abc542a..5a5e54aa20 100644 --- a/classpath/java/security/PrivilegedAction.java +++ b/classpath/java/security/PrivilegedAction.java @@ -1,3 +1,13 @@ +/* Copyright (c) 2008, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + package java.security; public interface PrivilegedAction { From 99fa6d14954f572388b5af8af0ad977d04960d1b Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 18:59:30 -0600 Subject: [PATCH 14/29] add StringBuilder.indexOf --- classpath/java/lang/StringBuilder.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/classpath/java/lang/StringBuilder.java b/classpath/java/lang/StringBuilder.java index 78cfc8c287..5b4987ec4b 100644 --- a/classpath/java/lang/StringBuilder.java +++ b/classpath/java/lang/StringBuilder.java @@ -209,6 +209,29 @@ public class StringBuilder implements CharSequence { insert(start, str); return this; } + + public int indexOf(String s) { + return indexOf(s, 0); + } + + public int indexOf(String s, int start) { + int slength = s.length(); + if (slength == 0) return start; + + for (int i = start; i < length - slength + 1; ++i) { + int j = 0; + for (; j < slength; ++j) { + if (charAt(i + j) != s.charAt(j)) { + break; + } + } + if (j == slength) { + return i; + } + } + + return -1; + } public int length() { return length; From 0ffba474fa3ebd554af7f0e776286d86903dd1b1 Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 20:33:26 -0600 Subject: [PATCH 15/29] implement additional Unicode support in Character --- classpath/java/lang/Character.java | 75 ++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/classpath/java/lang/Character.java b/classpath/java/lang/Character.java index a51008cf7d..6627ae3170 100644 --- a/classpath/java/lang/Character.java +++ b/classpath/java/lang/Character.java @@ -58,6 +58,14 @@ public final class Character implements Comparable { } } + public static int toLowerCase(int codePoint) { + if (isSupplementaryCodePoint(codePoint)) { + return codePoint; + } else { + return toLowerCase((char) codePoint); + } + } + public static char toUpperCase(char c) { if (c >= 'a' && c <= 'z') { return (char) ((c - 'a') + 'A'); @@ -66,10 +74,22 @@ public final class Character implements Comparable { } } + public static int toUpperCase(int codePoint) { + if (isSupplementaryCodePoint(codePoint)) { + return codePoint; + } else { + return toUpperCase((char) codePoint); + } + } + public static boolean isDigit(char c) { return c >= '0' && c <= '9'; } + public static boolean isDigit(int c) { + return c >= '0' && c <= '9'; + } + public static int digit(char c, int radix) { int digit = 0; if ((c >= '0') && (c <= '9')) { @@ -87,6 +107,10 @@ public final class Character implements Comparable { } } + public static boolean isLetter(int c) { + return canCastToChar(c) && isLetter((char) c); + } + public static boolean isLetter(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } @@ -95,6 +119,14 @@ public final class Character implements Comparable { return isDigit(c) || isLetter(c); } + public static boolean isLetterOrDigit(int c) { + return canCastToChar(c) && (isDigit((char) c) || isLetter((char) c)); + } + + public static boolean isLowerCase(int c) { + return canCastToChar(c) && isLowerCase((char) c); + } + public static boolean isLowerCase(char c) { return (c >= 'a' && c <= 'z'); } @@ -103,6 +135,14 @@ public final class Character implements Comparable { return (c >= 'A' && c <= 'Z'); } + public static boolean isUpperCase(int c) { + return canCastToChar(c) && isUpperCase((char) c); + } + + public static boolean isWhitespace(int c) { + return canCastToChar(c) && isWhitespace((char) c); + } + public static boolean isWhitespace(char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r'; } @@ -110,4 +150,39 @@ public final class Character implements Comparable { public static boolean isSpaceChar(char c) { return isWhitespace(c); } + + public static boolean isHighSurrogate(char ch) { + return ch >= '\uD800' && ch <= '\uDBFF'; + } + + public static boolean isLowSurrogate(char ch) { + return ch >= '\uDC00' && ch <= '\uDFFF'; + } + + public static int toCodePoint(char high, char low) { + return (((high & 0x3FF) << 10) | (low & 0x3FF)) + 0x10000; + } + + public static boolean isSupplementaryCodePoint(int codePoint) { + return codePoint >= 0x10000 && codePoint <= 0x10FFFF; + } + + private static boolean canCastToChar(int codePoint) { + return (codePoint >= 0 && codePoint <= 0xFFFF); + } + + public static char[] toChars(int codePoint) { + if (isSupplementaryCodePoint(codePoint)) { + int cpPrime = codePoint - 0x10000; + int high = 0xD800 | ((cpPrime >> 10) & 0x3FF); + int low = 0xDC00 | (cpPrime & 0x3FF); + return new char[] { (char) high, (char) low }; + } + return new char[] { (char) codePoint }; + } + + public static boolean isSurrogatePair(char high, char low) { + return isHighSurrogate(high) && isLowSurrogate(low); + } + } From 4fed24270b3ffe54278d07ac53968fbb5566bacd Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 20:33:51 -0600 Subject: [PATCH 16/29] add skeleton java.util.regex classes --- classpath/java/util/regex/Matcher.java | 106 +++++++++++++++++++++++++ classpath/java/util/regex/Pattern.java | 75 +++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 classpath/java/util/regex/Matcher.java create mode 100644 classpath/java/util/regex/Pattern.java diff --git a/classpath/java/util/regex/Matcher.java b/classpath/java/util/regex/Matcher.java new file mode 100644 index 0000000000..58af1a707d --- /dev/null +++ b/classpath/java/util/regex/Matcher.java @@ -0,0 +1,106 @@ +/* Copyright (c) 2008, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +/** + * This implementation is a skeleton, useful only for compilation. At runtime it + * is need to be replaced by a working implementation, for example one from the + * Apache Harmony project. + * + * @author zsombor + * + */ +public class Matcher { + + public boolean matches() { + throw new UnsupportedOperationException(); + } + + public boolean requireEnd() { + throw new UnsupportedOperationException(); + } + + public boolean hitEnd() { + throw new UnsupportedOperationException(); + } + + public boolean lookingAt() { + throw new UnsupportedOperationException(); + } + + public Matcher reset() { + throw new UnsupportedOperationException(); + } + + public Matcher reset(CharSequence input) { + throw new UnsupportedOperationException(); + } + + public int start() { + throw new UnsupportedOperationException(); + } + + public int start(int group) { + throw new UnsupportedOperationException(); + } + + public Pattern pattern() { + throw new UnsupportedOperationException(); + } + + public Matcher region(int start, int end) { + throw new UnsupportedOperationException(); + } + + public int regionEnd() { + throw new UnsupportedOperationException(); + } + + public int regionStart() { + throw new UnsupportedOperationException(); + } + + public String replaceAll(String replacement) { + throw new UnsupportedOperationException(); + } + + public String replaceFirst(String replacement) { + throw new UnsupportedOperationException(); + } + + public int end() { + throw new UnsupportedOperationException(); + } + + public int end(int group) { + throw new UnsupportedOperationException(); + } + + public boolean find() { + throw new UnsupportedOperationException(); + } + + public boolean find(int start) { + throw new UnsupportedOperationException(); + } + + public int groupCount() { + throw new UnsupportedOperationException(); + } + + public String group() { + throw new UnsupportedOperationException(); + } + + public String group(int group) { + throw new UnsupportedOperationException(); + } +} diff --git a/classpath/java/util/regex/Pattern.java b/classpath/java/util/regex/Pattern.java new file mode 100644 index 0000000000..972f93de37 --- /dev/null +++ b/classpath/java/util/regex/Pattern.java @@ -0,0 +1,75 @@ +/* Copyright (c) 2008, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +/** + * This implementation is a skeleton, useful only for compilation. At runtime it + * is need to be replaced by a working implementation, for example one from the + * Apache Harmony project. + * + * @author zsombor + * + */ +public class Pattern { + + public static final int UNIX_LINES = 1; + public static final int CASE_INSENSITIVE = 2; + public static final int COMMENTS = 4; + public static final int MULTILINE = 8; + public static final int LITERAL = 16; + public static final int DOTALL = 32; + public static final int UNICODE_CASE = 64; + public static final int CANON_EQ = 128; + + private int patternFlags; + private String pattern; + + protected Pattern(String pattern, int flags) { + this.pattern = pattern; + this.patternFlags = flags; + } + + public static Pattern compile(String regex) { + return new Pattern(regex, 0); + } + + public static Pattern compile(String regex, int flags) { + return new Pattern(regex, flags); + } + + public int flags() { + return patternFlags; + } + + public Matcher matcher(CharSequence input) { + throw new UnsupportedOperationException(); + } + + public static boolean matches(String regex, CharSequence input) { + return Pattern.compile(regex).matcher(input).matches(); + } + + public String pattern() { + return pattern; + } + + public static String quote(String s) { + throw new UnsupportedOperationException(); + } + + public String[] split(CharSequence input) { + throw new UnsupportedOperationException(); + } + + public String[] split(CharSequence input, int limit) { + throw new UnsupportedOperationException(); + } +} From 17a42c5611410e8609f03442111f295030e4aca5 Mon Sep 17 00:00:00 2001 From: Zsombor Date: Sun, 13 Jul 2008 20:34:13 -0600 Subject: [PATCH 17/29] add a few String methods --- classpath/java/lang/String.java | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index afec95c50b..74f05c4d55 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -11,6 +11,7 @@ package java.lang; import java.io.UnsupportedEncodingException; +import java.util.regex.Pattern; public final class String implements Comparable, CharSequence { private Object data; @@ -199,14 +200,8 @@ public final class String implements Comparable, CharSequence { return -1; } - public int lastIndexOf(int c) { - for (int i = length - 1; i >= 0; --i) { - if (charAt(i) == c) { - return i; - } - } - - return -1; + public int lastIndexOf(int ch) { + return lastIndexOf(ch, length-1); } public int indexOf(String s) { @@ -303,6 +298,14 @@ public final class String implements Comparable, CharSequence { } } + public boolean startsWith(String s, int start) { + if (length >= s.length + start) { + return substring(start, s.length).compareTo(s) == 0; + } else { + return false; + } + } + public boolean endsWith(String s) { if (length >= s.length) { return substring(length - s.length).compareTo(s) == 0; @@ -429,6 +432,10 @@ public final class String implements Comparable, CharSequence { return substring(start, end); } + public boolean matches(String regex) { + return Pattern.matches(regex, this); + } + public native String intern(); public static String valueOf(Object s) { @@ -466,4 +473,14 @@ public final class String implements Comparable, CharSequence { public static String valueOf(double v) { return Double.toString(v); } + + public int lastIndexOf(int ch, int lastIndex) { + for (int i = lastIndex ; i >= 0; --i) { + if (charAt(i) == ch) { + return i; + } + } + + return -1; + } } From 7534459fecb8e86a2cadac2078ae80b8b803c9eb Mon Sep 17 00:00:00 2001 From: Eric Scharff Date: Sun, 13 Jul 2008 21:54:07 -0600 Subject: [PATCH 18/29] Stylistic tweaks --- classpath/java/io/File.java | 6 +++--- classpath/java/io/FileInputStream.java | 6 +++--- classpath/java/io/FileOutputStream.java | 6 +++--- classpath/java/io/InputStream.java | 3 +-- classpath/java/io/PushbackReader.java | 8 ++++---- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index 3cc8c6ee29..0f91ebb746 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -14,9 +14,9 @@ public class File { private static final String FileSeparator = System.getProperty("file.separator"); -// static { -// System.loadLibrary("natives"); -// } + // static { + // System.loadLibrary("natives"); + // } private final String path; diff --git a/classpath/java/io/FileInputStream.java b/classpath/java/io/FileInputStream.java index 5a141c82a6..1c7a6c9532 100644 --- a/classpath/java/io/FileInputStream.java +++ b/classpath/java/io/FileInputStream.java @@ -11,9 +11,9 @@ package java.io; public class FileInputStream extends InputStream { -// static { -// System.loadLibrary("natives"); -// } + // static { + // System.loadLibrary("natives"); + // } private int fd; diff --git a/classpath/java/io/FileOutputStream.java b/classpath/java/io/FileOutputStream.java index 4083512656..4d50412414 100644 --- a/classpath/java/io/FileOutputStream.java +++ b/classpath/java/io/FileOutputStream.java @@ -11,9 +11,9 @@ package java.io; public class FileOutputStream extends OutputStream { -// static { -// System.loadLibrary("natives"); -// } + // static { + // System.loadLibrary("natives"); + // } private int fd; diff --git a/classpath/java/io/InputStream.java b/classpath/java/io/InputStream.java index ade4c81015..a225432044 100644 --- a/classpath/java/io/InputStream.java +++ b/classpath/java/io/InputStream.java @@ -41,8 +41,7 @@ public abstract class InputStream { int c; while ((c = read(buffer, 0, (int) (size < remaining ? size : remaining))) >= 0 - && remaining > 0) - { + && remaining > 0) { remaining -= c; } return count - remaining; diff --git a/classpath/java/io/PushbackReader.java b/classpath/java/io/PushbackReader.java index b75e963773..c1d8dd5091 100644 --- a/classpath/java/io/PushbackReader.java +++ b/classpath/java/io/PushbackReader.java @@ -38,11 +38,11 @@ public class PushbackReader extends Reader { if (length > 0) { int c = in.read(b, offset, length); if (c == -1) { - if (count == 0) { - count = -1; - } + if (count == 0) { + count = -1; + } } else { - count += c; + count += c; } } From 2d1ec11edcfce6a965266f22c2a13adb937ae494 Mon Sep 17 00:00:00 2001 From: Matt Weaver Date: Mon, 14 Jul 2008 08:45:51 -0600 Subject: [PATCH 19/29] Added no arg constructor to support Comparable types. --- classpath/java/util/TreeSet.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/classpath/java/util/TreeSet.java b/classpath/java/util/TreeSet.java index e4e70a9507..a2eddfe22a 100644 --- a/classpath/java/util/TreeSet.java +++ b/classpath/java/util/TreeSet.java @@ -23,6 +23,15 @@ public class TreeSet extends AbstractSet implements Collection { size = 0; } + public TreeSet() { + set = new PersistentSet(new Comparator>() { + public int compare(Cell a, Cell b) { + return ((Comparable)a).compareTo(b); + } + }); + size = 0; + } + public Iterator iterator() { return new MyIterator(set.first()); } From 920034e2315fd44bb14b547f0698bfad6f7a20c6 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 14 Jul 2008 11:02:43 -0600 Subject: [PATCH 20/29] use JavaVMInitArgs instead of JDK1_1InitArgs in JNI_CreateJavaVM; support -Xbootclasspath option --- readme.txt | 38 ++++------------ src/common.h | 2 + src/jnienv.cpp | 118 +++++++++++++++++++++++++++++++++---------------- src/main.cpp | 109 ++++++++++++++++++++++----------------------- 4 files changed, 141 insertions(+), 126 deletions(-) diff --git a/readme.txt b/readme.txt index fd4d549fbc..f28c70ebeb 100644 --- a/readme.txt +++ b/readme.txt @@ -176,40 +176,18 @@ extern "C" { } // extern "C" -#ifdef JNI_VERSION_1_6 -typedef struct JDK1_1InitArgs { - jint version; - - char **properties; - jint checkSource; - jint nativeStackSize; - jint javaStackSize; - jint minHeapSize; - jint maxHeapSize; - jint verifyMode; - char *classpath; - - jint (JNICALL *vfprintf)(FILE *fp, const char *format, va_list args); - void (JNICALL *exit)(jint code); - void (JNICALL *abort)(void); - - jint enableClassGC; - jint enableVerboseGC; - jint disableAsyncGC; - jint verbose; - jboolean debugging; - jint debugPort; -} JDK1_1InitArgs; -#endif - int main(int ac, const char** av) { - JDK1_1InitArgs vmArgs; - vmArgs.version = 0x00010001; - JNI_GetDefaultJavaVMInitArgs(&vmArgs); + JavaVMInitArgs vmArgs; + vmArgs.version = JNI_VERSION_1_2; + vmArgs.nOptions = 1; + vmArgs.ignoreUnrecognized = JNI_TRUE; - vmArgs.classpath = const_cast("[bootJar]"); + JavaVMOption options[vmArgs.nOptions]; + vmArgs.options = options; + + options[0].optionString = const_cast("-Djava.class.path=[bootJar]"); JavaVM* vm; void* env; diff --git a/src/common.h b/src/common.h index a02627b5d8..f0ac8f60cf 100644 --- a/src/common.h +++ b/src/common.h @@ -23,8 +23,10 @@ #undef JNIEXPORT #ifdef __MINGW32__ # define JNIEXPORT __declspec(dllexport) +# define PATH_SEPARATOR ';' #else # define JNIEXPORT __attribute__ ((visibility("default"))) +# define PATH_SEPARATOR ':' #endif #ifdef __i386__ diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 9d2147e432..27827d86f9 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -1845,30 +1845,39 @@ IsSameObject(Thread* t, jobject a, jobject b) } } -struct JDK1_1InitArgs { +struct JavaVMOption { + char* optionString; + void* extraInfo; +}; + +struct JavaVMInitArgs { jint version; - const char** properties; - jint checkSource; - jint nativeStackSize; - jint javaStackSize; - jint minHeapSize; - jint maxHeapSize; - jint verifyMode; - const char* classpath; - - jint (JNICALL *vfprintf)(FILE* fp, const char* format, va_list args); - void (JNICALL *exit)(jint code); - void (JNICALL *abort)(void); - - jint enableClassGC; - jint enableVerboseGC; - jint disableAsyncGC; - jint verbose; - jboolean debugging; - jint debugPort; + jint nOptions; + JavaVMOption* options; + jboolean ignoreUnrecognized; }; +int +parseSize(const char* s) +{ + unsigned length = strlen(s); + char buffer[length + 1]; + if (length == 0) { + return 0; + } else if (s[length - 1] == 'k') { + memcpy(buffer, s, length - 1); + buffer[length] = 0; + return atoi(buffer) * 1024; + } else if (s[length - 1] == 'm') { + memcpy(buffer, s, length - 1); + buffer[length] = 0; + return atoi(buffer) * 1024 * 1024; + } else { + return atoi(s); + } +} + } // namespace namespace vm { @@ -2040,43 +2049,74 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) } // namespace vm -extern "C" JNIEXPORT jint JNICALL -JNI_GetDefaultJavaVMInitArgs(void* args) -{ - JDK1_1InitArgs* a = static_cast(args); - a->maxHeapSize = 128 * 1024 * 1024; - a->classpath = "."; - a->properties = 0; - return 0; -} - #define BUILTINS_PROPERTY "avian.builtins" #define BOOTSTRAP_PROPERTY "avian.bootstrap" +#define CLASSPATH_PROPERTY "java.class.path" + +extern "C" JNIEXPORT jint JNICALL +JNI_GetDefaultJavaVMInitArgs(void*) +{ + return 0; +} extern "C" JNIEXPORT jint JNICALL JNI_CreateJavaVM(Machine** m, Thread** t, void* args) { - JDK1_1InitArgs* a = static_cast(args); + JavaVMInitArgs* a = static_cast(args); + unsigned heapLimit = 0; const char* builtins = 0; const char* bootLibrary = 0; - if (a->properties) { - for (const char** p = a->properties; *p; ++p) { - if (strncmp(*p, BUILTINS_PROPERTY "=", + const char* classpath = 0; + const char* bootClasspath = 0; + + for (int i = 0; i < a->nOptions; ++i) { + if (strncmp(a->options[i].optionString, "-Xmx", 4) == 0) { + heapLimit = parseSize(a->options[i].optionString + 4); + } else if (strncmp(a->options[i].optionString, + "-Xbootclasspath:", 16) == 0) + { + bootClasspath = a->options[i].optionString + 16; + } else if (strncmp(a->options[i].optionString, "-D", 2) == 0) { + const char* p = a->options[i].optionString + 2; + if (strncmp(p, BUILTINS_PROPERTY "=", sizeof(BUILTINS_PROPERTY)) == 0) { - builtins = (*p) + sizeof(BUILTINS_PROPERTY); - } else if (strncmp(*p, BOOTSTRAP_PROPERTY "=", + builtins = p + sizeof(BUILTINS_PROPERTY); + } else if (strncmp(p, BOOTSTRAP_PROPERTY "=", sizeof(BOOTSTRAP_PROPERTY)) == 0) { - bootLibrary = (*p) + sizeof(BOOTSTRAP_PROPERTY); + bootLibrary = p + sizeof(BOOTSTRAP_PROPERTY); + } else if (strncmp(p, CLASSPATH_PROPERTY "=", + sizeof(CLASSPATH_PROPERTY)) == 0) + { + classpath = p + sizeof(CLASSPATH_PROPERTY); } + + // todo: add properties to VM } } + if (heapLimit == 0) heapLimit = 128 * 1024 * 1024; + + if (classpath == 0) classpath = "."; + + unsigned bcpl = bootClasspath ? strlen(bootClasspath) : 0; + unsigned cpl = strlen(classpath); + + unsigned classpathBufferSize = bcpl + cpl + 2; + char classpathBuffer[classpathBufferSize]; + + if (bootClasspath) { + snprintf(classpathBuffer, classpathBufferSize, "%s%c%s", + bootClasspath, PATH_SEPARATOR, classpath); + } else { + memcpy(classpathBuffer, classpath, cpl + 1); + } + System* s = makeSystem(); - Heap* h = makeHeap(s, a->maxHeapSize); - Finder* f = makeFinder(s, a->classpath, bootLibrary); + Heap* h = makeHeap(s, heapLimit); + Finder* f = makeFinder(s, classpathBuffer, bootLibrary); Processor* p = makeProcessor(s, h); *m = new (h->allocate(sizeof(Machine))) diff --git a/src/main.cpp b/src/main.cpp index f2557e3a68..0624f3cbc9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,33 +20,6 @@ # define PATH_SEPARATOR ':' #endif -#ifdef JNI_VERSION_1_6 -// todo: use JavaVMInitArgs instead -typedef struct JDK1_1InitArgs { - jint version; - - char **properties; - jint checkSource; - jint nativeStackSize; - jint javaStackSize; - jint minHeapSize; - jint maxHeapSize; - jint verifyMode; - char *classpath; - - jint (JNICALL *vfprintf)(FILE *fp, const char *format, va_list args); - void (JNICALL *exit)(jint code); - void (JNICALL *abort)(void); - - jint enableClassGC; - jint enableVerboseGC; - jint disableAsyncGC; - jint verbose; - jboolean debugging; - jint debugPort; -} JDK1_1InitArgs; -#endif - namespace { void @@ -62,22 +35,25 @@ usageAndExit(const char* name) int main(int ac, const char** av) { - JDK1_1InitArgs vmArgs; - vmArgs.version = 0x00010001; - JNI_GetDefaultJavaVMInitArgs(&vmArgs); + JavaVMInitArgs vmArgs; + vmArgs.version = JNI_VERSION_1_2; + vmArgs.nOptions = 1; + vmArgs.ignoreUnrecognized = JNI_TRUE; const char* class_ = 0; int argc = 0; const char** argv = 0; - int propertyCount = 0; + const char* classpath = "."; for (int i = 1; i < ac; ++i) { - if (strcmp(av[i], "-cp") == 0) { - vmArgs.classpath = const_cast(av[++i]); - } else if (strncmp(av[i], "-Xmx", 4) == 0) { - vmArgs.maxHeapSize = atoi(av[i] + 4); - } else if (strncmp(av[i], "-D", 2) == 0) { - ++ propertyCount; + if (strcmp(av[i], "-cp") == 0 + or strcmp(av[i], "-classpath") == 0) + { + classpath = av[++i]; + } else if (strncmp(av[i], "-X", 2) == 0 + or strncmp(av[i], "-D", 2) == 0) + { + ++ vmArgs.nOptions; } else { class_ = av[i++]; if (i < ac) { @@ -88,35 +64,54 @@ main(int ac, const char** av) } } -#ifdef BOOT_CLASSPATH - unsigned size = sizeof(BOOT_CLASSPATH) + 1 + strlen(vmArgs.classpath); - char classpath[size]; - snprintf(classpath, size, "%s%c%s", - BOOT_CLASSPATH, PATH_SEPARATOR, vmArgs.classpath); - vmArgs.classpath = classpath; +#ifdef BOOT_LIBRARY + ++ vmArgs.nOptions; #endif + JavaVMOption options[vmArgs.nOptions]; + vmArgs.options = options; + +#ifdef BOOT_CLASSPATH + unsigned classpathBufferSize + = sizeof(BOOT_CLASSPATH) + 1 + strlen(classpath); + char classpathBuffer[classpathBufferSize]; + + snprintf(classpathBuffer, classpathBufferSize, "%s%c%s", + BOOT_CLASSPATH, PATH_SEPARATOR, classpath); + classpath = classpathBuffer; +#endif + + unsigned optionIndex = 0; + #ifdef BOOT_LIBRARY - const int BootPropertyCount = 1; -#else - const int BootPropertyCount = 0; + options[optionIndex++].optionString + = const_cast("-Davian.bootstrap=" BOOT_LIBRARY); #endif - const char* properties[propertyCount + BootPropertyCount + 1]; - properties[propertyCount + BootPropertyCount] = 0; +#define CLASSPATH_PROPERTY "-Djava.class.path=" + + unsigned classpathSize = strlen(classpath); + unsigned classpathPropertyBufferSize + = sizeof(CLASSPATH_PROPERTY) + classpathSize; + + char classpathPropertyBuffer[classpathPropertyBufferSize]; + memcpy(classpathPropertyBuffer, + CLASSPATH_PROPERTY, + sizeof(CLASSPATH_PROPERTY) - 1); + memcpy(classpathPropertyBuffer + sizeof(CLASSPATH_PROPERTY) - 1, + classpath, + classpathSize + 1); + + options[optionIndex++].optionString = classpathPropertyBuffer; + for (int i = 1; i < ac; ++i) { - if (strncmp(av[i], "-D", 2) == 0) { - properties[--propertyCount] = av[i] + 2; + if (strncmp(av[i], "-X", 2) == 0 + or strncmp(av[i], "-D", 2) == 0) + { + options[optionIndex++].optionString = const_cast(av[i]); } } -#ifdef BOOT_LIBRARY - properties[propertyCount + BootPropertyCount - 1] - = "avian.bootstrap=" BOOT_LIBRARY; -#endif - - vmArgs.properties = const_cast(properties); - if (class_ == 0) { usageAndExit(av[0]); } From f81e9f7f5d953ca317e2af8770a6d9e840f91379 Mon Sep 17 00:00:00 2001 From: Matt Weaver Date: Mon, 14 Jul 2008 11:05:33 -0600 Subject: [PATCH 21/29] Added for compliance. This makes IDEs happy, as certain types of "warning" casts are somewhat unavoidable. As it is small and potentially useful, I threw it in. --- classpath/java/lang/SuppressWarnings.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 classpath/java/lang/SuppressWarnings.java diff --git a/classpath/java/lang/SuppressWarnings.java b/classpath/java/lang/SuppressWarnings.java new file mode 100644 index 0000000000..5e35ed01ba --- /dev/null +++ b/classpath/java/lang/SuppressWarnings.java @@ -0,0 +1,6 @@ +package java.lang; + + +public @interface SuppressWarnings { + String[] value(); +} From a6853fa820eb1be1e8d3ce90129b7ad41e21e9f2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 14 Jul 2008 11:16:34 -0600 Subject: [PATCH 22/29] rename -Xbootclasspath option to -Xbootclasspath/p to match Sun syntax and semantics --- src/jnienv.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 27827d86f9..db6f774f26 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -2068,15 +2068,15 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) const char* builtins = 0; const char* bootLibrary = 0; const char* classpath = 0; - const char* bootClasspath = 0; + const char* bootClasspathPrepend = 0; for (int i = 0; i < a->nOptions; ++i) { if (strncmp(a->options[i].optionString, "-Xmx", 4) == 0) { heapLimit = parseSize(a->options[i].optionString + 4); } else if (strncmp(a->options[i].optionString, - "-Xbootclasspath:", 16) == 0) + "-Xbootclasspath/p:", 16) == 0) { - bootClasspath = a->options[i].optionString + 16; + bootClasspathPrepend = a->options[i].optionString + 16; } else if (strncmp(a->options[i].optionString, "-D", 2) == 0) { const char* p = a->options[i].optionString + 2; if (strncmp(p, BUILTINS_PROPERTY "=", @@ -2101,15 +2101,15 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) if (classpath == 0) classpath = "."; - unsigned bcpl = bootClasspath ? strlen(bootClasspath) : 0; + unsigned bcppl = bootClasspathPrepend ? strlen(bootClasspathPrepend) : 0; unsigned cpl = strlen(classpath); - unsigned classpathBufferSize = bcpl + cpl + 2; + unsigned classpathBufferSize = bcppl + cpl + 2; char classpathBuffer[classpathBufferSize]; - if (bootClasspath) { + if (bootClasspathPrepend) { snprintf(classpathBuffer, classpathBufferSize, "%s%c%s", - bootClasspath, PATH_SEPARATOR, classpath); + bootClasspathPrepend, PATH_SEPARATOR, classpath); } else { memcpy(classpathBuffer, classpath, cpl + 1); } From d20fc697cbca4854dfda974ae66d58186d0bc3d5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 14 Jul 2008 11:21:59 -0600 Subject: [PATCH 23/29] update usage message --- src/main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0624f3cbc9..8f094fc489 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,8 +25,12 @@ namespace { void usageAndExit(const char* name) { - fprintf(stderr, "usage: %s [-cp ] [-Xmx] " - " [ ...]\n", name); + fprintf + (stderr, "usage: %s\n" + "\t[{-cp|-classpath} ]\n" + "\t[-Xmx]\n" + "\t[-Xbootclasspath/p:]\n" + "\t [ ...]\n", name); exit(-1); } From cfaf69030675b07dc672e69ac0350b0317da9a12 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 14 Jul 2008 11:23:33 -0600 Subject: [PATCH 24/29] update usage message (part 2) --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index 8f094fc489..69fcb0cdfc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,7 @@ usageAndExit(const char* name) "\t[{-cp|-classpath} ]\n" "\t[-Xmx]\n" "\t[-Xbootclasspath/p:]\n" + "\t[-D= ...]\n" "\t [ ...]\n", name); exit(-1); } From a2ba391b89058c57fda14ade678f70cc5cc38d30 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 14 Jul 2008 11:51:20 -0600 Subject: [PATCH 25/29] support -Xbootclasspath and -Xbootclasspath/a options --- src/jnienv.cpp | 57 +++++++++++++++++++++++++++++++++++++------------- src/main.cpp | 21 ++++++++++--------- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index db6f774f26..ab0f18a304 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -1878,6 +1878,16 @@ parseSize(const char* s) } } +void +append(char** p, const char* value, unsigned length, char tail) +{ + if (length) { + memcpy(*p, value, length); + *p += length; + *((*p)++) = tail; + } +} + } // namespace namespace vm { @@ -2052,6 +2062,9 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) #define BUILTINS_PROPERTY "avian.builtins" #define BOOTSTRAP_PROPERTY "avian.bootstrap" #define CLASSPATH_PROPERTY "java.class.path" +#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p" +#define BOOTCLASSPATH_OPTION "bootclasspath" +#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" extern "C" JNIEXPORT jint JNICALL JNI_GetDefaultJavaVMInitArgs(void*) @@ -2068,15 +2081,28 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) const char* builtins = 0; const char* bootLibrary = 0; const char* classpath = 0; - const char* bootClasspathPrepend = 0; + const char* bootClasspathPrepend = ""; + const char* bootClasspath = ""; + const char* bootClasspathAppend = ""; for (int i = 0; i < a->nOptions; ++i) { - if (strncmp(a->options[i].optionString, "-Xmx", 4) == 0) { - heapLimit = parseSize(a->options[i].optionString + 4); - } else if (strncmp(a->options[i].optionString, - "-Xbootclasspath/p:", 16) == 0) - { - bootClasspathPrepend = a->options[i].optionString + 16; + if (strncmp(a->options[i].optionString, "-X", 2) == 0) { + const char* p = a->options[i].optionString + 2; + if (strncmp(p, "mx", 2) == 0) { + heapLimit = parseSize(p + 2); + } else if (strncmp(p, BOOTCLASSPATH_PREPEND_OPTION ":", + sizeof(BOOTCLASSPATH_PREPEND_OPTION)) == 0) + { + bootClasspathPrepend = p + sizeof(BOOTCLASSPATH_PREPEND_OPTION); + } else if (strncmp(p, BOOTCLASSPATH_OPTION ":", + sizeof(BOOTCLASSPATH_OPTION)) == 0) + { + bootClasspath = p + sizeof(BOOTCLASSPATH_OPTION); + } else if (strncmp(p, BOOTCLASSPATH_APPEND_OPTION ":", + sizeof(BOOTCLASSPATH_APPEND_OPTION)) == 0) + { + bootClasspathAppend = p + sizeof(BOOTCLASSPATH_APPEND_OPTION); + } } else if (strncmp(a->options[i].optionString, "-D", 2) == 0) { const char* p = a->options[i].optionString + 2; if (strncmp(p, BUILTINS_PROPERTY "=", @@ -2101,18 +2127,19 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) if (classpath == 0) classpath = "."; - unsigned bcppl = bootClasspathPrepend ? strlen(bootClasspathPrepend) : 0; + unsigned bcppl = strlen(bootClasspathPrepend); + unsigned bcpl = strlen(bootClasspath); + unsigned bcpal = strlen(bootClasspathAppend); unsigned cpl = strlen(classpath); - unsigned classpathBufferSize = bcppl + cpl + 2; + unsigned classpathBufferSize = bcppl + bcpl + bcpal + cpl + 4; char classpathBuffer[classpathBufferSize]; + char* classpathPointer = classpathBuffer; - if (bootClasspathPrepend) { - snprintf(classpathBuffer, classpathBufferSize, "%s%c%s", - bootClasspathPrepend, PATH_SEPARATOR, classpath); - } else { - memcpy(classpathBuffer, classpath, cpl + 1); - } + append(&classpathPointer, bootClasspathPrepend, bcppl, PATH_SEPARATOR); + append(&classpathPointer, bootClasspath, bcpl, PATH_SEPARATOR); + append(&classpathPointer, bootClasspathAppend, bcpal, PATH_SEPARATOR); + append(&classpathPointer, classpath, cpl, 0); System* s = makeSystem(); Heap* h = makeHeap(s, heapLimit); diff --git a/src/main.cpp b/src/main.cpp index 69fcb0cdfc..b784314579 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,8 @@ usageAndExit(const char* name) "\t[{-cp|-classpath} ]\n" "\t[-Xmx]\n" "\t[-Xbootclasspath/p:]\n" + "\t[-Xbootclasspath:]\n" + "\t[-Xbootclasspath/a:]\n" "\t[-D= ...]\n" "\t [ ...]\n", name); exit(-1); @@ -73,21 +75,20 @@ main(int ac, const char** av) ++ vmArgs.nOptions; #endif +#ifdef BOOT_CLASSPATH + ++ vmArgs.nOptions; +#endif + JavaVMOption options[vmArgs.nOptions]; vmArgs.options = options; -#ifdef BOOT_CLASSPATH - unsigned classpathBufferSize - = sizeof(BOOT_CLASSPATH) + 1 + strlen(classpath); - char classpathBuffer[classpathBufferSize]; - - snprintf(classpathBuffer, classpathBufferSize, "%s%c%s", - BOOT_CLASSPATH, PATH_SEPARATOR, classpath); - classpath = classpathBuffer; -#endif - unsigned optionIndex = 0; +#ifdef BOOT_CLASSPATH + options[optionIndex++].optionString + = const_cast("-Xbootclasspath:" BOOT_CLASSPATH); +#endif + #ifdef BOOT_LIBRARY options[optionIndex++].optionString = const_cast("-Davian.bootstrap=" BOOT_LIBRARY); From 0ae338e74ac128270da77b34f796f0bf6c3ed17a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 15 Jul 2008 08:59:00 -0600 Subject: [PATCH 26/29] fix various bugs in BufferedReader.readLine --- classpath/java/io/BufferedReader.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/classpath/java/io/BufferedReader.java b/classpath/java/io/BufferedReader.java index 6d67e71c29..3db923c5e9 100644 --- a/classpath/java/io/BufferedReader.java +++ b/classpath/java/io/BufferedReader.java @@ -38,16 +38,18 @@ public class BufferedReader extends Reader { } if (position >= limit) { - return sb.toString(); + return sb.length() == 0 ? null : sb.toString(); } for (int i = position; i < limit; ++i) { if (buffer[i] == '\n') { - sb.append(buffer, position, i); + sb.append(buffer, position, i - position); position = i + 1; return sb.toString(); } } + sb.append(buffer, position, limit-position); + position = limit; } } From 13a535d1c6f973e60d305ae58ecfac862e47bdae Mon Sep 17 00:00:00 2001 From: Eric Scharff Date: Tue, 15 Jul 2008 09:36:52 -0600 Subject: [PATCH 27/29] Added a getContentLength() method to URLConnection This is particularly important if you want to get the number of bytes of a resource loaded by the class loader: getClass().getResource("myFile").openConnection().getContentLength() --- classpath/java/net/URL.java | 6 ++++++ classpath/java/net/URLConnection.java | 4 ++++ src/builtin.cpp | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/classpath/java/net/URL.java b/classpath/java/net/URL.java index 4a1f577873..bf2174c447 100644 --- a/classpath/java/net/URL.java +++ b/classpath/java/net/URL.java @@ -100,6 +100,10 @@ public final class URL { super(url); } + public int getContentLength() { + return ResourceInputStream.getContentLength(url.getFile()); + } + public InputStream getInputStream() throws IOException { return new ResourceInputStream(url.getFile()); } @@ -116,6 +120,8 @@ public final class URL { } } + private static native int getContentLength(String path); + private static native long open(String path) throws IOException; private static native int read(long peer, int position) throws IOException; diff --git a/classpath/java/net/URLConnection.java b/classpath/java/net/URLConnection.java index b0c6e8a235..ab8f5619e4 100644 --- a/classpath/java/net/URLConnection.java +++ b/classpath/java/net/URLConnection.java @@ -25,6 +25,10 @@ public abstract class URLConnection { return getInputStream(); } + public int getContentLength() { + return -1; + } + public InputStream getInputStream() throws IOException { throw new UnknownServiceException(); } diff --git a/src/builtin.cpp b/src/builtin.cpp index df32700e42..396088dc56 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -741,6 +741,26 @@ Java_java_lang_Thread_enumerate(Thread* t, jclass, jobjectArray array) return count; } +extern "C" JNIEXPORT jint JNICALL +Java_java_net_URL_00024ResourceInputStream_getContentLength +(Thread* t, jclass, jstring path) +{ + ENTER(t, Thread::ActiveState); + + if (LIKELY(path)) { + char p[stringLength(t, *path) + 1]; + stringChars(t, *path, p); + + System::Region* r = t->m->finder->find(p); + if (r) { + jint rSize = r->length(); + r->dispose(); + return rSize; + } + } + return -1; +} + extern "C" JNIEXPORT jlong JNICALL Java_java_net_URL_00024ResourceInputStream_open (Thread* t, jclass, jstring path) From 360ab7d9f9de3cf53860a54130d451f33e4c3184 Mon Sep 17 00:00:00 2001 From: Eric Scharff Date: Tue, 15 Jul 2008 15:31:01 -0600 Subject: [PATCH 28/29] Fix typo in mac build instructions --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index f28c70ebeb..2efc5b8c84 100644 --- a/readme.txt +++ b/readme.txt @@ -142,7 +142,7 @@ for darwin-i386: (objcopy is not currently supported on this platform, so we use the binaryToMacho utility instead) $ ../build/darwin-i386-compile-fast/binaryToMacho boot.jar \ - __binary_boot_jar_start __binary_boot_jar_size > boot-jar.o + __binary_boot_jar_start __binary_boot_jar_end > boot-jar.o Step 4: Write a driver which starts the VM and runs the desired main From a677a2da173cdd2a61f70b8223f012ac43a8798b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 17 Jul 2008 15:46:54 -0600 Subject: [PATCH 29/29] fix class cast exception in TreeSet ctor --- classpath/java/util/TreeSet.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/classpath/java/util/TreeSet.java b/classpath/java/util/TreeSet.java index a2eddfe22a..eaff92106a 100644 --- a/classpath/java/util/TreeSet.java +++ b/classpath/java/util/TreeSet.java @@ -24,12 +24,11 @@ public class TreeSet extends AbstractSet implements Collection { } public TreeSet() { - set = new PersistentSet(new Comparator>() { - public int compare(Cell a, Cell b) { - return ((Comparable)a).compareTo(b); - } + this(new Comparator() { + public int compare(T a, T b) { + return ((Comparable) a).compareTo(b); + } }); - size = 0; } public Iterator iterator() {