-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0814087
commit e9e084f
Showing
3 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
6 changes: 6 additions & 0 deletions
6
src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
-include ../tools.mk | ||
|
||
all: | ||
$(RUSTC) checkrust.rs | ||
$(CC) test.c $(call STATICLIB,checkrust) $(call OUT_EXE,test) $(EXTRACFLAGS) | ||
$(call RUN,test) |
142 changes: 142 additions & 0 deletions
142
src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
#![crate_type = "staticlib"] | ||
#![feature(c_variadic)] | ||
#![feature(libc)] | ||
|
||
extern crate libc; | ||
|
||
use libc::{c_char, c_double, c_int, c_long, c_longlong}; | ||
use std::ffi::VaList; | ||
use std::slice; | ||
use std::ffi::CStr; | ||
|
||
#[repr(C)] | ||
#[derive(Clone, Copy, Debug)] | ||
pub enum AnswerType { | ||
Double, | ||
Long, | ||
LongLong, | ||
Int, | ||
Byte, | ||
CStr, | ||
Skip, | ||
} | ||
|
||
#[repr(C)] | ||
pub union AnswerData { | ||
pub double: c_double, | ||
pub long: c_long, | ||
pub longlong: c_longlong, | ||
pub int: c_int, | ||
pub byte: c_char, | ||
pub cstr: *const c_char, | ||
pub skip_ty: AnswerType, | ||
} | ||
|
||
#[repr(C)] | ||
pub struct Answer { | ||
tag: AnswerType, | ||
data: AnswerData, | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe fn compare_answers(answers: &[Answer], mut ap: VaList) -> usize { | ||
for (i, answer) in answers.iter().enumerate() { | ||
match answer { | ||
Answer { tag: AnswerType::Double, data: AnswerData { double: d } } => { | ||
let tmp = ap.arg::<c_double>(); | ||
if d.floor() != tmp.floor() { | ||
println!("Double: {} != {}", d, tmp); | ||
return i + 1; | ||
} | ||
} | ||
Answer { tag: AnswerType::Long, data: AnswerData { long: l } } => { | ||
let tmp = ap.arg::<c_long>(); | ||
if *l != tmp { | ||
println!("Long: {} != {}", l, tmp); | ||
return i + 1; | ||
} | ||
} | ||
Answer { tag: AnswerType::LongLong, data: AnswerData { longlong: l } } => { | ||
let tmp = ap.arg::<c_longlong>(); | ||
if *l != tmp { | ||
println!("Long Long: {} != {}", l, tmp); | ||
return i + 1; | ||
} | ||
} | ||
Answer { tag: AnswerType::Int, data: AnswerData { int: n } } => { | ||
let tmp = ap.arg::<c_int>(); | ||
if *n != tmp { | ||
println!("Int: {} != {}", n, tmp); | ||
return i + 1; | ||
} | ||
} | ||
Answer { tag: AnswerType::Byte, data: AnswerData { byte: b } } => { | ||
let tmp = ap.arg::<c_char>(); | ||
if *b != tmp { | ||
println!("Byte: {} != {}", b, tmp); | ||
return i + 1; | ||
} | ||
} | ||
Answer { tag: AnswerType::CStr, data: AnswerData { cstr: c0 } } => { | ||
let c1 = ap.arg::<*const c_char>(); | ||
let cstr0 = CStr::from_ptr(*c0); | ||
let cstr1 = CStr::from_ptr(c1); | ||
if cstr0 != cstr1 { | ||
println!("C String: {:?} != {:?}", cstr0, cstr1); | ||
return i + 1; | ||
} | ||
} | ||
_ => { | ||
println!("Unknown type!"); | ||
return i + 1; | ||
} | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn check_rust(argc: usize, answers: *const Answer, ap: VaList) -> usize { | ||
let slice = slice::from_raw_parts(answers, argc); | ||
compare_answers(slice, ap) | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn check_rust_copy(argc: usize, answers: *const Answer, | ||
mut ap: VaList) -> usize { | ||
let slice = slice::from_raw_parts(answers, argc); | ||
let mut skip_n = 0; | ||
for (i, answer) in slice.iter().enumerate() { | ||
match answer { | ||
Answer { tag: AnswerType::Skip, data: AnswerData { skip_ty } } => { | ||
match skip_ty { | ||
AnswerType::Double => { ap.arg::<c_double>(); } | ||
AnswerType::Long => { ap.arg::<c_long>(); } | ||
AnswerType::LongLong => { ap.arg::<c_longlong>(); } | ||
AnswerType::Int => { ap.arg::<c_int>(); } | ||
AnswerType::Byte => { ap.arg::<c_char>(); } | ||
AnswerType::CStr => { ap.arg::<*const c_char>(); } | ||
_ => { return i; } | ||
}; | ||
} | ||
_ => { | ||
skip_n = i; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
ap.copy(|ap| { | ||
compare_answers(&slice[skip_n..], ap) | ||
}) | ||
} |
95 changes: 95 additions & 0 deletions
95
src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
#include <stdarg.h> | ||
#include <assert.h> | ||
#include <stdint.h> | ||
#include <stdlib.h> | ||
|
||
typedef enum { | ||
TAG_DOUBLE, | ||
TAG_LONG, | ||
TAG_LONGLONG, | ||
TAG_INT, | ||
TAG_BYTE, | ||
TAG_CSTR, | ||
TAG_SKIP, | ||
} tag; | ||
|
||
typedef struct { | ||
tag answer_type; | ||
union { | ||
double double_precision; | ||
long num_long; | ||
long long num_longlong; | ||
int num_int; | ||
int8_t byte; | ||
char* cstr; | ||
tag skip_ty; | ||
} answer_data; | ||
} answer; | ||
|
||
#define MK_DOUBLE(n) \ | ||
{ TAG_DOUBLE, { .double_precision = n } } | ||
#define MK_LONG(n) \ | ||
{ TAG_LONG, { .num_long = n } } | ||
#define MK_LONGLONG(n) \ | ||
{ TAG_LONGLONG, { .num_longlong = n } } | ||
#define MK_INT(n) \ | ||
{ TAG_INT, { .num_int = n } } | ||
#define MK_BYTE(b) \ | ||
{ TAG_BYTE, { .byte = b } } | ||
#define MK_CSTR(s) \ | ||
{ TAG_CSTR, { .cstr = s } } | ||
#define MK_SKIP(ty) \ | ||
{ TAG_SKIP, { .skip_ty = TAG_ ## ty } } | ||
|
||
extern size_t check_rust(size_t argc, const answer* answers, va_list ap); | ||
extern size_t check_rust_copy(size_t argc, const answer* answers, va_list ap); | ||
|
||
size_t test_check_rust(size_t argc, const answer* answers, ...) { | ||
size_t ret = 0; | ||
va_list ap; | ||
va_start(ap, answers); | ||
ret = check_rust(argc, answers, ap); | ||
va_end(ap); | ||
return ret; | ||
} | ||
|
||
size_t test_check_rust_copy(size_t argc, const answer* answers, ...) { | ||
size_t ret = 0; | ||
va_list ap; | ||
va_start(ap, answers); | ||
ret = check_rust_copy(argc, answers, ap); | ||
va_end(ap); | ||
return ret; | ||
} | ||
|
||
int main(int argc, char* argv[]) { | ||
answer test_alignment0[] = {MK_LONGLONG(0x01LL), MK_INT(0x02), MK_LONGLONG(0x03LL)}; | ||
assert(test_check_rust(3, test_alignment0, 0x01LL, 0x02, 0x03LL) == 0); | ||
|
||
answer test_alignment1[] = {MK_INT(-1), MK_BYTE('A'), MK_BYTE('4'), MK_BYTE(';'), | ||
MK_INT(0x32), MK_INT(0x10000001), MK_CSTR("Valid!")}; | ||
assert(test_check_rust(7, test_alignment1, -1, 'A', '4', ';', 0x32, 0x10000001, | ||
"Valid!") == 0); | ||
|
||
answer basic_answers[] = {MK_DOUBLE(3.14), MK_LONG(12l), MK_BYTE('a'), | ||
MK_DOUBLE(6.28), MK_CSTR("Hello"), MK_INT(42), | ||
MK_CSTR("World")}; | ||
assert(test_check_rust(7, basic_answers, 3.14, 12l, 'a', 6.28, "Hello", | ||
42, "World") == 0); | ||
|
||
answer copy_answers[] = { MK_SKIP(DOUBLE), MK_SKIP(INT), MK_SKIP(BYTE), MK_SKIP(CSTR), | ||
MK_CSTR("Correctly skipped and copied list") }; | ||
assert(test_check_rust_copy(5, copy_answers, 6.28, 16, 'A', "Skip Me!", | ||
"Correctly skipped and copied list") == 0); | ||
return 0; | ||
} |