Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve readChar #191

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/rars/riscv/syscalls/SyscallReadChar.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ a copy of this software and associated documentation files (the

public class SyscallReadChar extends AbstractSyscall {
public SyscallReadChar() {
super("ReadChar", "Reads a character from input console", "N/A", "a0 = the character");
super("ReadChar", "Reads a character from input console", "N/A", "a0 = the character or -1 if end of input.");
}

public void simulate(ProgramStatement statement) throws ExitingException {
Expand Down
2 changes: 1 addition & 1 deletion src/rars/riscv/syscalls/SyscallReadString.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ a copy of this software and associated documentation files (the
public class SyscallReadString extends AbstractSyscall {
public SyscallReadString() {
super("ReadString", "Reads a string from the console",
"a0 = address of input buffer<br>a1 = maximum number of characters to read", "N/A");
"a0 = address of input buffer<br>a1 = size of the buffer", "N/A");
}

public void simulate(ProgramStatement statement) throws ExitingException {
Expand Down
31 changes: 18 additions & 13 deletions src/rars/util/SystemIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -177,24 +177,29 @@ public static String readString(int serviceNumber, int maxLength) {
* Implements syscall having 12 in $v0, to read a char value.
*
* @param serviceNumber the number assigned to Read Char syscall (default 12)
* @return int value with lowest byte corresponding to user input
* @return int value with lowest byte corresponding to user input or -1 on EOF
*/
public static int readChar(int serviceNumber) {
int returnValue = 0;

String input = readStringInternal("0", "Enter a character value (syscall " + serviceNumber + ")", 1);
// The whole try-catch is not really necessary in this case since I'm
// just propagating the runtime exception (the default behavior), but
// I want to make it explicit. The client needs to catch it.
try {
returnValue = (int) (input.charAt(0)); // first character input
} catch (IndexOutOfBoundsException e) // no chars present
{
throw e; // was: returnValue = 0;
int returnValue;

// Need a popup?
if (Globals.getGui() != null && Globals.getSettings().getBooleanSetting(Settings.Bool.POPUP_SYSCALL_INPUT)) {
String input = readStringInternal("0", "Enter a character value (syscall " + serviceNumber + ")", 1);
if (input.length()>0)
returnValue = input.charAt(0); // truncate
else
returnValue = -1; // assume EOF on empty string
} else {
// Otherwise delegate to the Read syscall
byte[] input = new byte[1];
int len = readFromFile(0, input, 1);
if (len>0)
returnValue = input[0];
else
returnValue = -1;
}

return returnValue;

}


Expand Down
2 changes: 1 addition & 1 deletion test/Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public static String run(String path, Program p){
for(int i = 0; i < linenumbers.length; i++){
errorlines[i] = Integer.parseInt(linenumbers[i].trim());
}
} else if (line.startsWith("stdin:")) {
} else if (line.startsWith("#stdin:")) {
stdin = line.replaceFirst("#stdin:", "").replaceAll("\\\\n","\n");
} else if (line.startsWith("#stdout:")) {
stdout = line.replaceFirst("#stdout:", "").replaceAll("\\\\n","\n");
Expand Down
73 changes: 73 additions & 0 deletions test/read.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#stdin:hello\nworldXremain
#stdout:11hello\nworld....\n1Xello\nworld....\n0Xello\nworld....\n6remainworld....\n0remainworld....\n

.eqv PrintInt, 1
.eqv Read, 63
.eqv PrintString, 4

# Expect to read one and half line "hello\nworld"
li a0, 0
la a1, buf
li a2, 11
li a7, Read
ecall
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

# Expect to read only a character
li a0, 0
la a1, buf
li a2, 1
li a7, Read
ecall
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

# Expect to read nothing
li a0, 0
la a1, buf
li a2, 0 # nothing
li a7, Read
ecall
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

# Expect to read what remains
li a0, 0
la a1, buf
li a2, 12
li a7, Read
ecall
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

# Expect to read nothing, it's EOF
li a0, 0
la a1, buf
li a2, 12
li a7, Read
ecall
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

li a0, 42
li a7, 93 # Exit2
ecall

.data
buf: .string "...............\n"
24 changes: 24 additions & 0 deletions test/readchar.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#stdin:a b\n\n!
#stdout:97a32 98b10\n10\n33!-1ÿ-1ÿ

.eqv PrintInt, 1
.eqv ReadChar, 12
.eqv PrintChar, 11

li s0, 8
loop:
beqz s0, end
addi s0, s0, -1
li a7, ReadChar
ecall
li a7, PrintInt
ecall
# Note: lowest byte of -1 is ff, and U+FF is ÿ
li a7, PrintChar
ecall
j loop

end:
li a0, 42
li a7, 93 # Exit2
ecall
100 changes: 100 additions & 0 deletions test/readstring.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#stdin:hello\n\nworldNOTWORLD\nXXXX\nYYYY\nremain
#stdout:0hello\n1\n2world34A5remain\n6\n

.eqv PrintInt, 1
.eqv ReadString, 8
.eqv PrintString, 4

# Expect to read one line "hello\n"
la a0, buf
li a1, 256
li a7, ReadString
ecall
li a0, 0
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

# Expect to read an empty line
la a0, buf
li a1, 256
li a7, ReadString
ecall
li a0, 1
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

# Expect to read "world" only
la a0, buf
li a1, 6 # include space for '\0'
li a7, ReadString
ecall
li a0, 2
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

# Expect to read nothing
la a0, buf
li a1, 1 # only space for a nullbyte
li a7, ReadString
ecall
li a0, 3
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

# Expect to read nothing
la a0, buf
li a1, 'A'
sb a1, 0(a0)
sb zero, 1(a0) # Initialize buffer with "A\0"
li a1, 0 # no space for a nullbyte
li a7, ReadString
ecall
li a0, 4
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

# Expect to read the last line, a "\n" is added
la a0, buf
li a1, 256
li a7, ReadString
ecall
li a0, 5
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

# Expect to read only an added "\n". ReadString has no concept of EOF
la a0, buf
li a1, 256
li a7, ReadString
ecall
li a0, 6
li a7, PrintInt
ecall
la a0, buf
li a7, PrintString
ecall

li a0, 42
li a7, 93 # Exit2
ecall

.data
buf: .space 256