ソースを参照

WIP: proof of concept for stdout() and stderr() functions to open streams

Nicolas Schodet 7 年 前
コミット
6deed404f4
2 ファイル変更59 行追加24 行削除
  1. 44 24
      src/io.rs
  2. 15 0
      src/nr.rs

+ 44 - 24
src/io.rs

@@ -2,85 +2,105 @@
 
 use core::{fmt, slice};
 use core::fmt::Write;
-
-/// File descriptors
-const STDOUT: usize = 1;
-const STDERR: usize = 2;
+use nr;
 
 /// Host's standard error
-struct Stderr;
+pub struct Stderr {
+    fd: usize,
+}
+
+/// Construct a new handle to the host's standard error.
+pub fn stderr() -> Stderr {
+    Stderr { fd: open(":tt\0", nr::open::W_APPEND).unwrap() }
+}
 
 /// Host's standard output
-struct Stdout;
+pub struct Stdout {
+    fd: usize,
+}
+
+/// Construct a new handle to the host's standard output.
+pub fn stdout() -> Stdout {
+    Stdout { fd: open(":tt\0", nr::open::W_TRUNC).unwrap() }
+}
+
+fn open(name: &str, mode: usize) -> Result<usize, ()> {
+    let name = name.as_bytes();
+    match unsafe { syscall!(OPEN, name.as_ptr(), mode, name.len() - 1) } as isize {
+        -1 => Err(()),
+        fd => Ok(fd as usize),
+    }
+}
 
-fn write_all(fd: usize, mut buffer: &[u8]) {
+fn write_all(fd: usize, mut buffer: &[u8]) -> fmt::Result {
     while !buffer.is_empty() {
         match unsafe { syscall!(WRITE, fd, buffer.as_ptr(), buffer.len()) } {
             // Done
-            0 => return,
+            0 => return Ok(()),
             // `n` bytes were not written
-            n => {
+            n if n <= buffer.len() => {
                 let offset = (buffer.len() - n) as isize;
                 buffer = unsafe {
-                    slice::from_raw_parts(buffer.as_ptr().offset(offset as isize), n)
+                    slice::from_raw_parts(buffer.as_ptr().offset(offset), n)
                 }
             }
+            // Error
+            _ => return Err(fmt::Error::default()),
         }
     }
+    Ok(())
 }
 
 impl Stderr {
-    fn write_all(&mut self, buffer: &[u8]) {
-        write_all(STDERR, buffer);
+    fn write_all(&mut self, buffer: &[u8]) -> fmt::Result {
+        write_all(self.fd, buffer)
     }
 }
 
 impl Stdout {
-    fn write_all(&mut self, buffer: &[u8]) {
-        write_all(STDOUT, buffer);
+    fn write_all(&mut self, buffer: &[u8]) -> fmt::Result {
+        write_all(self.fd, buffer)
     }
 }
 
 impl Write for Stderr {
     fn write_str(&mut self, s: &str) -> fmt::Result {
-        self.write_all(s.as_bytes());
-        Ok(())
+        self.write_all(s.as_bytes())
     }
 }
 
 impl Write for Stdout {
     fn write_str(&mut self, s: &str) -> fmt::Result {
-        self.write_all(s.as_bytes());
-        Ok(())
+        self.write_all(s.as_bytes())
     }
 }
 
 /// Write a `buffer` to the host's stderr
 pub fn ewrite(buffer: &[u8]) {
-    Stderr.write_all(buffer)
+    stderr().write_all(buffer).ok();
 }
 
 /// Write `fmt::Arguments` to the host's stderr
 pub fn ewrite_fmt(args: fmt::Arguments) {
-    Stderr.write_fmt(args).ok();
+    stderr().write_fmt(args).ok();
 }
 
 /// Write a `string` to the host's stderr
 pub fn ewrite_str(string: &str) {
-    Stderr.write_all(string.as_bytes())
+    stderr().write_all(string.as_bytes()).ok();
 }
 
 /// Write a `buffer` to the host's stdout
 pub fn write(buffer: &[u8]) {
-    Stdout.write_all(buffer)
+    stdout().write_all(buffer).ok();
 }
 
 /// Write `fmt::Arguments` to the host's stdout
 pub fn write_fmt(args: fmt::Arguments) {
-    Stdout.write_fmt(args).ok();
+    stdout().write_fmt(args).ok();
 }
 
 /// Write a `string` to the host's stdout
 pub fn write_str(string: &str) {
-    Stdout.write_all(string.as_bytes())
+    stdout().write_all(string.as_bytes()).ok();
 }

+ 15 - 0
src/nr.rs

@@ -24,3 +24,18 @@ pub const WRITE: usize = 0x05;
 pub const WRITEC: usize = 0x03;
 pub const ENTER_SVC: usize = 0x17;
 pub const REPORT_EXCEPTION: usize = 0x18;
+
+pub mod open {
+    pub const R: usize = 0;
+    pub const R_TEXT: usize = 1;
+    pub const RW: usize = 2;
+    pub const RW_TEXT: usize = 3;
+    pub const W_TRUNC: usize = 4;
+    pub const W_TRUNC_TEXT: usize = 5;
+    pub const RW_TRUNC: usize = 6;
+    pub const RW_TRUNC_TEXT: usize = 7;
+    pub const W_APPEND: usize = 8;
+    pub const W_APPEND_TEXT: usize = 9;
+    pub const RW_APPEND: usize = 10;
+    pub const RW_APPEND_TEXT: usize = 11;
+}