Compare commits

...

3 Commits

31 changed files with 860 additions and 59 deletions

View File

@ -409,7 +409,7 @@ void vm_exception(struct vm * vm, struct objectref * objectref)
printc(')');
prints("\n ");
struct arrayref * arrayref = string_objectref->aref[0];
print__string(arrayref->u8, arrayref->length);
print_chars(arrayref->u16, arrayref->length);
printc('\n');
}
}

View File

@ -88,9 +88,21 @@ const static struct native_method native_method[] = {
},
{
.class_name = "java/io/PrintStream",
.method_name = "write",
.method_name = "_write",
.method_descriptor = "([B)V",
.func = native_java_io_printstream_write_1,
.func = native_java_io_printstream_write_ba_1,
},
{
.class_name = "java/io/PrintStream",
.method_name = "_write",
.method_descriptor = "([C)V",
.func = native_java_io_printstream_write_ca_1,
},
{
.class_name = "java/io/PrintStream",
.method_name = "_write",
.method_descriptor = "(Ljava/lang/String;)V",
.func = native_java_io_printstream_write_s_1,
},
{
.class_name = "jvm/internal/Loader",

View File

@ -2,8 +2,21 @@
#include "printstream.h"
#include "printf.h"
void native_java_io_printstream_write_1(struct vm * vm, uint32_t * args)
void native_java_io_printstream_write_ba_1(struct vm * vm, uint32_t * args)
{
struct arrayref * arrayref = (struct arrayref *)args[0];
print_string((const char *)arrayref->u8, arrayref->length);
print_bytes(arrayref->u8, arrayref->length);
}
void native_java_io_printstream_write_ca_1(struct vm * vm, uint32_t * args)
{
struct arrayref * arrayref = (struct arrayref *)args[0];
print_chars(arrayref->u16, arrayref->length);
}
void native_java_io_printstream_write_s_1(struct vm * vm, uint32_t * args)
{
struct objectref * objectref = (struct objectref *)args[0];
struct arrayref * arrayref = objectref->aref[0];
print_chars(arrayref->u16, arrayref->length);
}

View File

@ -4,4 +4,6 @@
#include "frame.h"
void native_java_io_printstream_write_1(struct vm * vm, uint32_t * args);
void native_java_io_printstream_write_ba_1(struct vm * vm, uint32_t * args);
void native_java_io_printstream_write_ca_1(struct vm * vm, uint32_t * args);
void native_java_io_printstream_write_s_1(struct vm * vm, uint32_t * args);

View File

@ -78,6 +78,20 @@ void print_string(const char * s, int length)
}
}
void print_bytes(const uint8_t * s, int length)
{
for (int i = 0; i < length; i++) {
print_char(s[i]);
}
}
void print_chars(const uint16_t * s, int length)
{
for (int i = 0; i < length; i++) {
print_char(s[i]);
}
}
void print_cstring(const char * s)
{
while (*s != 0) {

View File

@ -6,6 +6,8 @@
#include <stdio.h>
#endif
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -20,6 +22,8 @@ static inline void print_char(char c)
}
void print_string(const char * s, int length);
void print_bytes(const uint8_t * s, int length);
void print_chars(const uint16_t * s, int length);
void print_cstring(const char * s);
void _printf(const char * format, ...);

View File

@ -25,12 +25,12 @@ struct objectref * vm_instance_create(struct vm * vm, const char * class_name)
struct objectref * vm_instance_string_from_constant(struct vm * vm, struct constant * constant)
{
int32_t count = constant->utf8.length;
struct arrayref * arrayref = prim_array_allocate(vm, 1, count);
struct arrayref * arrayref = prim_array_allocate(vm, 2, count);
assert(arrayref != nullptr);
arrayref->class_entry = nullptr; // byte[]
arrayref->length = constant->utf8.length;
for (int i = 0; i < constant->utf8.length; i++) {
arrayref->u8[i] = constant->utf8.bytes[i];
arrayref->u16[i] = constant->utf8.bytes[i];
}
struct objectref * objectref = vm_instance_create(vm, "java/lang/String");

View File

@ -10,94 +10,94 @@ public class PrintStream
private static final byte[] newline = {'\n'};
public static native void write(byte[] buf);
private static native void _write(byte[] buf);
public static void write(String s) {
write(s.getBytes());
}
private static native void _write(char[] buf);
private static native void _write(String s);
public void print(byte[] buf) {
write(buf);
_write(buf);
}
public void print(boolean b) {
write(String.valueOf(b));
_write(String.valueOf(b));
}
public void print(char c) {
write(String.valueOf(c));
_write(String.valueOf(c));
}
public void print(int i) {
write(String.valueOf(i));
_write(String.valueOf(i));
}
public void print(long l) {
write(String.valueOf(l));
_write(String.valueOf(l));
}
public void print(float f) {
write(String.valueOf(f));
_write(String.valueOf(f));
}
public void print(double d) {
write(String.valueOf(d));
_write(String.valueOf(d));
}
public void print(Object obj) {
write(String.valueOf(obj));
_write(String.valueOf(obj));
}
public void print(String s) {
write(String.valueOf(s));
_write(String.valueOf(s));
}
public void println() {
write(newline);
_write(newline);
}
public void println(byte[] buf) {
write(buf);
write(newline);
_write(buf);
_write(newline);
}
public void println(boolean b) {
write(String.valueOf(b));
write(newline);
_write(String.valueOf(b));
_write(newline);
}
public void println(char c) {
write(String.valueOf(c));
write(newline);
_write(String.valueOf(c));
_write(newline);
}
public void println(int i) {
write(String.valueOf(i));
write(newline);
_write(String.valueOf(i));
_write(newline);
}
public void println(long l) {
write(String.valueOf(l));
write(newline);
_write(String.valueOf(l));
_write(newline);
}
public void println(float f) {
write(String.valueOf(f));
write(newline);
_write(String.valueOf(f));
_write(newline);
}
public void println(double d) {
write(String.valueOf(d));
write(newline);
_write(String.valueOf(d));
_write(newline);
}
public void println(Object obj) {
write(String.valueOf(obj));
write(newline);
_write(String.valueOf(obj));
_write(newline);
}
public void println(String s) {
write(String.valueOf(s));
write(newline);
_write(String.valueOf(s));
_write(newline);
}
}

View File

@ -1,4 +1,12 @@
package java.lang;
public class ArithmeticException extends RuntimeException {
public ArithmeticException() {
super();
}
public ArithmeticException(String s) {
super(s);
}
}

View File

@ -1,4 +1,16 @@
package java.lang;
public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
ArrayIndexOutOfBoundsException() {
super();
}
ArrayIndexOutOfBoundsException(int index) {
super(String.valueOf(index));
}
ArrayIndexOutOfBoundsException(String s) {
super(s);
}
}

View File

@ -1,4 +1,11 @@
package java.lang;
public class ArrayStoreException extends RuntimeException {
public ArrayStoreException() {
super();
}
public ArrayStoreException(String s) {
super(s);
}
}

View File

@ -1,4 +1,144 @@
package java.lang;
class Character {
class Character
implements Comparable<Character> {
public static final int MAX_RADIX = 36;
public static final int MAX_VALUE = '\uFFFF';
public static final int MIN_RADIX = 2;
public static final char MIN_VALUE = '\u0000';
public static final int SIZE = 16;
private final char value;
public Character(char value) {
this.value = value;
}
public char charValue() {
return value;
}
public int compareTo(Character anotherCharacter) {
return this.charValue() - anotherCharacter.charValue();
}
private static int _digit(char ch) {
if (Character.isDigit(ch))
return (char)((int)ch - (int)'0');
if (ch >= 'A' && ch <= 'Z')
return (char)((int)ch - (int)'A' + 10);
if (ch >= 'a' && ch <= 'z')
return (char)((int)ch - (int)'a' + 10);
return -1;
}
public static int digit(char ch, int radix) {
if (radix < MIN_RADIX || radix > MAX_RADIX)
return -1;
int value = _digit(ch);
return (value < radix) ? value : -1;
}
public boolean equals(Object obj) {
return obj instanceof Character && value == ((Character)obj).value;
}
public static char forDigit(int digit, int radix) {
if (digit < 0 || digit > MAX_RADIX)
return '\u0000';
if (digit < 10) {
return (char)((int)'0' + digit);
} else {
return (char)((int)'a' + digit - 10);
}
}
public int hashCode() {
return value;
}
public static boolean isDigit(char ch) {
return ch >= '0' && ch <= '9';
}
public static boolean isISOControl(char ch) {
return (ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F');
}
public static boolean isLowerCase(char ch) {
return
(ch >= 'a' && ch <= 'z') ||
(ch >= '\u00DF' && ch <= '\u00F6') ||
(ch >= '\u00F8' && ch <= '\u00FF');
}
public static boolean isSpaceChar(char ch) {
switch (ch) {
case ' ': return true;
case '\t': return true;
case '\n': return true;
case '\r': return true;
case '\f': return true;
default: return false;
}
}
public static boolean isUpperCase(char ch) {
return
(ch >= 'A' && ch <= 'Z') ||
(ch >= '\u00C0' && ch <= '\u00D6') ||
(ch >= '\u00D8' && ch <= '\u00DE');
}
public static boolean isWhitespace(char ch) {
switch (ch) {
case ' ': return true;
case '\t': return true;
case '\n': return true;
case '\u000B': return true;
case '\u000C': return true;
case '\r': return true;
case '\u001C': return true;
case '\u001D': return true;
case '\u001E': return true;
case '\u001F': return true;
default: return false;
}
}
public static char toLowerCase(char ch) {
if (ch >= 'A' && ch <= 'Z')
return (char)((int)ch - (int)'A' + (int)'a');
if (ch >= '\u00C0' && ch <= '\u00D6')
return (char)((int)ch - (int)'\u00C0' + (int)'\u00E0');
if (ch >= '\u00D8' && ch <= '\u00DE')
return (char)((int)ch - (int)'\u00D8' + (int)'\u00F8');
return ch;
}
public String toString() {
return Character.toString(value);
}
public static String toString(char c) {
return new String(new char[] { c });
}
public static char toUpperCase(char ch) {
if (ch >= 'a' && ch <= 'z')
return (char)((int)ch - (int)'a' + (int)'A');
if (ch >= '\u00E0' && ch <= '\u00F6')
return (char)((int)ch - (int)'\u00E0' + (int)'\u00C0');
if (ch >= '\u00F8' && ch <= '\u00FE')
return (char)((int)ch - (int)'\u00F8' + (int)'\u00D8');
return ch;
}
public static Character valueOf(char c) {
return new Character(c);
}
}

View File

@ -1,4 +1,12 @@
package java.lang;
public class ClassCastException extends RuntimeException {
public ClassCastException() {
super();
}
public ClassCastException(String s) {
super(s);
}
}

View File

@ -0,0 +1,17 @@
package java.lang;
public class ClassNotFoundException extends RuntimeException {
public ClassNotFoundException() {
super();
}
public ClassNotFoundException(String s) {
super(s);
}
public ClassNotFoundException(String s,
Throwable ex) {
super(s, ex);
}
}

View File

@ -0,0 +1,12 @@
package java.lang;
public class CloneNotSupportedException extends RuntimeException {
public CloneNotSupportedException() {
super();
}
public CloneNotSupportedException(String s) {
super(s);
}
}

View File

@ -0,0 +1,12 @@
package java.lang;
public class IllegalAccessException extends Exception {
public IllegalAccessException() {
super();
}
public IllegalAccessException(String s) {
super(s);
}
}

View File

@ -0,0 +1,21 @@
package java.lang;
public class IllegalArgumentException extends RuntimeException {
public IllegalArgumentException() {
super();
}
public IllegalArgumentException(String s) {
super(s);
}
public IllegalArgumentException(String message,
Throwable cause) {
super(message, cause);
}
public IllegalArgumentException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,12 @@
package java.lang;
public class IllegalMonitorStateException extends RuntimeException {
public IllegalMonitorStateException() {
super();
}
public IllegalMonitorStateException(String s) {
super(s);
}
}

View File

@ -0,0 +1,21 @@
package java.lang;
public class IllegalStateException extends RuntimeException {
public IllegalStateException() {
super();
}
public IllegalStateException(String s) {
super(s);
}
public IllegalStateException(String message,
Throwable cause) {
super(message, cause);
}
public IllegalStateException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,12 @@
package java.lang;
public class IllegalThreadStateException extends RuntimeException {
public IllegalThreadStateException() {
super();
}
public IllegalThreadStateException(String s) {
super(s);
}
}

View File

@ -1,4 +1,12 @@
package java.lang;
public class IndexOutOfBoundsException extends RuntimeException {
public IndexOutOfBoundsException() {
super();
}
public IndexOutOfBoundsException(String s) {
super(s);
}
}

View File

@ -0,0 +1,12 @@
package java.lang;
public class InstantiationException extends Exception {
public InstantiationException() {
super();
}
public InstantiationException(String s) {
super(s);
}
}

View File

@ -0,0 +1,12 @@
package java.lang;
public class InterruptedException extends Exception {
public InterruptedException() {
super();
}
public InterruptedException(String s) {
super(s);
}
}

View File

@ -1,4 +1,12 @@
package java.lang;
public class NegativeArraySizeException extends RuntimeException {
public NegativeArraySizeException() {
super();
}
public NegativeArraySizeException(String s) {
super(s);
}
}

View File

@ -1,4 +1,12 @@
package java.lang;
public class NullPointerException extends RuntimeException {
public NullPointerException() {
super();
}
public NullPointerException(String s) {
super(s);
}
}

View File

@ -0,0 +1,12 @@
package java.lang;
public class NumberFormatException extends IllegalArgumentException {
public NumberFormatException() {
super();
}
public NumberFormatException(String s) {
super(s);
}
}

View File

@ -1,4 +1,20 @@
package java.lang;
public class RuntimeException extends Exception {
public RuntimeException() {
super();
}
public RuntimeException(String message) {
super(message);
}
public RuntimeException(String message,
Throwable cause) {
super(message, cause);
}
public RuntimeException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,21 @@
package java.lang;
public class SecurityException extends RuntimeException {
public SecurityException() {
super();
}
public SecurityException(String s) {
super(s);
}
public SecurityException(String message,
Throwable cause) {
super(message, cause);
}
public SecurityException(Throwable cause) {
super(cause);
}
}

View File

@ -1,30 +1,377 @@
package java.lang;
public class String {
private final byte[] value;
public final class String
implements Comparable<String>, CharSequence {
private final char[] value;
public String() {
this.value = new byte[0];
value = new char[0];
}
public String(byte[] bytes) {
this(bytes, 0, bytes.length);
}
public String(byte[] bytes, int offset, int length) {
value = new char[length];
int i = 0;
while (length > 0) {
value[i] = (char)bytes[offset];
i += 1;
offset += 1;
length -= 1;
}
}
public String(char[] value) {
this(value, 0, value.length);
}
public String(char[] value, int offset, int count) {
this.value = new char[count];
int i = 0;
while (count > 0) {
this.value[i] = value[offset];
i += 1;
offset += 1;
count -= 1;
}
}
public String(String original) {
this.value = original.value;
// shallow copy
value = original.value;
}
public String(byte[] value) {
this.value = value;
public char charAt(int index) {
return value[index];
}
public int compareTo(String anotherString) {
int length = value.length < anotherString.value.length
? value.length
: anotherString.value.length;
for (int k = 0; k < length; k++) {
int difference = value[k] - anotherString.value[k];
if (difference != 0)
return difference;
}
return value.length - anotherString.value.length;
}
public int compareToIgnoreCase(String str) {
int length = value.length < str.value.length
? value.length
: str.value.length;
for (int k = 0; k < length; k++) {
char a = Character.toLowerCase(Character.toUpperCase(value[k]));
char b = Character.toLowerCase(Character.toUpperCase(str.value[k]));
int difference = a - b;
if (difference != 0)
return difference;
}
return value.length - str.value.length;
}
public String concat(String str) {
if (str.value.length == 0)
return this;
if (value.length == 0)
return str;
int length_a = value.length;
int length_b = str.value.length;
char[] newValue = new char[length_a + length_b];
for (int i = 0; i < length_a; i++) {
newValue[i] = value[i];
}
for (int i = 0; i < length_b; i++) {
newValue[length_a + i] = str.value[i];
}
return new String(newValue);
}
public boolean contains(CharSequence s) {
return indexOf(s.toString()) != -1;
}
public boolean contentEquals(CharSequence cs) {
return equals(cs.toString());
}
public static String copyValueOf(char[] data) {
return new String(data);
}
public static String copyValueOf(char[] data,
int offset,
int count) {
return new String(data, offset, count);
}
public boolean endsWith(String suffix) {
int fromIndex = value.length - suffix.value.length;
return regionMatches(false, fromIndex, suffix, 0, suffix.value.length);
}
public boolean equals(Object anObject) {
if (anObject == null)
return false;
if (!(anObject instanceof String))
return false;
String str = (String)anObject;
if (value == str.value)
return true;
if (value.length != str.value.length)
return false;
for (int i = 0; i < value.length; i++) {
if (value[i] != str.value[i])
return false;
}
return true;
}
public boolean equalsIgnoreCase(String anotherString) {
if (anotherString == null)
return false;
if (value == anotherString.value)
return true;
if (value.length != anotherString.value.length)
return false;
for (int i = 0; i < value.length; i++) {
char a = Character.toLowerCase(Character.toUpperCase(value[i]));
char b = Character.toLowerCase(Character.toUpperCase(anotherString.value[i]));
if (a != b)
return false;
}
return true;
}
public byte[] getBytes() {
return this.value;
byte[] bytes = new byte[value.length];
for (int i = 0; i < value.length; i++) {
bytes[i] = (byte)value[i];
}
return bytes;
}
public void getChars(int srcBegin,
int srcEnd,
char[] dst,
int dstBegin) {
if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > value.length ||
dstBegin < 0 || (dstBegin + (srcEnd - srcBegin)) > dst.length)
throw new IndexOutOfBoundsException();
for (int i = 0; i < srcEnd - srcBegin; i++) {
dst[dstBegin + i] = value[srcBegin + i];
}
}
public int hashCode() {
int code = 0;
for (int i = 0; i < value.length; i++) {
code = code * 31 + value[i];
}
return code;
}
public int indexOf(int ch) {
return indexOf(ch, 0);
}
public int indexOf(int ch, int fromIndex) {
if (ch > 0xffff)
return -1;
if (fromIndex < 0)
fromIndex = 0;
while (fromIndex < value.length) {
if (value[fromIndex] == ch)
return fromIndex;
fromIndex += 1;
}
return -1;
}
public int indexOf(String str) {
return indexOf(str, 0);
}
public int indexOf(String str, int fromIndex) {
if (fromIndex < 0)
fromIndex = 0;
int maxIndex = value.length - str.value.length;
while (fromIndex <= maxIndex) {
if (regionMatches(false, fromIndex, str, 0, str.value.length))
return fromIndex;
fromIndex += 1;
}
return -1;
}
public boolean isEmpty() {
return value.length == 0;
}
public int lastIndexOf(int ch) {
return lastIndexOf(ch, value.length - 1);
}
public int lastIndexOf(int ch, int fromIndex) {
if (ch > 0xffff)
return -1;
if (fromIndex >= value.length)
fromIndex = value.length - 1;
while (fromIndex >= 0) {
if (value[fromIndex] == ch)
return fromIndex;
fromIndex -= 1;
}
return -1;
}
public int lastIndexOf(String str) {
return indexOf(str, value.length - 1);
}
public int lastIndexOf(String str, int fromIndex) {
if (fromIndex >= value.length)
fromIndex = value.length - 1;
while (fromIndex >= 0) {
if (regionMatches(false, fromIndex, str, 0, str.value.length))
return fromIndex;
fromIndex -= 1;
}
return -1;
}
public int length() {
return value.length;
}
public boolean regionMatches(boolean ignoreCase,
int toffset,
String other,
int ooffset,
int len) {
if (toffset < 0 || ooffset < 0 || toffset + len > value.length || ooffset + len > other.value.length)
return false;
while (len > 0) {
len -= 1;
char a = value[toffset];
toffset += 1;
char b = other.value[ooffset];
ooffset += 1;
if (a != b) {
if (!ignoreCase)
return false;
char a1 = Character.toLowerCase(Character.toUpperCase(a));
char b1 = Character.toLowerCase(Character.toUpperCase(b));
if (a1 != b1)
return false;
}
}
return true;
}
public boolean regionMatches(int toffset,
String other,
int ooffset,
int len) {
return regionMatches(false, toffset, other, ooffset, len);
}
public String replace(char oldChar, char newChar) {
boolean replaced = false;
char[] newValue = new char[value.length];
for (int i = 0; i < value.length; i++) {
if (value[i] == oldChar) {
replaced = true;
newValue[i] = newChar;
} else {
newValue[i] = value[i];
}
}
if (replaced)
return new String(newValue);
else
return this;
}
public boolean startsWith(String prefix) {
return regionMatches(false, 0, prefix, 0, prefix.value.length);
}
public boolean startsWith(String prefix, int toffset) {
return regionMatches(false, toffset, prefix, 0, prefix.value.length);
}
public CharSequence subSequence(int beginIndex, int endIndex) {
return substring(beginIndex, endIndex);
}
public String substring(int beginIndex) {
return substring(beginIndex, value.length);
}
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex)
throw new IndexOutOfBoundsException();
int length = endIndex - beginIndex;
return new String(value, beginIndex, length);
}
public char[] toCharArray() {
char[] array = new char[value.length];
for (int i = 0; i < value.length; i++) {
array[i] = value[i];
}
return array;
}
public String toLowerCase() {
char[] newValue = new char[value.length];
for (int i = 0; i < value.length; i++) {
newValue[i] = Character.toLowerCase(value[i]);
}
return new String(newValue);
}
public String toString() {
return this;
}
public int length() {
return value.length;
public String toUpperCase() {
char[] newValue = new char[value.length];
for (int i = 0; i < value.length; i++) {
newValue[i] = Character.toUpperCase(value[i]);
}
return new String(newValue);
}
public String trim() {
if (value.length == 0 || (value[0] > '\u0020' && value[value.length - 1] > '\u0020'))
return this;
int k = 0;
while (k < value.length - 1) {
if (value[k] > '\u0020')
break;
k += 1;
}
int m = value.length - 1;
while (m >= 0) {
if (value[m] > '\u0020')
break;
m -= 1;
}
return substring(k, m + 1);
}
public static String valueOf(boolean b) {
@ -32,7 +379,25 @@ public class String {
}
public static String valueOf(char c) {
return new String(new byte[] { (byte)c });
return new String(new char[] { c });
}
public static String valueOf(char[] data) {
return new String(data, 0, data.length);
}
public static String valueOf(char[] data,
int offset,
int count) {
return new String(data, offset, count);
}
public static String valueOf(double d) {
return Double.toString(d);
}
public static String valueOf(float f) {
return Float.toString(f);
}
public static String valueOf(int i) {
@ -43,14 +408,6 @@ public class String {
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 static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}

View File

@ -0,0 +1,16 @@
package java.lang;
public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException {
public StringIndexOutOfBoundsException() {
super();
}
public StringIndexOutOfBoundsException(int index) {
super(index);
}
public StringIndexOutOfBoundsException(String s) {
super(s);
}
}

View File

@ -0,0 +1,4 @@
package java.lang;
public class UnsupportedOperationException extends RuntimeException {
}