]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
e9174d1e | 11 | // ignore-msvc -- sprintf isn't a symbol in msvcrt? maybe a #define? |
c34b1796 AL |
12 | |
13 | #![feature(libc, std_misc)] | |
14 | ||
1a4d82fc JJ |
15 | extern crate libc; |
16 | ||
c34b1796 | 17 | use std::ffi::{CStr, CString}; |
1a4d82fc JJ |
18 | use libc::{c_char, c_int}; |
19 | ||
1a4d82fc JJ |
20 | |
21 | extern { | |
22 | fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int; | |
23 | } | |
24 | ||
25 | unsafe fn check<T, F>(expected: &str, f: F) where F: FnOnce(*mut c_char) -> T { | |
26 | let mut x = [0 as c_char; 50]; | |
27 | f(&mut x[0] as *mut c_char); | |
c34b1796 | 28 | assert_eq!(expected.as_bytes(), CStr::from_ptr(x.as_ptr()).to_bytes()); |
1a4d82fc JJ |
29 | } |
30 | ||
31 | pub fn main() { | |
32 | ||
33 | unsafe { | |
34 | // Call with just the named parameter | |
c34b1796 | 35 | let c = CString::new(&b"Hello World\n"[..]).unwrap(); |
1a4d82fc JJ |
36 | check("Hello World\n", |s| sprintf(s, c.as_ptr())); |
37 | ||
38 | // Call with variable number of arguments | |
c34b1796 | 39 | let c = CString::new(&b"%d %f %c %s\n"[..]).unwrap(); |
1a4d82fc | 40 | check("42 42.500000 a %d %f %c %s\n\n", |s| { |
85aaf69f | 41 | sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr()); |
1a4d82fc JJ |
42 | }); |
43 | ||
44 | // Make a function pointer | |
45 | let x: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int = sprintf; | |
46 | ||
47 | // A function that takes a function pointer | |
54a0048b | 48 | unsafe fn call(fp: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) { |
1a4d82fc | 49 | // Call with just the named parameter |
c34b1796 | 50 | let c = CString::new(&b"Hello World\n"[..]).unwrap(); |
54a0048b | 51 | check("Hello World\n", |s| fp(s, c.as_ptr())); |
1a4d82fc JJ |
52 | |
53 | // Call with variable number of arguments | |
c34b1796 | 54 | let c = CString::new(&b"%d %f %c %s\n"[..]).unwrap(); |
1a4d82fc | 55 | check("42 42.500000 a %d %f %c %s\n\n", |s| { |
54a0048b | 56 | fp(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr()); |
1a4d82fc JJ |
57 | }); |
58 | } | |
59 | ||
60 | // Pass sprintf directly | |
61 | call(sprintf); | |
62 | ||
63 | // Pass sprintf indirectly | |
64 | call(x); | |
65 | } | |
66 | ||
67 | } |