|  | @@ -126,6 +126,67 @@ impl VaArg {
 | 
	
		
			
				|  |  |                  => VaArg::pointer(ap.arg::<*const c_void>()),
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    unsafe fn transmute(&self, arg: &PrintfArg) -> VaArg {
 | 
	
		
			
				|  |  | +        // At this point, there are conflicting printf arguments. An
 | 
	
		
			
				|  |  | +        // example of this is:
 | 
	
		
			
				|  |  | +        // ```c
 | 
	
		
			
				|  |  | +        // printf("%1$d %1$lf\n", 5, 0.1);
 | 
	
		
			
				|  |  | +        // ```
 | 
	
		
			
				|  |  | +        // We handle it just like glibc: We read it from the VaList
 | 
	
		
			
				|  |  | +        // using the *last* argument type, but we transmute it when we
 | 
	
		
			
				|  |  | +        // try to access the other ones.
 | 
	
		
			
				|  |  | +        union Untyped {
 | 
	
		
			
				|  |  | +            c_char: c_char,
 | 
	
		
			
				|  |  | +            c_double: c_double,
 | 
	
		
			
				|  |  | +            c_int: c_int,
 | 
	
		
			
				|  |  | +            c_long: c_long,
 | 
	
		
			
				|  |  | +            c_longlong: c_longlong,
 | 
	
		
			
				|  |  | +            c_short: c_short,
 | 
	
		
			
				|  |  | +            intmax_t: intmax_t,
 | 
	
		
			
				|  |  | +            pointer: *const c_void,
 | 
	
		
			
				|  |  | +            ptrdiff_t: ptrdiff_t,
 | 
	
		
			
				|  |  | +            ssize_t: ssize_t
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        let untyped = match *self {
 | 
	
		
			
				|  |  | +            VaArg::c_char(i) => Untyped { c_char: i },
 | 
	
		
			
				|  |  | +            VaArg::c_double(i) => Untyped { c_double: i },
 | 
	
		
			
				|  |  | +            VaArg::c_int(i) => Untyped { c_int: i },
 | 
	
		
			
				|  |  | +            VaArg::c_long(i) => Untyped { c_long: i },
 | 
	
		
			
				|  |  | +            VaArg::c_longlong(i) => Untyped { c_longlong: i },
 | 
	
		
			
				|  |  | +            VaArg::c_short(i) => Untyped { c_short: i },
 | 
	
		
			
				|  |  | +            VaArg::intmax_t(i) => Untyped { intmax_t: i },
 | 
	
		
			
				|  |  | +            VaArg::pointer(i) => Untyped { pointer: i },
 | 
	
		
			
				|  |  | +            VaArg::ptrdiff_t(i) => Untyped { ptrdiff_t: i },
 | 
	
		
			
				|  |  | +            VaArg::ssize_t(i) => Untyped { ssize_t: i }
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        match (arg.fmtkind, arg.intkind) {
 | 
	
		
			
				|  |  | +            (FmtKind::Percent, _) => panic!("Can't call transmute on %"),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            (FmtKind::Char, _) |
 | 
	
		
			
				|  |  | +            (FmtKind::Unsigned, IntKind::Byte) |
 | 
	
		
			
				|  |  | +            (FmtKind::Signed, IntKind::Byte) => VaArg::c_char(untyped.c_char),
 | 
	
		
			
				|  |  | +            (FmtKind::Unsigned, IntKind::Short) |
 | 
	
		
			
				|  |  | +            (FmtKind::Signed, IntKind::Short) => VaArg::c_short(untyped.c_short),
 | 
	
		
			
				|  |  | +            (FmtKind::Unsigned, IntKind::Int) |
 | 
	
		
			
				|  |  | +            (FmtKind::Signed, IntKind::Int) => VaArg::c_int(untyped.c_int),
 | 
	
		
			
				|  |  | +            (FmtKind::Unsigned, IntKind::Long) |
 | 
	
		
			
				|  |  | +            (FmtKind::Signed, IntKind::Long) => VaArg::c_long(untyped.c_long),
 | 
	
		
			
				|  |  | +            (FmtKind::Unsigned, IntKind::LongLong) |
 | 
	
		
			
				|  |  | +            (FmtKind::Signed, IntKind::LongLong) => VaArg::c_longlong(untyped.c_longlong),
 | 
	
		
			
				|  |  | +            (FmtKind::Unsigned, IntKind::IntMax) |
 | 
	
		
			
				|  |  | +            (FmtKind::Signed, IntKind::IntMax) => VaArg::intmax_t(untyped.intmax_t),
 | 
	
		
			
				|  |  | +            (FmtKind::Unsigned, IntKind::PtrDiff) |
 | 
	
		
			
				|  |  | +            (FmtKind::Signed, IntKind::PtrDiff) => VaArg::ptrdiff_t(untyped.ptrdiff_t),
 | 
	
		
			
				|  |  | +            (FmtKind::Unsigned, IntKind::Size) |
 | 
	
		
			
				|  |  | +            (FmtKind::Signed, IntKind::Size) => VaArg::ssize_t(untyped.ssize_t),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            (FmtKind::AnyNotation, _) | (FmtKind::Decimal, _) | (FmtKind::Scientific, _)
 | 
	
		
			
				|  |  | +                => VaArg::c_double(untyped.c_double),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            (FmtKind::GetWritten, _) | (FmtKind::Pointer, _) | (FmtKind::String, _)
 | 
	
		
			
				|  |  | +                => VaArg::pointer(untyped.pointer),
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  #[derive(Default)]
 | 
	
		
			
				|  |  |  struct VaListCache {
 | 
	
	
		
			
				|  | @@ -133,8 +194,12 @@ struct VaListCache {
 | 
	
		
			
				|  |  |      i: usize
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  impl VaListCache {
 | 
	
		
			
				|  |  | -    unsafe fn get(&mut self, i: usize, ap: &mut VaList, arg: Option<&PrintfArg>) -> VaArg {
 | 
	
		
			
				|  |  | +    unsafe fn get(&mut self, i: usize, ap: &mut VaList, default: Option<&PrintfArg>) -> VaArg {
 | 
	
		
			
				|  |  |          if let Some(&arg) = self.args.get(i) {
 | 
	
		
			
				|  |  | +            let mut arg = arg;
 | 
	
		
			
				|  |  | +            if let Some(default) = default {
 | 
	
		
			
				|  |  | +                arg = arg.transmute(default);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |              return arg;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          while self.args.len() < i {
 | 
	
	
		
			
				|  | @@ -144,8 +209,8 @@ impl VaListCache {
 | 
	
		
			
				|  |  |              // defaulting to c_int.
 | 
	
		
			
				|  |  |              self.args.push(VaArg::c_int(ap.arg::<c_int>()))
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        self.args.push(match arg {
 | 
	
		
			
				|  |  | -            Some(arg) => VaArg::arg_from(arg, ap),
 | 
	
		
			
				|  |  | +        self.args.push(match default {
 | 
	
		
			
				|  |  | +            Some(default) => VaArg::arg_from(default, ap),
 | 
	
		
			
				|  |  |              None => VaArg::c_int(ap.arg::<c_int>())
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  |          self.args[i]
 |