From fa94f1b6d5e61d4fdd2abfae98c46a911005b666 Mon Sep 17 00:00:00 2001
From: Dan Robertson <dan@dlrobertson.com>
Date: Tue, 4 Dec 2018 01:59:41 +0000
Subject: [PATCH] Use core::ffi::VaList

---
 Cargo.lock                 |  15 ---
 Cargo.toml                 |   1 -
 ci.sh                      |   2 +-
 src/header/stdio/mod.rs    |   2 +-
 src/header/stdio/printf.rs | 240 ++++++++++++++++++++-----------------
 src/header/stdio/scanf.rs  |  18 +--
 src/header/wchar/mod.rs    |   2 +-
 src/lib.rs                 |   2 +-
 8 files changed, 140 insertions(+), 142 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 5fb7b4f9..f18e5483 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -278,7 +278,6 @@ dependencies = [
  "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "va_list 0.1.0",
 ]
 
 [[package]]
@@ -500,20 +499,6 @@ name = "unicode-xid"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "va_list"
-version = "0.1.0"
-dependencies = [
- "va_list-helper 0.0.2",
-]
-
-[[package]]
-name = "va_list-helper"
-version = "0.0.2"
-dependencies = [
- "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "vec_map"
 version = "0.8.1"
diff --git a/Cargo.toml b/Cargo.toml
index 69b2fc81..e849c6a5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,7 +21,6 @@ lazy_static = { version = "1.2.0", features = ["nightly", "spin_no_std"] }
 memoffset = "0.3.0"
 posix-regex = { path = "posix-regex", features = ["no_std"] }
 rand = { version = "0.5.5", default-features = false }
-va_list = { path = "va_list", features = ["no_std"] }
 
 [dependencies.goblin]
 version = "0.0.21"
diff --git a/ci.sh b/ci.sh
index 5432f31b..3f29adc3 100755
--- a/ci.sh
+++ b/ci.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 set -ex
 
-./fmt.sh -- --write-mode=diff
+./fmt.sh -- --check
 if [ -z "$TARGET" ]
 then
     make all
diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs
index 1fb4c697..a3c44a6c 100644
--- a/src/header/stdio/mod.rs
+++ b/src/header/stdio/mod.rs
@@ -6,7 +6,7 @@ use alloc::vec::Vec;
 use core::fmt::Write as WriteFmt;
 use core::ops::{Deref, DerefMut};
 use core::{fmt, mem, ptr, slice, str};
-use va_list::VaList as va_list;
+use core::ffi::VaList as va_list;
 
 use c_str::CStr;
 use fs::File;
diff --git a/src/header/stdio/printf.rs b/src/header/stdio/printf.rs
index 0d4ea1b9..7786de01 100644
--- a/src/header/stdio/printf.rs
+++ b/src/header/stdio/printf.rs
@@ -3,11 +3,11 @@ use alloc::string::ToString;
 use alloc::vec::Vec;
 use core::ops::Range;
 use core::{fmt, slice};
-
+use core::ffi::VaList as va_list;
 use io::{self, Write};
+
 use platform;
 use platform::types::*;
-use va_list::{VaList, VaPrimitive};
 
 #[derive(PartialEq, Eq)]
 enum IntKind {
@@ -21,104 +21,108 @@ enum IntKind {
     Size,
 }
 
-trait IntoUsize {
-    fn into_usize(self) -> usize;
-    fn from_usize(i: usize) -> Self;
-}
-macro_rules! impl_intousize {
-    ($($kind:tt;)*) => {
-        $(impl IntoUsize for $kind {
-            fn into_usize(self) -> usize {
-                self as usize
-            }
-            fn from_usize(i: usize) -> Self {
-                i as Self
-            }
-        })*
-    }
-}
-impl_intousize! {
-    i32;
-    u32;
-    i64;
-    u64;
-    isize;
-    usize;
-}
-impl<T> IntoUsize for *const T {
-    fn into_usize(self) -> usize {
-        self as usize
-    }
-    fn from_usize(i: usize) -> Self {
-        i as Self
-    }
-}
-impl<T> IntoUsize for *mut T {
-    fn into_usize(self) -> usize {
-        self as usize
-    }
-    fn from_usize(i: usize) -> Self {
-        i as Self
-    }
-}
-impl IntoUsize for f32 {
-    fn into_usize(self) -> usize {
-        self.to_bits() as usize
-    }
-    fn from_usize(i: usize) -> Self {
-        Self::from_bits(i as u32)
-    }
+enum ArgType {
+    Byte,
+    Short,
+    Int,
+    Long,
+    LongLong,
+    PtrDiff,
+    Size,
+    IntMax,
+    Double,
+    CharPtr,
+    VoidPtr,
+    IntPtr,
+    ArgDefault
 }
-impl IntoUsize for f64 {
-    fn into_usize(self) -> usize {
-        self.to_bits() as usize
-    }
-    fn from_usize(i: usize) -> Self {
-        Self::from_bits(i as u64)
-    }
+
+#[derive(Clone, Copy)]
+union VaArg {
+    byte: c_char,
+    short: c_short,
+    int: c_int,
+    long: c_long,
+    longlong: c_longlong,
+    ptrdiff: ptrdiff_t,
+    size: ssize_t,
+    intmax: intmax_t,
+    double: c_double,
+    char_ptr: *const c_char,
+    void_ptr: *const c_void,
+    int_ptr: *mut c_int,
+    arg_default: usize
 }
 
-struct BufferedVaList {
-    list: VaList,
-    buf: Vec<usize>,
+struct BufferedVaList<'a> {
+    list: va_list<'a>,
+    buf: Vec<VaArg>,
     i: usize,
 }
-impl BufferedVaList {
-    fn new(list: VaList) -> Self {
+
+impl<'a> BufferedVaList<'a> {
+    fn new(list: va_list<'a>) -> Self {
         Self {
             list,
             buf: Vec::new(),
             i: 0,
         }
     }
-    unsafe fn get<T: VaPrimitive + IntoUsize>(&mut self, i: Option<usize>) -> T {
+
+    unsafe fn get_arg(&mut self, ty: ArgType) -> VaArg {
+        match ty {
+            ArgType::Byte => VaArg { byte: self.list.arg::<c_char>() },
+            ArgType::Short => VaArg { short: self.list.arg::<c_short>() },
+            ArgType::Int => VaArg { int: self.list.arg::<c_int>() },
+            ArgType::Long => VaArg { long: self.list.arg::<c_long>() },
+            ArgType::LongLong => VaArg { longlong: self.list.arg::<c_longlong>() },
+            ArgType::PtrDiff => VaArg { ptrdiff: self.list.arg::<ptrdiff_t>() },
+            ArgType::Size => VaArg { size: self.list.arg::<ssize_t>() },
+            ArgType::IntMax => VaArg { intmax: self.list.arg::<intmax_t>() },
+            ArgType::Double => VaArg { double: self.list.arg::<c_double>() },
+            ArgType::CharPtr => VaArg { char_ptr: self.list.arg::<*const c_char>() },
+            ArgType::VoidPtr => VaArg { void_ptr: self.list.arg::<*const c_void>() },
+            ArgType::IntPtr => VaArg { int_ptr: self.list.arg::<*mut c_int>() },
+            ArgType::ArgDefault => VaArg { arg_default: self.list.arg::<usize>() }
+        }
+    }
+
+    unsafe fn get(&mut self, ty: ArgType, i: Option<usize>) -> VaArg {
         match i {
-            None => self.next(),
-            Some(i) => self.index(i),
+            None => self.next(ty),
+            Some(i) => self.index(ty, i),
         }
     }
-    unsafe fn next<T: VaPrimitive + IntoUsize>(&mut self) -> T {
+
+    unsafe fn next(&mut self, ty: ArgType) -> VaArg {
         if self.i >= self.buf.len() {
-            self.buf.push(self.list.get::<T>().into_usize());
+            let arg = self.get_arg(ty);
+            self.buf.push(arg);
         }
-        let arg = T::from_usize(self.buf[self.i]);
+        let arg = self.buf[self.i];
         self.i += 1;
         arg
     }
-    unsafe fn index<T: VaPrimitive + IntoUsize>(&mut self, i: usize) -> T {
-        while self.buf.len() < i {
-            // Getting a usize here most definitely isn't sane, however,
-            // there's no way to know the type!
-            // Just take this for example:
-            //
-            // printf("%*4$d\n", "hi", 0, "hello", 10);
-            //
-            // This chooses the width 10. How does it know the type of 0 and "hello"?
-            // It clearly can't.
-
-            self.buf.push(self.list.get::<usize>());
+
+    unsafe fn index(&mut self, ty: ArgType, i: usize) -> VaArg {
+        if self.i >= self.buf.len() {
+            while self.buf.len() < (i - 1) {
+                // Getting a usize here most definitely isn't sane, however,
+                // there's no way to know the type!
+                // Just take this for example:
+                //
+                // printf("%*4$d\n", "hi", 0, "hello", 10);
+                //
+                // This chooses the width 10. How does it know the type of 0 and "hello"?
+                // It clearly can't.
+
+                let arg = self.get_arg(ArgType::ArgDefault);
+                self.buf.push(arg);
+            }
+            let arg = self.get_arg(ty);
+            self.buf.push(arg);
         }
-        T::from_usize(self.buf[i - 1])
+        self.buf[i - 1]
     }
 }
 
@@ -134,6 +138,7 @@ unsafe fn pop_int_raw(format: &mut *const u8) -> Option<usize> {
     }
     int
 }
+
 unsafe fn pop_int(format: &mut *const u8, ap: &mut BufferedVaList) -> Option<usize> {
     if **format == b'*' {
         *format = format.offset(1);
@@ -143,15 +148,16 @@ unsafe fn pop_int(format: &mut *const u8, ap: &mut BufferedVaList) -> Option<usi
         if let Some(i) = pop_int_raw(&mut format2) {
             if *format2 == b'$' {
                 *format = format2.offset(1);
-                return Some(ap.index::<usize>(i));
+                return Some(ap.index(ArgType::ArgDefault, i).arg_default);
             }
         }
 
-        Some(ap.next::<usize>())
+        Some(ap.next(ArgType::ArgDefault).arg_default)
     } else {
         pop_int_raw(format)
     }
 }
+
 unsafe fn fmt_int<I>(fmt: u8, i: I) -> String
 where
     I: fmt::Display + fmt::Octal + fmt::LowerHex + fmt::UpperHex,
@@ -164,6 +170,7 @@ where
         _ => panic!("fmt_int should never be called with the fmt {}", fmt),
     }
 }
+
 fn pad<W: Write>(
     w: &mut W,
     current_side: bool,
@@ -177,6 +184,7 @@ fn pad<W: Write>(
     }
     Ok(())
 }
+
 fn float_string(float: c_double, precision: usize, trim: bool) -> String {
     let mut string = format!("{:.p$}", float, p = precision);
     if trim {
@@ -192,6 +200,7 @@ fn float_string(float: c_double, precision: usize, trim: bool) -> String {
     }
     string
 }
+
 fn fmt_float_exp<W: Write>(
     w: &mut W,
     exp_fmt: u8,
@@ -244,6 +253,7 @@ fn fmt_float_exp<W: Write>(
 
     Ok(true)
 }
+
 fn fmt_float_normal<W: Write>(
     w: &mut W,
     trim: bool,
@@ -268,7 +278,8 @@ fn fmt_float_normal<W: Write>(
 
     Ok(string.len())
 }
-unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io::Result<c_int> {
+
+unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: va_list) -> io::Result<c_int> {
     let w = &mut platform::CountingWriter::new(w);
     let mut ap = BufferedVaList::new(ap);
     let mut format = format as *const u8;
@@ -356,17 +367,21 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
                 b'%' => w.write_all(&[b'%'])?,
                 b'd' | b'i' => {
                     let string = match kind {
-                        // VaList does not seem to support these two:
-                        //   IntKind::Byte     => ap.get::<c_char>(index).to_string(),
-                        //   IntKind::Short    => ap.get::<c_short>(index).to_string(),
-                        IntKind::Byte => (ap.get::<c_int>(index) as c_char).to_string(),
-                        IntKind::Short => (ap.get::<c_int>(index) as c_short).to_string(),
-                        IntKind::Int => ap.get::<c_int>(index).to_string(),
-                        IntKind::Long => ap.get::<c_long>(index).to_string(),
-                        IntKind::LongLong => ap.get::<c_longlong>(index).to_string(),
-                        IntKind::PtrDiff => ap.get::<ptrdiff_t>(index).to_string(),
-                        IntKind::Size => ap.get::<ssize_t>(index).to_string(),
-                        IntKind::IntMax => ap.get::<intmax_t>(index).to_string(),
+                        // Per the C standard using va_arg with a type with a size
+                        // less than that of an int for integers and double for floats
+                        // is invalid. As a result any arguments smaller than an int or
+                        // double passed to a function will be promoted to the smallest
+                        // possible size. The va_list::arg function will handle this
+                        // automagically.
+                        IntKind::Byte => ap.get(ArgType::Byte, index).byte.to_string(),
+                        IntKind::Short => ap.get(ArgType::Short, index).short.to_string(),
+                        // Types that will not be promoted
+                        IntKind::Int => ap.get(ArgType::Int, index).int.to_string(),
+                        IntKind::Long => ap.get(ArgType::Long, index).long.to_string(),
+                        IntKind::LongLong => ap.get(ArgType::LongLong, index).longlong.to_string(),
+                        IntKind::PtrDiff => ap.get(ArgType::PtrDiff, index).ptrdiff.to_string(),
+                        IntKind::Size => ap.get(ArgType::Size, index).size.to_string(),
+                        IntKind::IntMax => ap.get(ArgType::IntMax, index).intmax.to_string(),
                     };
                     let positive = !string.starts_with('-');
                     let zero = precision == Some(0) && string == "0";
@@ -405,17 +420,15 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
                 b'o' | b'u' | b'x' | b'X' => {
                     let fmt = *format;
                     let string = match kind {
-                        // VaList does not seem to support these two:
-                        //   IntKind::Byte     => fmt_int(kind ap.get::<c_char>(index)),
-                        //   IntKind::Short     => fmt_int(kind ap.get::<c_short>(index)),
-                        IntKind::Byte => fmt_int(fmt, ap.get::<c_uint>(index) as c_uchar),
-                        IntKind::Short => fmt_int(fmt, ap.get::<c_uint>(index) as c_ushort),
-                        IntKind::Int => fmt_int(fmt, ap.get::<c_uint>(index)),
-                        IntKind::Long => fmt_int(fmt, ap.get::<c_ulong>(index)),
-                        IntKind::LongLong => fmt_int(fmt, ap.get::<c_ulonglong>(index)),
-                        IntKind::PtrDiff => fmt_int(fmt, ap.get::<ptrdiff_t>(index)),
-                        IntKind::Size => fmt_int(fmt, ap.get::<size_t>(index)),
-                        IntKind::IntMax => fmt_int(fmt, ap.get::<uintmax_t>(index)),
+                        // va_list will promote the following two to a c_int
+                        IntKind::Byte => fmt_int(fmt, ap.get(ArgType::Byte, index).byte),
+                        IntKind::Short => fmt_int(fmt, ap.get(ArgType::Short, index).short),
+                        IntKind::Int => fmt_int(fmt, ap.get(ArgType::Int, index).int),
+                        IntKind::Long => fmt_int(fmt, ap.get(ArgType::Long, index).long),
+                        IntKind::LongLong => fmt_int(fmt, ap.get(ArgType::LongLong, index).longlong),
+                        IntKind::PtrDiff => fmt_int(fmt, ap.get(ArgType::PtrDiff, index).ptrdiff),
+                        IntKind::Size => fmt_int(fmt, ap.get(ArgType::Size, index).size),
+                        IntKind::IntMax => fmt_int(fmt, ap.get(ArgType::IntMax, index).intmax),
                     };
                     let zero = precision == Some(0) && string == "0";
 
@@ -460,7 +473,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
                 }
                 b'e' | b'E' => {
                     let exp_fmt = *format;
-                    let mut float = ap.get::<c_double>(index);
+                    let mut float = ap.get(ArgType::Double, index).double;
                     let precision = precision.unwrap_or(6);
 
                     fmt_float_exp(
@@ -468,14 +481,14 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
                     )?;
                 }
                 b'f' | b'F' => {
-                    let mut float = ap.get::<c_double>(index);
+                    let mut float = ap.get(ArgType::Double, index).double;
                     let precision = precision.unwrap_or(6);
 
                     fmt_float_normal(w, false, precision, float, left, pad_space, pad_zero)?;
                 }
                 b'g' | b'G' => {
                     let exp_fmt = b'E' | (*format & 32);
-                    let mut float = ap.get::<c_double>(index);
+                    let mut float = ap.get(ArgType::Double, index).double;
                     let precision = precision.unwrap_or(6);
 
                     if !fmt_float_exp(
@@ -495,7 +508,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
                 b's' => {
                     // if kind == IntKind::Long || kind == IntKind::LongLong, handle *const wchar_t
 
-                    let ptr = ap.get::<*const c_char>(index);
+                    let ptr = ap.get(ArgType::CharPtr, index).char_ptr;
 
                     if ptr.is_null() {
                         w.write_all(b"(null)")?;
@@ -515,14 +528,14 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
                 b'c' => {
                     // if kind == IntKind::Long || kind == IntKind::LongLong, handle wint_t
 
-                    let c = ap.get::<c_int>(index) as c_char;
+                    let c = ap.get(ArgType::Byte, index).byte;
 
                     pad(w, !left, b' ', 1..pad_space)?;
                     w.write_all(&[c as u8])?;
                     pad(w, left, b' ', 1..pad_space)?;
                 }
                 b'p' => {
-                    let ptr = ap.get::<*const c_void>(index);
+                    let ptr = ap.get(ArgType::VoidPtr, index).int_ptr;
 
                     let mut len = 1;
                     if ptr.is_null() {
@@ -544,7 +557,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
                     pad(w, left, b' ', len..pad_space)?;
                 }
                 b'n' => {
-                    let ptr = ap.get::<*mut c_int>(index);
+                    let ptr = ap.get(ArgType::IntPtr, index).int_ptr;
                     *ptr = w.written as c_int;
                 }
                 _ => return Ok(-1),
@@ -554,6 +567,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
     }
     Ok(w.written as c_int)
 }
-pub unsafe fn printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> c_int {
+
+pub unsafe fn printf<W: Write>(w: W, format: *const c_char, ap: va_list) -> c_int {
     inner_printf(w, format, ap).unwrap_or(-1)
 }
diff --git a/src/header/stdio/scanf.rs b/src/header/stdio/scanf.rs
index 2e858d20..fd7a655d 100644
--- a/src/header/stdio/scanf.rs
+++ b/src/header/stdio/scanf.rs
@@ -2,7 +2,7 @@ use alloc::string::String;
 use alloc::vec::Vec;
 use io::Read;
 use platform::types::*;
-use va_list::VaList;
+use core::ffi::VaList as va_list;
 
 #[derive(PartialEq, Eq)]
 enum IntKind {
@@ -30,7 +30,7 @@ unsafe fn next_byte(string: &mut *const c_char) -> Result<u8, c_int> {
 unsafe fn inner_scanf<R: Read>(
     mut r: R,
     mut format: *const c_char,
-    mut ap: VaList,
+    mut ap: va_list,
 ) -> Result<c_int, c_int> {
     let mut matched = 0;
     let mut byte = 0;
@@ -231,7 +231,7 @@ unsafe fn inner_scanf<R: Read>(
                                 n.parse::<$type>().map_err(|_| 0)?
                             };
                             if !ignore {
-                                *ap.get::<*mut $type>() = n;
+                                *ap.arg::<*mut $type>() = n;
                                 matched += 1;
                             }
                         }};
@@ -251,7 +251,7 @@ unsafe fn inner_scanf<R: Read>(
                                 $type::from_str_radix(&n, radix).map_err(|_| 0)?
                             };
                             if !ignore {
-                                *ap.get::<*mut $final>() = n as $final;
+                                *ap.arg::<*mut $final>() = n as $final;
                                 matched += 1;
                             }
                         }};
@@ -329,7 +329,7 @@ unsafe fn inner_scanf<R: Read>(
                         }
                     }
 
-                    let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.get()) };
+                    let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) };
 
                     while width.map(|w| w > 0).unwrap_or(true) && !(byte as char).is_whitespace() {
                         if let Some(ref mut ptr) = ptr {
@@ -349,7 +349,7 @@ unsafe fn inner_scanf<R: Read>(
                     }
                 }
                 b'c' => {
-                    let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.get()) };
+                    let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) };
 
                     for i in 0..width.unwrap_or(1) {
                         if let Some(ptr) = ptr {
@@ -400,7 +400,7 @@ unsafe fn inner_scanf<R: Read>(
                         }
                     }
 
-                    let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.get()) };
+                    let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) };
 
                     // While we haven't used up all the width, and it matches
                     while width.map(|w| w > 0).unwrap_or(true) && !invert == matches.contains(&byte) {
@@ -425,7 +425,7 @@ unsafe fn inner_scanf<R: Read>(
                 },
                 b'n' => {
                     if !ignore {
-                        *ap.get::<*mut c_int>() = count as c_int;
+                        *ap.arg::<*mut c_int>() = count as c_int;
                     }
                 }
                 _ => return Err(-1),
@@ -444,7 +444,7 @@ unsafe fn inner_scanf<R: Read>(
     }
     Ok(matched)
 }
-pub unsafe fn scanf<R: Read>(r: R, format: *const c_char, ap: VaList) -> c_int {
+pub unsafe fn scanf<R: Read>(r: R, format: *const c_char, ap: va_list) -> c_int {
     match inner_scanf(r, format, ap) {
         Ok(n) => n,
         Err(n) => n,
diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs
index 5d496529..18dd985d 100644
--- a/src/header/wchar/mod.rs
+++ b/src/header/wchar/mod.rs
@@ -1,7 +1,7 @@
 //! wchar implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/wchar.h.html
 
 use core::{mem, ptr, usize};
-use va_list::VaList as va_list;
+use core::ffi::VaList as va_list;
 
 use header::stdio::*;
 use header::stdlib::MB_CUR_MAX;
diff --git a/src/lib.rs b/src/lib.rs
index 05c34710..8f6ae1b3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,6 +5,7 @@
 #![feature(alloc)]
 #![feature(allocator_api)]
 #![feature(asm)]
+#![feature(c_variadic)]
 #![feature(const_fn)]
 #![feature(const_raw_ptr_deref)]
 #![feature(const_str_as_bytes)]
@@ -33,7 +34,6 @@ extern crate lazy_static;
 extern crate memoffset;
 extern crate posix_regex;
 extern crate rand;
-extern crate va_list;
 
 #[cfg(target_os = "linux")]
 #[macro_use]
-- 
GitLab