diff --git a/classpath/java/io/InputStreamReader.java b/classpath/java/io/InputStreamReader.java index feb9c3df7d..6cb8a7c80f 100644 --- a/classpath/java/io/InputStreamReader.java +++ b/classpath/java/io/InputStreamReader.java @@ -16,6 +16,17 @@ public class InputStreamReader extends Reader { public InputStreamReader(InputStream in) { this.in = in; } + + public InputStreamReader(InputStream in, String encoding) + throws UnsupportedEncodingException + { + this(in); + + if (! encoding.equals("UTF-8")) { + throw new UnsupportedEncodingException(encoding); + } + } + public int read(char[] b, int offset, int length) throws IOException { byte[] buffer = new byte[length]; diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index e2295cdc89..8363f9a1fd 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -32,6 +32,13 @@ public final class String implements Comparable, CharSequence { this(data, 0, data.length); } + public String(byte bytes[], int offset, int length, String charsetName) throws UnsupportedEncodingException { + this(bytes, offset, length); + if (!charsetName.equals("UTF-8")) { + throw new UnsupportedEncodingException(charsetName); + } + } + public String(byte[] data, int offset, int length, boolean copy) { this((Object) data, offset, length, copy); } diff --git a/classpath/java/nio/channels/SocketChannel.java b/classpath/java/nio/channels/SocketChannel.java index aa723030db..0edc605ce2 100644 --- a/classpath/java/nio/channels/SocketChannel.java +++ b/classpath/java/nio/channels/SocketChannel.java @@ -57,6 +57,8 @@ public class SocketChannel extends SelectableChannel } private int doConnect(String host, int port) throws Exception { + if (host == null) throw new NullPointerException(); + boolean b[] = new boolean[1]; int s = natDoConnect(host, port, b); connected = b[0]; @@ -66,7 +68,11 @@ public class SocketChannel extends SelectableChannel public int read(ByteBuffer b) throws IOException { if (! isOpen()) return -1; if (b.remaining() == 0) return 0; - int r = natRead(socket, b.array(), b.arrayOffset() + b.position(), b.remaining()); + + byte[] array = b.array(); + if (array == null) throw new NullPointerException(); + + int r = natRead(socket, array, b.arrayOffset() + b.position(), b.remaining()); if (r > 0) { b.position(b.position() + r); } @@ -78,7 +84,11 @@ public class SocketChannel extends SelectableChannel natThrowWriteError(socket); } if (b.remaining() == 0) return 0; - int w = natWrite(socket, b.array(), b.arrayOffset() + b.position(), b.remaining()); + + byte[] array = b.array(); + if (array == null) throw new NullPointerException(); + + int w = natWrite(socket, array, b.arrayOffset() + b.position(), b.remaining()); if (w > 0) { b.position(b.position() + w); } diff --git a/classpath/java/util/BitSet.java b/classpath/java/util/BitSet.java index eff0cfafdf..3b1e80bc61 100644 --- a/classpath/java/util/BitSet.java +++ b/classpath/java/util/BitSet.java @@ -45,16 +45,20 @@ public class BitSet implements Serializable, Cloneable { } public void and(BitSet otherBits) { - int max = Math.max(bits.length, otherBits.bits.length); - for (int i = 0; i < max; i++) { + int min = Math.min(bits.length, otherBits.bits.length); + for (int i = 0; i < min; i++) { bits[i] &= otherBits.bits[i]; } + for (int i = min; i < bits.length; i++) { + bits[i] = 0; + } } public void andNot(BitSet otherBits) { int max = Math.max(bits.length, otherBits.bits.length); enlarge(max); - for (int i = 0; i < max; i++) { + int min = Math.min(bits.length, otherBits.bits.length); + for (int i = 0; i < min; i++) { bits[i] &= ~otherBits.bits[i]; } } @@ -62,7 +66,8 @@ public class BitSet implements Serializable, Cloneable { public void or(BitSet otherBits) { int max = Math.max(bits.length, otherBits.bits.length); enlarge(max); - for (int i = 0; i < max; i++) { + int min = Math.min(bits.length, otherBits.bits.length); + for (int i = 0; i < min; i++) { bits[i] |= otherBits.bits[i]; } } @@ -70,13 +75,14 @@ public class BitSet implements Serializable, Cloneable { public void xor(BitSet otherBits) { int max = Math.max(bits.length, otherBits.bits.length); enlarge(max); - for (int i = 0; i < max; i++) { + int min = Math.min(bits.length, otherBits.bits.length); + for (int i = 0; i < min; i++) { bits[i] ^= otherBits.bits[i]; } } private void enlarge(int newSize) { - if (bits == null || bits.length <= newSize) { + if (bits == null || bits.length < newSize) { long[] newBits = new long[newSize + 1]; if (bits != null) { System.arraycopy(bits, 0, newBits, 0, bits.length); diff --git a/classpath/java/util/Collections.java b/classpath/java/util/Collections.java index 70639abd32..9582ff0884 100644 --- a/classpath/java/util/Collections.java +++ b/classpath/java/util/Collections.java @@ -13,6 +13,25 @@ package java.util; public class Collections { private Collections() { } + public static void shuffle(List list, Random random) { + Object[] array = toArray(list, new Object[list.size()]); + for (int i = 0; i < array.length; ++i) { + int j = random.nextInt(array.length); + Object tmp = array[i]; + array[i] = array[j]; + array[j] = tmp; + } + + list.clear(); + for (int i = 0; i < array.length; ++i) { + list.add(array[i]); + } + } + + public static void shuffle(List list) { + shuffle(list, new Random()); + } + static T[] toArray(Collection collection, T[] array) { Class c = array.getClass().getComponentType(); @@ -106,6 +125,63 @@ public class Collections { return new SynchronizedIterator(lock, collection.iterator()); } } + + static class SynchronizedMap implements Map { + protected final Object lock; + protected final Map map; + + SynchronizedMap(Map map) { + this.map = map; + this.lock = this; + } + + SynchronizedMap(Object lock, Map map) { + this.lock = lock; + this.map = map; + } + + public void clear() { + synchronized (lock) { map.clear(); } + } + public boolean containsKey(K key) { + synchronized (lock) { return map.containsKey(key); } + } + public boolean containsValue(V value) { + synchronized (lock) { return map.containsValue(value); } + } + public Set> entrySet() { + synchronized (lock) { return new SynchronizedSet>(lock, map.entrySet()); } + } + public V get(K key) { + synchronized (lock) { return map.get(key); } + } + public boolean isEmpty() { + synchronized (lock) { return map.isEmpty(); } + } + public Set keySet() { + synchronized (lock) { return new SynchronizedSet(lock, map.keySet()); } + } + public V put(K key, V value) { + synchronized (lock) { return map.put(key, value); } + } + public void putAll(Map elts) { + synchronized (lock) { map.putAll(elts); } + } + public V remove(K key) { + synchronized (lock) { return map.remove(key); } + } + public int size() { + synchronized (lock) { return map.size(); } + } + public Collection values() { + synchronized (lock) { return new SynchronizedCollection(lock, map.values()); } + } + } + + public static Map synchronizedMap(Map map) { + return new SynchronizedMap (map); + } + static class SynchronizedSet extends SynchronizedCollection diff --git a/classpath/java/util/logging/Logger.java b/classpath/java/util/logging/Logger.java index 5262268844..6fb968dd83 100644 --- a/classpath/java/util/logging/Logger.java +++ b/classpath/java/util/logging/Logger.java @@ -16,14 +16,23 @@ import java.util.List; public class Logger { private final String name; + private Level levelValue = null; private static final ArrayList handlers; + private static Logger rootLogger; + private Logger parent; + static { + rootLogger = new Logger(""); + rootLogger.setLevel(Level.INFO); handlers = new ArrayList(); handlers.add(new DefaultHandler()); } public static Logger getLogger(String name) { - return new Logger(name); + if (name.equals("")) return rootLogger; + Logger logger = new Logger(name); + logger.parent = rootLogger; + return logger; } private Logger(String name) { @@ -42,6 +51,10 @@ public class Logger { handlers.remove(handler); } + public Logger getParent() { + return parent; + } + public void fine(String message) { log(Level.FINE, Method.getCaller(), message, null); } @@ -66,19 +79,59 @@ public class Logger { log(level, Method.getCaller(), message, exception); } + public void logp(Level level, String sourceClass, String sourceMethod, String msg) { + if (!isLoggable(level)) { + return; + } + publish(new LogRecord(name, sourceMethod, level, msg, null)); + } + + public void logp(Level level, String sourceClass, String sourceMethod, + String msg, Throwable thrown) { + if (!isLoggable(level)) { + return; + } + publish(new LogRecord(name, sourceMethod, level, msg, thrown)); + } + + public Level getLevel() { + return levelValue; + } + + private Level getEffectiveLevel() { + Logger logger = this; + + while (logger.levelValue == null) { + logger = logger.getParent(); + } + return logger.getLevel(); + } + private void log(Level level, Method caller, String message, Throwable exception) { + + if (level.intValue() < getEffectiveLevel().intValue()) { + return; + } LogRecord r = new LogRecord(name, caller.getName(), level, message, exception); + publish(r); + } + + private void publish(LogRecord logRecord) { for (Handler h : handlers) { - h.publish(r); + h.publish(logRecord); } } public void setLevel(Level level) { - // Currently ignored + levelValue = level; } - + + public boolean isLoggable(Level level) { + return level.intValue() >= levelValue.intValue(); + } + private static class DefaultHandler extends Handler { private static final int NAME_WIDTH = 14; private static final int METHOD_WIDTH = 15; diff --git a/makefile b/makefile index a2ad32ecc6..5c5c62ef11 100644 --- a/makefile +++ b/makefile @@ -125,7 +125,7 @@ ifeq ($(platform),windows) exe-suffix = .exe lflags = -L$(lib) $(common-lflags) -lws2_32 -mwindows -mconsole - cflags = $(common-cflags) -I$(inc) + cflags = -I$(inc) $(common-cflags) ifeq (,$(filter mingw32 cygwin,$(build-platform))) cxx = i586-mingw32msvc-g++ diff --git a/src/windows.cpp b/src/windows.cpp index 59c6bbacce..08505d6f78 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -238,9 +238,11 @@ class MySystem: public System { assert(s, t); if (owner_ == t) { - bool interrupted; - bool notified; - unsigned depth; + // Initialized here to make gcc 4.2 a happy compiler + bool interrupted = false; + bool notified = false; + unsigned depth = 0; + int r UNUSED; { ACQUIRE(s, t->mutex); @@ -837,11 +839,18 @@ LONG CALLBACK handleException(LPEXCEPTION_POINTERS e) { if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { + void* ip = reinterpret_cast(e->ContextRecord->Eip); + void* base = reinterpret_cast(e->ContextRecord->Ebp); + void* stack = reinterpret_cast(e->ContextRecord->Esp); + void* thread = reinterpret_cast(e->ContextRecord->Ebx); + bool jump = system->segFaultHandler->handleSignal - (reinterpret_cast(&(e->ContextRecord->Eip)), - reinterpret_cast(&(e->ContextRecord->Ebp)), - reinterpret_cast(&(e->ContextRecord->Esp)), - reinterpret_cast(&(e->ContextRecord->Ebx))); + (&ip, &base, &stack, &thread); + + e->ContextRecord->Eip = reinterpret_cast(ip); + e->ContextRecord->Ebp = reinterpret_cast(base); + e->ContextRecord->Esp = reinterpret_cast(stack); + e->ContextRecord->Ebx = reinterpret_cast(thread); if (jump) { return EXCEPTION_CONTINUE_EXECUTION;