浏览代码

Add asprintf

Jeremy Soller 6 年之前
父节点
当前提交
ee40035c4b
共有 5 个文件被更改,包括 65 次插入0 次删除
  1. 1 0
      include/bits/stdio.h
  2. 4 0
      include/math.h
  3. 11 0
      src/c/stdio.c
  4. 8 0
      src/header/stdio/mod.rs
  5. 41 0
      src/platform/mod.rs

+ 1 - 0
include/bits/stdio.h

@@ -9,6 +9,7 @@ typedef struct FILE FILE;
 extern "C" {
 #endif
 
+int asprintf(char **strp, const char * fmt, ...);
 int fprintf(FILE * stream, const char * fmt, ...);
 int printf(const char * fmt, ...);
 int snprintf(char *s, size_t n, const char * fmt, ...);

+ 4 - 0
include/math.h

@@ -1 +1,5 @@
 #include <openlibm_math.h>
+
+// Included to fix mesa issues
+#define M_PI_2 (M_PI/2.0)
+#define M_PI_4 (M_PI/4.0)

+ 11 - 0
src/c/stdio.c

@@ -3,6 +3,17 @@
 
 typedef struct FILE FILE;
 
+int vasprintf(char ** strp, const char * fmt, va_list ap);
+
+int asprintf(char ** strp, const char * fmt, ...) {
+    int ret;
+    va_list ap;
+    va_start(ap, fmt);
+    ret = vasprintf(strp, fmt, ap);
+    va_end(ap);
+    return ret;
+}
+
 int vfprintf(FILE * stream, const char * fmt, va_list ap);
 
 int fprintf(FILE * stream, const char * fmt, ...) {

+ 8 - 0
src/header/stdio/mod.rs

@@ -920,6 +920,14 @@ pub unsafe extern "C" fn vprintf(format: *const c_char, ap: va_list) -> c_int {
     vfprintf(&mut *stdout, format, ap)
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn vasprintf(strp: *mut *mut c_char, format: *const c_char, ap: va_list) -> c_int {
+    let mut alloc_writer = platform::AllocStringWriter(ptr::null_mut(), 0);
+    let ret = printf::printf(&mut alloc_writer, format, ap);
+    *strp = alloc_writer.0 as *mut c_char;
+    ret
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn vsnprintf(
     s: *mut c_char,

+ 41 - 0
src/platform/mod.rs

@@ -99,6 +99,47 @@ impl Read for FileReader {
     }
 }
 
+pub struct AllocStringWriter(pub *mut u8, pub usize);
+impl Write for AllocStringWriter {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        let ptr = unsafe {
+            realloc(self.0 as *mut c_void, self.1 + buf.len() + 1) as *mut u8
+        };
+        if ptr.is_null() {
+            return Err(io::Error::new(
+                io::ErrorKind::Other,
+                "AllocStringWriter::write failed to allocate"
+            ));
+        }
+        self.0 = ptr;
+
+        unsafe {
+            ptr::copy_nonoverlapping(buf.as_ptr(), self.0.add(self.1), buf.len());
+            self.1 += buf.len();
+            *self.0.add(self.1) = 0;
+        }
+
+        Ok(buf.len())
+    }
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+impl fmt::Write for AllocStringWriter {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        // can't fail
+        self.write(s.as_bytes()).unwrap();
+        Ok(())
+    }
+}
+impl WriteByte for AllocStringWriter {
+    fn write_u8(&mut self, byte: u8) -> fmt::Result {
+        // can't fail
+        self.write(&[byte]).unwrap();
+        Ok(())
+    }
+}
+
 pub struct StringWriter(pub *mut u8, pub usize);
 impl Write for StringWriter {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {