diff --git a/Cargo.lock b/Cargo.lock index 98537e48d5..90e67f5081 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -256,7 +256,7 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.18+rb0.2.5" +version = "0.1.18+rb0.3.0" dependencies = [ "bitflags", "libc", @@ -726,4 +726,4 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[patch.unused]] name = "redox-scheme" -version = "0.11.2+rb0.2.5" +version = "0.11.2+rb0.3.0" diff --git a/build.rs b/build.rs index e0fd5be41f..39b0759e8e 100644 --- a/build.rs +++ b/build.rs @@ -8,6 +8,38 @@ fn main() { println!("cargo:rerun-if-changed=src/c"); + // The Redoxer toolchain and some upstream nightlies keep the older + // `VaList<'a>` ABI for `extern "C" fn(...)` parameters, while others + // pass `VaListImpl<'f>` and require `.as_va_list()` to obtain + // `VaList<'_, '_>`. This is a host-compiler property, so probe + // directly with the host rustc (avoiding autocfg's target probing). + println!("cargo:rustc-check-cfg=cfg(relibc_valist_impl)"); + let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".to_string()); + let out_dir = env::var("OUT_DIR").unwrap_or_else(|_| "/tmp".to_string()); + let probe_file = std::path::Path::new(&out_dir).join("relibc_valist_probe.rs"); + let probe_out = std::path::Path::new(&out_dir).join("librelibc_valist_probe.rlib"); + std::fs::write( + &probe_file, + "#![feature(c_variadic)] pub fn _relibc_valist_probe(_: core::ffi::VaList<'_, '_>) {}", + ) + .ok(); + let probe_ok = std::process::Command::new(&rustc) + .args([ + "--crate-type", + "lib", + "--edition", + "2024", + probe_file.to_str().unwrap(), + "-o", + probe_out.to_str().unwrap(), + ]) + .status() + .ok() + .map_or(false, |s| s.success()); + if probe_ok { + println!("cargo:rustc-cfg=relibc_valist_impl"); + } + let mut cc_builder = &mut cc::Build::new(); cc_builder = cc_builder.flag("-nostdinc").flag("-nostdlib"); diff --git a/src/header/err/mod.rs b/src/header/err/mod.rs index 5e47ee4e7c..203794ede1 100644 --- a/src/header/err/mod.rs +++ b/src/header/err/mod.rs @@ -67,7 +67,7 @@ pub unsafe extern "C" fn err_set_exit(ef: ExitCallback) { #[unsafe(no_mangle)] pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, mut va_list: ...) -> ! { let code = Some(ERRNO.get()); - err_exit(eval, code, fmt, va_list.as_va_list()) + err_exit(eval, code, fmt, relibc_as_va_list!(va_list)) } /// Print a user message then an error message for `code` before exiting with `eval` as a return. @@ -78,7 +78,7 @@ pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, mut va_list: ...) /// Exits with `eval` as an error code. #[unsafe(no_mangle)] pub unsafe extern "C" fn errc(eval: c_int, code: c_int, fmt: *const c_char, mut va_list: ...) -> ! { - err_exit(eval, Some(code), fmt, va_list.as_va_list()) + err_exit(eval, Some(code), fmt, relibc_as_va_list!(va_list)) } /// Print a user message then exits with `eval` as a return. @@ -89,7 +89,7 @@ pub unsafe extern "C" fn errc(eval: c_int, code: c_int, fmt: *const c_char, mut /// Exits with `eval` as an error code. #[unsafe(no_mangle)] pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, mut va_list: ...) -> ! { - err_exit(eval, None, fmt, va_list.as_va_list()) + err_exit(eval, None, fmt, relibc_as_va_list!(va_list)) } /// Print a user message and then an error message for [`ERRNO`]. @@ -98,7 +98,7 @@ pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, mut va_list: ...) #[unsafe(no_mangle)] pub unsafe extern "C" fn warn(fmt: *const c_char, mut va_list: ...) { let code = Some(ERRNO.get()); - display_message(code, fmt, va_list.as_va_list()); + display_message(code, fmt, relibc_as_va_list!(va_list)); } /// Print a user message then an error message for `code`. @@ -106,7 +106,7 @@ pub unsafe extern "C" fn warn(fmt: *const c_char, mut va_list: ...) { /// The message format is `progname: fmt: strerror(code)` #[unsafe(no_mangle)] pub unsafe extern "C" fn warnc(code: c_int, fmt: *const c_char, mut va_list: ...) { - display_message(Some(code), fmt, va_list.as_va_list()); + display_message(Some(code), fmt, relibc_as_va_list!(va_list)); } /// Print a user message as a warning. @@ -114,7 +114,7 @@ pub unsafe extern "C" fn warnc(code: c_int, fmt: *const c_char, mut va_list: ... /// The message format is `progname: fmt` #[unsafe(no_mangle)] pub unsafe extern "C" fn warnx(fmt: *const c_char, mut va_list: ...) { - display_message(None, fmt, va_list.as_va_list()); + display_message(None, fmt, relibc_as_va_list!(va_list)); } /// See [`err`]. diff --git a/src/header/fcntl/mod.rs b/src/header/fcntl/mod.rs index 972575fff4..c0c08421a1 100644 --- a/src/header/fcntl/mod.rs +++ b/src/header/fcntl/mod.rs @@ -71,7 +71,7 @@ pub unsafe extern "C" fn fcntl(fildes: c_int, cmd: c_int, mut __valist: ...) -> // c_ulonglong let arg = match cmd { F_DUPFD | F_SETFD | F_SETFL | F_GETLK | F_SETLK | F_SETLKW | F_OFD_GETLK | F_OFD_SETLK - | F_OFD_SETLKW | F_DUPFD_CLOEXEC => unsafe { __valist.arg::() }, + | F_OFD_SETLKW | F_DUPFD_CLOEXEC => unsafe { relibc_va_arg!(__valist, c_ulonglong) }, _ => 0, }; @@ -112,7 +112,7 @@ pub unsafe extern "C" fn openat( let mode = if oflag & O_CREAT == O_CREAT /* || oflag & O_TMPFILE == O_TMPFILE */ { - unsafe { __valist.arg::() } + unsafe { relibc_va_arg!(__valist, mode_t) } } else { 0 }; diff --git a/src/header/monetary/strfmon.rs b/src/header/monetary/strfmon.rs index c0f380604e..b110f34498 100644 --- a/src/header/monetary/strfmon.rs +++ b/src/header/monetary/strfmon.rs @@ -122,7 +122,7 @@ pub unsafe extern "C" fn strfmon( Some('i') => { // International formatting flags.international = true; - let value = unsafe { args.arg::() }; // Get the argument as f64 + let value = unsafe { relibc_va_arg!(args, f64) }; // Get the argument as f64 if let Some(written) = format_monetary(&mut buffer[pos..], value, &DEFAULT_MONETARY, &flags) { @@ -133,7 +133,7 @@ pub unsafe extern "C" fn strfmon( } Some('n') => { // Locale-specific formatting - let value = unsafe { args.arg::() }; // Get the argument as f64 + let value = unsafe { relibc_va_arg!(args, f64) }; // Get the argument as f64 if let Some(written) = format_monetary(&mut buffer[pos..], value, &DEFAULT_MONETARY, &flags) { diff --git a/src/header/semaphore/mod.rs b/src/header/semaphore/mod.rs index c730738654..de8a414ecf 100644 --- a/src/header/semaphore/mod.rs +++ b/src/header/semaphore/mod.rs @@ -159,8 +159,8 @@ pub unsafe extern "C" fn sem_open( } let (mode, value): (mode_t, c_uint) = if create { ( - unsafe { __valist.arg::() }, - unsafe { __valist.arg::() }, + unsafe { relibc_va_arg!(__valist, mode_t) }, + unsafe { relibc_va_arg!(__valist, c_uint) }, ) } else { (0, 0) diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index 8cb689ec54..a67fed3648 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -1415,7 +1415,7 @@ pub unsafe extern "C" fn fprintf( format: *const c_char, mut __valist: ... ) -> c_int { - unsafe { vfprintf(file, format, __valist.as_va_list()) } + unsafe { vfprintf(file, format, relibc_as_va_list!(__valist)) } } /// See . @@ -1433,7 +1433,7 @@ pub unsafe extern "C" fn vdprintf(fd: c_int, format: *const c_char, ap: va_list) /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn dprintf(fd: c_int, format: *const c_char, mut __valist: ...) -> c_int { - unsafe { vdprintf(fd, format, __valist.as_va_list()) } + unsafe { vdprintf(fd, format, relibc_as_va_list!(__valist)) } } /// See . @@ -1445,7 +1445,7 @@ pub unsafe extern "C" fn vprintf(format: *const c_char, ap: va_list) -> c_int { /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn printf(format: *const c_char, mut __valist: ...) -> c_int { - unsafe { vfprintf(&raw mut *stdout, format, __valist.as_va_list()) } + unsafe { vfprintf(&raw mut *stdout, format, relibc_as_va_list!(__valist)) } } /// See . @@ -1470,7 +1470,7 @@ pub unsafe extern "C" fn asprintf( format: *const c_char, mut __valist: ... ) -> c_int { - unsafe { vasprintf(strp, format, __valist.as_va_list()) } + unsafe { vasprintf(strp, format, relibc_as_va_list!(__valist)) } } /// See . @@ -1502,7 +1502,7 @@ pub unsafe extern "C" fn snprintf( printf::printf( &mut platform::StringWriter(s.cast::(), n), CStr::from_ptr(format), - __valist.as_va_list(), + relibc_as_va_list!(__valist), ) } } @@ -1530,7 +1530,7 @@ pub unsafe extern "C" fn sprintf( printf::printf( &mut platform::UnsafeStringWriter(s.cast::()), CStr::from_ptr(format), - __valist.as_va_list(), + relibc_as_va_list!(__valist), ) } } @@ -1558,7 +1558,7 @@ pub unsafe extern "C" fn fscanf( format: *const c_char, mut __valist: ... ) -> c_int { - unsafe { vfscanf(file, format, __valist.as_va_list()) } + unsafe { vfscanf(file, format, relibc_as_va_list!(__valist)) } } /// See . @@ -1570,7 +1570,7 @@ pub unsafe extern "C" fn vscanf(format: *const c_char, ap: va_list) -> c_int { /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn scanf(format: *const c_char, mut __valist: ...) -> c_int { - unsafe { vfscanf(&raw mut *stdin, format, __valist.as_va_list()) } + unsafe { vfscanf(&raw mut *stdin, format, relibc_as_va_list!(__valist)) } } /// See . @@ -1593,7 +1593,7 @@ pub unsafe extern "C" fn sscanf( unsafe { let format = CStr::from_ptr(format); let s = CStr::from_ptr(s); - scanf::scanf(s.into(), format.into(), __valist.as_va_list()) + scanf::scanf(s.into(), format.into(), relibc_as_va_list!(__valist)) } } diff --git a/src/header/stdio/printf.rs b/src/header/stdio/printf.rs index ec9307940d..84d4a78c38 100644 --- a/src/header/stdio/printf.rs +++ b/src/header/stdio/printf.rs @@ -127,36 +127,36 @@ impl VaArg { (FmtKind::Percent, _) => panic!("Can't call arg_from on %"), (FmtKind::Char, IntKind::Long) | (FmtKind::Char, IntKind::LongLong) => { - VaArg::wint_t(unsafe { ap.arg::() }) + VaArg::wint_t(unsafe { relibc_va_arg!(ap, wint_t) }) } (FmtKind::Char, _) | (FmtKind::Unsigned, IntKind::Byte) | (FmtKind::Signed, IntKind::Byte) => { // c_int is passed but truncated to c_char - VaArg::c_char(unsafe { ap.arg::() } as c_char) + VaArg::c_char(unsafe { relibc_va_arg!(ap, c_int) } as c_char) } (FmtKind::Unsigned, IntKind::Short) | (FmtKind::Signed, IntKind::Short) => { // c_int is passed but truncated to c_short - VaArg::c_short(unsafe { ap.arg::() } as c_short) + VaArg::c_short(unsafe { relibc_va_arg!(ap, c_int) } as c_short) } (FmtKind::Unsigned, IntKind::Int) | (FmtKind::Signed, IntKind::Int) => { - VaArg::c_int(unsafe { ap.arg::() }) + VaArg::c_int(unsafe { relibc_va_arg!(ap, c_int) }) } (FmtKind::Unsigned, IntKind::Long) | (FmtKind::Signed, IntKind::Long) => { - VaArg::c_long(unsafe { ap.arg::() }) + VaArg::c_long(unsafe { relibc_va_arg!(ap, c_long) }) } (FmtKind::Unsigned, IntKind::LongLong) | (FmtKind::Signed, IntKind::LongLong) => { - VaArg::c_longlong(unsafe { ap.arg::() }) + VaArg::c_longlong(unsafe { relibc_va_arg!(ap, c_longlong) }) } (FmtKind::Unsigned, IntKind::IntMax) | (FmtKind::Signed, IntKind::IntMax) => { - VaArg::intmax_t(unsafe { ap.arg::() }) + VaArg::intmax_t(unsafe { relibc_va_arg!(ap, intmax_t) }) } (FmtKind::Unsigned, IntKind::PtrDiff) | (FmtKind::Signed, IntKind::PtrDiff) => { - VaArg::ptrdiff_t(unsafe { ap.arg::() }) + VaArg::ptrdiff_t(unsafe { relibc_va_arg!(ap, ptrdiff_t) }) } (FmtKind::Unsigned, IntKind::Size) | (FmtKind::Signed, IntKind::Size) => { - VaArg::ssize_t(unsafe { ap.arg::() }) + VaArg::ssize_t(unsafe { relibc_va_arg!(ap, ssize_t) }) } (FmtKind::AnyNotation, IntKind::LongLong) @@ -165,11 +165,11 @@ impl VaArg { VaArg::c_longdouble(unsafe { VaArg::extract_longdouble(ap) }) } (FmtKind::AnyNotation, _) | (FmtKind::Decimal, _) | (FmtKind::Scientific, _) => { - VaArg::c_double(unsafe { ap.arg::() }) + VaArg::c_double(unsafe { relibc_va_arg!(ap, c_double) }) } (FmtKind::GetWritten, _) | (FmtKind::Pointer, _) | (FmtKind::String, _) => { - VaArg::pointer(unsafe { ap.arg::<*const c_void>() }) + VaArg::pointer(unsafe { relibc_va_arg!(ap, *const c_void) }) } } } @@ -348,13 +348,13 @@ impl VaListCache { // point. Reaching here means there are unused gaps in the // arguments. Ultimately we'll have to settle down with // defaulting to c_int. - self.args.push(VaArg::c_int(unsafe { ap.arg::() })) + self.args.push(VaArg::c_int(unsafe { relibc_va_arg!(ap, c_int) })) } // Add the value to the cache self.args.push(match default { Some((fmtkind, intkind)) => unsafe { VaArg::arg_from(fmtkind, intkind, ap) }, - None => VaArg::c_int(unsafe { ap.arg::() }), + None => VaArg::c_int(unsafe { relibc_va_arg!(ap, c_int) }), }); // Return the value @@ -774,7 +774,7 @@ pub(crate) unsafe fn inner_printf( match num { Number::Next => varargs .args - .push(VaArg::c_int(unsafe { ap.arg::() })), + .push(VaArg::c_int(unsafe { relibc_va_arg!(ap, c_int) })), Number::Index(i) => { positional.insert(i - 1, (FmtKind::Signed, IntKind::Int)); } diff --git a/src/header/stdio/scanf.rs b/src/header/stdio/scanf.rs index 1d89cc54e6..462c61dc8d 100644 --- a/src/header/stdio/scanf.rs +++ b/src/header/stdio/scanf.rs @@ -244,7 +244,7 @@ pub unsafe fn inner_scanf( n.parse::<$type>().map_err(|_| 0)? }; if !ignore { - unsafe { *ap.arg::<*mut $type>() = n }; + unsafe { *relibc_va_arg!(ap, *mut $type) = n }; matched += 1; } }}; @@ -264,7 +264,7 @@ pub unsafe fn inner_scanf( $type::from_str_radix(&n, radix).map_err(|_| 0)? }; if !ignore { - unsafe { *ap.arg::<*mut $final>() = n as $final }; + unsafe { *relibc_va_arg!(ap, *mut $final) = n as $final }; matched += 1; } }}; @@ -346,7 +346,7 @@ pub unsafe fn inner_scanf( } let mut ptr: Option<*mut $type> = - if ignore { None } else { Some(ap.arg()) }; + if ignore { None } else { Some(relibc_va_arg!(ap)) }; while width.map(|w| w > 0).unwrap_or(true) && !character.is_whitespace() { @@ -391,7 +391,7 @@ pub unsafe fn inner_scanf( let ptr: Option<*mut $type> = if ignore { None } else { - Some(unsafe { ap.arg() }) + Some(unsafe { relibc_va_arg!(ap) }) }; for i in 0..width.unwrap_or(1) { @@ -456,7 +456,7 @@ pub unsafe fn inner_scanf( let mut ptr: Option<*mut c_char> = if ignore { None } else { - Some(unsafe { ap.arg() }) + Some(unsafe { relibc_va_arg!(ap) }) }; // While we haven't used up all the width, and it matches @@ -486,7 +486,7 @@ pub unsafe fn inner_scanf( } 'n' => { if !ignore { - unsafe { *ap.arg::<*mut c_int>() = count as c_int }; + unsafe { *relibc_va_arg!(ap, *mut c_int) = count as c_int }; } } _ => return Err(-1), diff --git a/src/header/sys_mman/mod.rs b/src/header/sys_mman/mod.rs index 0930c9660c..5d89b986fc 100644 --- a/src/header/sys_mman/mod.rs +++ b/src/header/sys_mman/mod.rs @@ -112,7 +112,7 @@ pub unsafe extern "C" fn mremap( flags: c_int, mut __valist: ... ) -> *mut c_void { - let new_address = unsafe { __valist.arg::<*mut c_void>() }; + let new_address = unsafe { relibc_va_arg!(__valist, *mut c_void) }; match unsafe { Sys::mremap(old_address, old_size, new_size, flags, new_address) } { Ok(ptr) => ptr, Err(Errno(errno)) => { diff --git a/src/header/sys_ptrace/mod.rs b/src/header/sys_ptrace/mod.rs index 464a8b66e1..23f1eb1001 100644 --- a/src/header/sys_ptrace/mod.rs +++ b/src/header/sys_ptrace/mod.rs @@ -29,8 +29,8 @@ pub const PTRACE_SYSEMU_SINGLESTEP: c_int = 32; /// Non-POSIX, see . #[unsafe(no_mangle)] pub unsafe extern "C" fn ptrace(request: c_int, mut __valist: ...) -> c_int { - let pid = unsafe { __valist.arg::() }; - let addr = unsafe { __valist.arg::<*mut c_void>() }; - let data = unsafe { __valist.arg::<*mut c_void>() }; + let pid = unsafe { relibc_va_arg!(__valist, pid_t) }; + let addr = unsafe { relibc_va_arg!(__valist, *mut c_void) }; + let data = unsafe { relibc_va_arg!(__valist, *mut c_void) }; unsafe { Sys::ptrace(request, pid, addr, data) }.or_minus_one_errno() } diff --git a/src/header/sys_syslog/mod.rs b/src/header/sys_syslog/mod.rs index 9aea6ed58a..b673be38d6 100644 --- a/src/header/sys_syslog/mod.rs +++ b/src/header/sys_syslog/mod.rs @@ -136,7 +136,7 @@ pub unsafe extern "C" fn vsyslog(priority: c_int, message: *const c_char, ap: Va /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn syslog(priority: c_int, message: *const c_char, mut __valist: ...) { - unsafe { vsyslog(priority, message, __valist.as_va_list()) }; + unsafe { vsyslog(priority, message, relibc_as_va_list!(__valist)) }; } /// See . diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index 73393f4180..75e8690b5e 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -4,7 +4,7 @@ use core::{ convert::TryFrom, - ffi::VaList, + ffi::VaList as va_list, mem::{self, MaybeUninit}, ptr, slice, }; @@ -307,7 +307,7 @@ pub unsafe extern "C" fn execl( mut __valist: ... ) -> c_int { unsafe { - with_argv(__valist.as_va_list(), arg0, |args, _remaining_va| { + with_argv(relibc_as_va_list!(__valist), arg0, |args, _remaining_va| { execv(path, args.as_ptr().cast()) }) } @@ -321,8 +321,8 @@ pub unsafe extern "C" fn execle( mut __valist: ... ) -> c_int { unsafe { - with_argv(__valist.as_va_list(), arg0, |args, mut remaining_va| { - let envp = remaining_va.arg::<*const *mut c_char>(); + with_argv(relibc_as_va_list!(__valist), arg0, |args, mut remaining_va| { + let envp = relibc_va_arg!(remaining_va, *const *mut c_char); execve(path, args.as_ptr().cast(), envp) }) } @@ -336,7 +336,7 @@ pub unsafe extern "C" fn execlp( mut __valist: ... ) -> c_int { unsafe { - with_argv(__valist.as_va_list(), arg0, |args, _remaining_va| { + with_argv(relibc_as_va_list!(__valist), arg0, |args, _remaining_va| { execvp(file, args.as_ptr().cast()) }) } @@ -1267,13 +1267,13 @@ pub extern "C" fn vfork() -> pid_t { } unsafe fn with_argv( - mut va: VaList<'_, '_>, + mut va: va_list, arg0: *const c_char, - f: impl FnOnce(&[*const c_char], VaList<'_, '_>) -> c_int, + f: impl FnOnce(&[*const c_char], va_list) -> c_int, ) -> c_int { let argc = 1 + { let mut copy = va.clone(); - core::iter::from_fn(|| Some(unsafe { copy.arg::<*const c_char>() })) + core::iter::from_fn(|| Some(unsafe { relibc_va_arg!(copy, *const c_char) })) .position(|p| p.is_null()) .unwrap() }; @@ -1298,11 +1298,11 @@ unsafe fn with_argv( out[0].write(arg0); for inner in out.iter_mut().take(argc).skip(1) { - (*inner).write(unsafe { va.arg::<*const c_char>() }); + (*inner).write(unsafe { relibc_va_arg!(va, *const c_char) }); } out[argc].write(core::ptr::null()); // NULL - unsafe { va.arg::<*const c_char>() }; + unsafe { relibc_va_arg!(va, *const c_char) }; f(unsafe { (&*out).assume_init_ref() }, va); diff --git a/src/header/unistd/syscall.rs b/src/header/unistd/syscall.rs index d9d00218bf..30f44ff2bb 100644 --- a/src/header/unistd/syscall.rs +++ b/src/header/unistd/syscall.rs @@ -3,12 +3,12 @@ use crate::platform::types::c_long; /// Non-POSIX, see . #[unsafe(no_mangle)] pub unsafe extern "C" fn syscall(sysno: c_long, mut args: ...) -> c_long { - let a1 = unsafe { args.arg::() }; - let a2 = unsafe { args.arg::() }; - let a3 = unsafe { args.arg::() }; - let a4 = unsafe { args.arg::() }; - let a5 = unsafe { args.arg::() }; - let a6 = unsafe { args.arg::() }; + let a1 = unsafe { relibc_va_arg!(args, usize) }; + let a2 = unsafe { relibc_va_arg!(args, usize) }; + let a3 = unsafe { relibc_va_arg!(args, usize) }; + let a4 = unsafe { relibc_va_arg!(args, usize) }; + let a5 = unsafe { relibc_va_arg!(args, usize) }; + let a6 = unsafe { relibc_va_arg!(args, usize) }; (unsafe { sc::syscall6(sysno as usize, a1, a2, a3, a4, a5, a6) }) as c_long } diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index 5d265759e0..ccbfe1bf5a 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -183,7 +183,7 @@ pub unsafe extern "C" fn fwscanf( format: *const wchar_t, mut __valist: ... ) -> c_int { - unsafe { vfwscanf(stream, format, __valist.as_va_list()) } + unsafe { vfwscanf(stream, format, relibc_as_va_list!(__valist)) } } /// See . @@ -342,7 +342,7 @@ pub unsafe extern "C" fn swscanf( format: *const wchar_t, mut __valist: ... ) -> c_int { - unsafe { vswscanf(s, format, __valist.as_va_list()) } + unsafe { vswscanf(s, format, relibc_as_va_list!(__valist)) } } /// See . @@ -396,7 +396,7 @@ pub unsafe extern "C" fn fwprintf( format: *const wchar_t, mut __valist: ... ) -> c_int { - unsafe { vfwprintf(stream, format, __valist.as_va_list()) } + unsafe { vfwprintf(stream, format, relibc_as_va_list!(__valist)) } } /// See . @@ -408,7 +408,7 @@ pub unsafe extern "C" fn vwprintf(format: *const wchar_t, arg: va_list) -> c_int /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wprintf(format: *const wchar_t, mut __valist: ...) -> c_int { - unsafe { vfwprintf(&raw mut *stdout, format, __valist.as_va_list()) } + unsafe { vfwprintf(&raw mut *stdout, format, relibc_as_va_list!(__valist)) } } /// See . @@ -433,7 +433,7 @@ pub unsafe extern "C" fn swprintf( format: *const wchar_t, mut __valist: ... ) -> c_int { - unsafe { vswprintf(s, n, format, __valist.as_va_list()) } + unsafe { vswprintf(s, n, format, relibc_as_va_list!(__valist)) } } /// See . @@ -1047,13 +1047,13 @@ pub unsafe extern "C" fn vfwscanf( /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vwscanf(format: *const wchar_t, mut __valist: va_list) -> c_int { - unsafe { vfwscanf(stdin, format, __valist.as_va_list()) } + unsafe { vfwscanf(stdin, format, __valist) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wscanf(format: *const wchar_t, mut __valist: ...) -> c_int { - unsafe { vfwscanf(stdin, format, __valist.as_va_list()) } + unsafe { vfwscanf(stdin, format, relibc_as_va_list!(__valist)) } } /// See . diff --git a/src/lib.rs b/src/lib.rs index f41627985e..d26f7e5fe2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ //! Currently, Linux and Redox syscall backends are supported. #![no_std] +#![allow(unused_mut)] #![feature(alloc_error_handler)] #![feature(allocator_api)] #![feature(c_variadic)] diff --git a/src/macros.rs b/src/macros.rs index 72b4e414db..37747a87a9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,3 +1,52 @@ +/// Convert an `extern "C" fn(...)` variadic parameter into a `VaList`. +/// +/// Older Rust nightlies pass `core::ffi::VaList` directly for `...` +/// parameters, while newer nightlies pass `core::ffi::VaListImpl` and +/// require `.as_va_list()` to obtain a C-compatible `VaList`. The build +/// script sets `relibc_valist_impl` when the new API is detected. +#[macro_export] +macro_rules! relibc_as_va_list { + ($valist:expr) => {{ + #[cfg(relibc_valist_impl)] + { + $valist.as_va_list() + } + #[cfg(not(relibc_valist_impl))] + { + $valist + } + }}; +} + +/// Read the next argument from a `VaList`. +/// +/// Newer upstream Rust renamed `next_arg()` to `arg()`. The Redoxer +/// toolchain keeps the older `next_arg()` name. The build script sets +/// `relibc_valist_impl` when the newer API is detected. +#[macro_export] +macro_rules! relibc_va_arg { + ($ap:expr) => {{ + #[cfg(relibc_valist_impl)] + { + $ap.arg() + } + #[cfg(not(relibc_valist_impl))] + { + $ap.next_arg() + } + }}; + ($ap:expr, $T:ty) => {{ + #[cfg(relibc_valist_impl)] + { + $ap.arg::<$T>() + } + #[cfg(not(relibc_valist_impl))] + { + $ap.next_arg::<$T>() + } + }}; +} + /// Print to stdout #[macro_export] macro_rules! print {