Browse Source

Merge pull request #2 from japaric/stderr

add a macro to write to the host stderr
Jorge Aparicio 8 years ago
parent
commit
3f17e4ed00
2 changed files with 65 additions and 14 deletions
  1. 49 14
      src/io.rs
  2. 16 0
      src/macros.rs

+ 49 - 14
src/io.rs

@@ -3,31 +3,51 @@
 use core::{fmt, slice};
 use core::fmt::Write;
 
-/// File descriptor
+/// File descriptors
 const STDOUT: usize = 1;
+const STDERR: usize = 2;
+
+/// Host's standard error
+struct Stderr;
 
 /// Host's standard output
 struct Stdout;
 
-impl Stdout {
-    fn write_all(&mut self, mut buffer: &[u8]) {
-        while !buffer.is_empty() {
-            match unsafe {
-                syscall!(WRITE, STDOUT, buffer.as_ptr(), buffer.len())
-            } {
-                // Done
-                0 => return,
-                // `n` bytes were not written
-                n => {
-                    buffer = unsafe {
-                        slice::from_raw_parts(buffer.as_ptr(), buffer.len() - n)
-                    }
+fn write_all(fd: usize, mut buffer: &[u8]) {
+    while !buffer.is_empty() {
+        match unsafe { syscall!(WRITE, fd, buffer.as_ptr(), buffer.len()) } {
+            // Done
+            0 => return,
+            // `n` bytes were not written
+            n => {
+                let offset = (buffer.len() - n) as isize;
+                buffer = unsafe {
+                    slice::from_raw_parts(buffer.as_ptr().offset(offset as isize), n)
                 }
             }
         }
     }
 }
 
+impl Stderr {
+    fn write_all(&mut self, buffer: &[u8]) {
+        write_all(STDERR, buffer);
+    }
+}
+
+impl Stdout {
+    fn write_all(&mut self, buffer: &[u8]) {
+        write_all(STDOUT, buffer);
+    }
+}
+
+impl Write for Stderr {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.write_all(s.as_bytes());
+        Ok(())
+    }
+}
+
 impl Write for Stdout {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         self.write_all(s.as_bytes());
@@ -35,6 +55,21 @@ impl Write for Stdout {
     }
 }
 
+/// Write a `buffer` to the host's stderr
+pub fn ewrite(buffer: &[u8]) {
+    Stderr.write_all(buffer)
+}
+
+/// Write `fmt::Arguments` to the host's stderr
+pub fn ewrite_fmt(args: fmt::Arguments) {
+    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())
+}
+
 /// Write a `buffer` to the host's stdout
 pub fn write(buffer: &[u8]) {
     Stdout.write_all(buffer)

+ 16 - 0
src/macros.rs

@@ -16,6 +16,22 @@ macro_rules! syscall {
                                            $a3 as usize, $a4 as usize])
     };
 }
+
+/// Macro for printing to the **host's** standard stderr
+#[macro_export]
+macro_rules! ehprint {
+    ($s:expr) => ($crate::io::ewrite_str($s));
+    ($($arg:tt)*) => ($crate::io::ewrite_fmt(format_args!($($arg)*)));
+}
+
+/// Macro for printing to the **host's** standard error, with a newline.
+#[macro_export]
+macro_rules! ehprintln {
+    () => (ehprint!("\n"));
+    ($fmt:expr) => (ehprint!(concat!($fmt, "\n")));
+    ($fmt:expr, $($arg:tt)*) => (ehprint!(concat!($fmt, "\n"), $($arg)*));
+}
+
 /// Macro for printing to the **host's** standard output
 #[macro_export]
 macro_rules! hprint {