File I/O (interrupt based) Implement a collection of functions to support file Input/Output. Interrupt based means that I/O functions will be invoked through a syscall interrupt. The I/O functions will reside in kernel memory. As described in http://courses.missouristate.edu/KenVollmar/Mars/Help/SyscallHelp.html the MARS simulator already implements a collection of system calls. These are hard-coded into the simulator and can not be re-defined with one's own handlers. It is however possible to write one's own syscall routines, with code in $v0 > 59. These handlers will implement a much reduced functionality of syscall codes 14 and 15. We will assume that the content written to the files will only be 7-bit ASCII characters. Note that files will be created and managed in memory. Hence, you need to reserve space for these files in memory. Functions to be implemented: open(filename: String) -> Handle Opens a file with name filename for reading and writing. String is a 0x00 terminated ASCII string. If a file with this name already exists, it will be opened. Otherwise, an empty new file will be created. Handle may be an address or an integer or ... as long as it's unique. A table of unique handles will be kept, one for each open file. If the file open()ed already exists, the handle of the existing file will be returned. To indicate that open() failed (due to insufficient memory), a special Handle value should be reserved (such as 0x00000000 if addresses are used or -1 if integers are used). For each open file, a filepointer must be kept. Note that this filepointer is not explicitly accessible. This means the user can not explicitly manipulate the filepointer which is safer than giving access to pointers directly. The filepointer always points to the next-to-be written or read character in the file. You should decide on how to represent the filepointer and how to associate it with the corresponding handle. After handle=open(filename), the filepointer for this file/handle will point to the first byte in the file. You should figure out what to do when when the opened file is empty and/or newly created. close(handle: Handle) -> Status Status = {0, 1}. 0 indicates success, 1 indicates failure (as when handle does not refer to a valid open file). eof(handle: Handle) -> Result Result = {0, 1}. 0 indicates the filepointer into the open file referred to through handle, is not yet at the end of the file. 1 indicates it is at the end of the file and hence further reading from the file is not possible/allowed. You should decide how to encode the end of a file. Note that using 0x00 will not work as that indicates the end of a zero-terminated string. Hint: you may remember that actual file content consists of only 7-bit ASCII characters. next(handle: Handle) -> Status Increment the filepointer to point to the next character in the file. Status = {0, 1, 2} 0 indicates success. 1 indicates failure due to attempting to point beyond the end-of-file marker. The filepointer will not be incremented and hence this is a way of testing for eof. 2 indicates failure due to not enough memory to increment the filepointer (and hence write the end-of-file marker). read(handle: Handle) -> Byte Read a character from the current position of the filepointer. A returned byte 0xFF indicates that the end of the file is reached. Note that read does not increase the filepointer and hence subsequent reads will keep returning the same character. write(handle: Handle, char:Byte) -> Status Write char to the current position of the filepointer. Status = {0, 1} 0 indicates success. 1 indicates failure due to char not a 7-bit ASCII character (i.e., the most the significant bit is 1). Note that write does not increase the filepointer and hence subsequent writes will keep overwriting the same position in the file. Command Shell A small interactive "shell" (like csh or bash) which keeps prompting (using a "prompt" string such as $) the user for commands. The shell is started automatically (is "main") when your program starts and stays in an infinite loop until the command "exit" is given. The shell "parses" (tries to understand) a typed-in line (terminated by pressing the newline/enter key). If the shell cannot understand the line, it prints an informative error message and loops back (printing the prompt string and waiting for new input). If the shell understands the entered line, it calls the appropriate function. The functions (to be written by you) implement the commands using the primitive I/O functions and data structures described above. Commands to implement: exit Terminates the program ls Prints a list of all the files on your (in-memory) "filesystem". rm filename Removes the file with name filename. If no file with such name exists in your filesystem, a warning message is printed. cat filename Prints the content of the file with name filename. If no file with such name exists in your filesystem, a warning message is printed. cat "text" >> filename Appends the text between "" (without the ""s) to the file with name filename. If no file with such name exists in your filesystem, it is created.