We planned to upgrade GitLab and Mattermost to the latest version this Friday morning (early). You may experience some downtime!

Commit cb2f55c9 authored by atzedijkstra's avatar atzedijkstra

Merge pull request #1 from joostrijneveld/master

Added User- and File IO, (unicode) character support
parents 093270d3 64a5c538
......@@ -196,7 +196,8 @@ halt_descr=Halt execution. Machine stops executing instructions.
halt_prepost=
halt_example=halt
trap_descr=Trap to environment function. Trap invokes a systemcall, which one is determined by its argument. Currently just 1 call exists, print the topmost element on the stack as an integer in the output window.
trap_descr=Trap to environment function. Trap invokes a systemcall determined by its argument. Currently, trap supports the following system calls: <ol> <li value="0">Pop the topmost element from the stack and print it as an integer.</li> <li value="1">Pop the topmost element from the stack and print it as a unicode character.</li> <li value="10">Ask the user for an integer input and push it on the stack.</li> <li value="11">Ask the user for a unicode character input and push it on the stack.</li> <li value="12">Ask the user for a sequence of unicode characters input and push the characters on the stack terminated by a null-character.</li> <li value="20">Pop a null-terminated file name from the stack, open the file for reading and push a file pointer on the stack.</li> <li value="21">Pop a null-terminated file name from the stack, open the file for writing and push a file pointer on the stack.</li> <li value="22">Pop a file pointer from the stack, read a character from the file pointed to by the file pointer and push the character on the stack.</li> <li value="23">Pop a character and a file pointer from the stack, write the character to the file pointed to by the file pointer.</li> <li value="24">Pop a file pointer from the stack and close the corresponding file.</li> </ol>
trap_prepost=
trap_example=ldc 5, trap 0 ; print 5 on output
......
......@@ -161,8 +161,16 @@ public class Instruction
/**
* Traps
*/
protected final static int TR_PR_INT = 0 ;
protected final static int TR_PR_INT = 00;
protected final static int TR_PR_CHAR = 01;
protected final static int TR_IN_INT = 10;
protected final static int TR_IN_CHAR = 11;
protected final static int TR_IN_CHAR_ARRAY = 12;
protected final static int TR_FILE_OPEN_READ = 20;
protected final static int TR_FILE_OPEN_WRITE = 21;
protected final static int TR_FILE_READ = 22;
protected final static int TR_FILE_WRITE = 23;
protected final static int TR_FILE_CLOSE = 24;
/**
* Metas
*/
......
......@@ -9,6 +9,8 @@
package nl.uu.cs.ssm ;
import java.awt.Color;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class Machine
{
......@@ -479,7 +481,104 @@ public class Machine
case Instruction.TR_PR_INT :
messenger.println( "" + pop() ) ;
break ;
case Instruction.TR_PR_CHAR :
try
{
messenger.print( "" + Utils.codePointToString(pop()) ) ;
}
catch (UnsupportedEncodingException e)
{
messenger.println("Error: UTF-32 encoding missing.");
}
break;
case Instruction.TR_IN_INT :
push(messenger.promptInt());
break;
case Instruction.TR_IN_CHAR :
push(messenger.promptChar());
break;
case Instruction.TR_IN_CHAR_ARRAY :
push(0);
int[] chars = messenger.promptCharArray();
for (int i = chars.length - 1; i >= 0; i--)
{
push(chars[i]);
}
break;
case Instruction.TR_FILE_OPEN_READ :
case Instruction.TR_FILE_OPEN_WRITE :
StringBuilder filename = new StringBuilder();
int n = pop();
while (n != 0)
{
filename.append((char)n);
n = pop();
}
String fname = filename.toString();
try
{
boolean readOnly = state.inlineOpnds[0] == Instruction.TR_FILE_OPEN_READ;
push(state.openFile(fname, readOnly));
}
catch (IOException e)
{
messenger.println("Error: file "+fname+" not found");
}
break;
case Instruction.TR_FILE_READ :
try
{
push(state.readFromFile(pop()));
}
catch (IOException e)
{
messenger.println("Error: cannot read from file.");
}
catch (IndexOutOfBoundsException e)
{
messenger.println("Error: invalid file pointer.");
}
catch (NullPointerException e)
{
messenger.println("Error: invalid file pointer.");
}
break;
case Instruction.TR_FILE_WRITE :
try
{
push(state.writeToFile(pop(), pop()));
}
catch (IOException e)
{
messenger.println("Error: cannot write to file.");
}
catch (IndexOutOfBoundsException e)
{
messenger.println("Error: invalid file pointer.");
}
catch (NullPointerException e)
{
messenger.println("Error: invalid file pointer.");
}
break;
case Instruction.TR_FILE_CLOSE :
try
{
state.closeFile(pop());
}
catch (IOException e)
{
messenger.println("Error: cannot close file.");
}
catch (IndexOutOfBoundsException e)
{
messenger.println("Error: invalid file pointer.");
}
catch (NullPointerException e)
{
messenger.println("Error: invalid file pointer.");
}
break;
default : break ;
}
break ;
......
......@@ -8,6 +8,11 @@
package nl.uu.cs.ssm ;
import java.io.Closeable;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
public class MachineState extends Model
......@@ -25,6 +30,7 @@ public class MachineState extends Model
protected Memory memory ;
protected Registers registers ;
protected MemoryUser memoryUser ;
protected ArrayList<Closeable> filePtrs;
public boolean isHalted ;
......@@ -34,6 +40,7 @@ public class MachineState extends Model
registers = new Registers( memory, m ) ;
stackGrowthDir = 1 ;
this.startAddressOfHeap = startAddressOfHeap;
filePtrs = new ArrayList<Closeable>();
reset() ;
}
......@@ -66,11 +73,26 @@ public class MachineState extends Model
public void resetToInitialState()
{
registers.setPC( 0 ) ;
stackBottom = memory.getUsedForCode() + 16 ;
stackBottom = memory.getUsedForCode() + 16 ;
registers.setSP( stackBottom - stackGrowthDir ) ;
registers.setMP( registers.getSP() ) ;
registers.setHP(startAddressOfHeap);
isHalted = false ;
try
{
for(Closeable f : filePtrs)
{
if (f != null)
{
f.close();
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
filePtrs = new ArrayList<Closeable>();
}
public int dir( int v )
......@@ -162,6 +184,65 @@ public class MachineState extends Model
{
return "state code=" + code + " instr-pc=" + instrPC + " n-inl=" + nInlineOpnds ;
}
/**
* Opens a file
* @param fname Name of the file
* @param readOnly True if the file should be open for reading, false otherwise
* @return The 'file pointer' of the file
* @throws IOException
*/
public int openFile(String fname, boolean readOnly) throws IOException {
if (readOnly)
{
filePtrs.add(new FileReader(fname));
}
else {
filePtrs.add(new FileWriter(fname));
}
return filePtrs.size() - 1;
}
/**
* Reads a unicode character from the file indicated by index
* @param index The 'file pointer' of the file
* @return The unicode codepoint of the read character
* @throws IOException
*/
public int readFromFile(int index) throws IOException {
FileReader file = (FileReader) filePtrs.get(index);
int i16 = file.read(); // UTF-16 as int
char c16 = (char)i16; // UTF-16
if (Character.isHighSurrogate(c16))
{
int low_i16 = file.read(); // low surrogate UTF-16 as int
char low_c16 = (char)low_i16;
return Character.toCodePoint(c16, low_c16);
}
return i16;
}
/**
* Writes a unicode character to the file indicated by the index
* @param n The unicode codepoint of the character
* @param index The 'file pointer' of the file
* @return index The 'file pointer' of the file
* @throws IOException
*/
public int writeToFile(int n, int index) throws IOException {
FileWriter file = (FileWriter) filePtrs.get(index);
file.write(Utils.codePointToString(n));
return index;
}
/**
* Closes a file
* @param index The 'file pointer' of the file
* @throws IOException
*/
public void closeFile(int index) throws IOException {
filePtrs.get(index).close();
// cannot remove from filePtrs, as that messes up index
filePtrs.set(index, null);
}
}
\ No newline at end of file
......@@ -10,6 +10,24 @@ package nl.uu.cs.ssm ;
public interface Messenger
{
public void println( String s ) ;
public void print(String s);
public void println(String s);
/**
* Asks the user for an integer value (i.e. via a dialog)
* @return Returns the integer value as provided by the user
*/
public int promptInt();
/**
* Asks the user for a character (i.e. via a dialog)
* @return Returns the unicode integer code point of the provided character
*/
public int promptChar();
/**
* Asks the user for a string (i.e. via a dialog)
* @return Returns an array of unicode integer code points
*/
public int[] promptCharArray();
}
\ No newline at end of file
......@@ -10,6 +10,8 @@ package nl.uu.cs.ssm ;
import java.awt.Rectangle;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
......@@ -281,5 +283,13 @@ public class Utils
Rectangle r = c.getBounds() ;
scrollComponentTo( c, new Rectangle( 0, r.height-2, r.width, 2 ) ) ;
}
/**
* Convert unicode code point to String
*/
public static String codePointToString(int n) throws UnsupportedEncodingException {
ByteBuffer b = ByteBuffer.allocate(4);
b.putInt(n);
return new String(b.array(), "UTF-32BE");
}
}
......@@ -12,6 +12,8 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileReader;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Vector;
......@@ -22,6 +24,7 @@ import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollBar;
import javax.swing.JTable;
import javax.swing.KeyStroke;
......@@ -322,7 +325,7 @@ public class SSMRunner extends JFrame
outputScrollPane.setBorder(createTitledBorder("Output"));
outputTextArea.setVisible(true);
outputTextArea.setEditable(false);
outputTextArea.setFont(new java.awt.Font("SansSerif", 0, 10));
outputTextArea.setFont(new java.awt.Font("SansSerif", 0, 12));
setLocation(new java.awt.Point(0, 0));
setFont(new java.awt.Font("SansSerif", 0, 12));
setJMenuBar(JMenuBar);
......@@ -647,12 +650,72 @@ public class SSMRunner extends JFrame
}
stepManager.endForwardStep() ;
}
public void println( String s )
{
outputTextArea.append( s ) ;
outputTextArea.append( "\n" ) ;
}
public void print( String s )
{
outputTextArea.append( s ) ;
}
public int promptInt()
{
while(true)
{
try
{
String s = JOptionPane.showInputDialog(this,
"Please enter an integer.","Integer requested", JOptionPane.QUESTION_MESSAGE);
if (s == null)
{
return 0;
}
return Integer.parseInt(s);
}
catch (NumberFormatException e)
{
continue; // Ask again
}
}
}
public int promptChar()
{
while(true)
{
String s = JOptionPane.showInputDialog(this,
"Please enter a character.","Character requested", JOptionPane.QUESTION_MESSAGE);
if (s == null)
{
return 0;
}
if (s.length() == 0)
{
continue;
}
return s.codePointAt(0);
}
}
public int[] promptCharArray()
{
String s = JOptionPane.showInputDialog(this,
"Please enter a string.","String requested", JOptionPane.QUESTION_MESSAGE);
if (s == null || s.length() == 0)
{
return new int[0];
}
int[] result = new int[s.length()];
for(int i = 0; i < s.length(); i++)
{
result[i] = s.codePointAt(i);
}
return result;
}
// Close the window when the close box is clicked
void thisWindowClosing(java.awt.event.WindowEvent e)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment