diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2013-08-14 21:41:40 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2013-08-19 07:13:15 -0400 |
| commit | 0479d946c83cf9ed90bba5b33820ea4118dd8f9e (patch) | |
| tree | 0e31638f9dee1f085c9463e2a6b3f8b9209c6fdd /src/libsyntax/ext | |
| parent | 303f650ecfb5580f3d89aa662fbd164b849c8eff (diff) | |
Add externfn macro and correctly label fixed_stack_segments
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index a4132e6c879..4bea1dc23e7 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -968,6 +968,85 @@ pub fn std_macros() -> @str { pub static $name: ::std::local_data::Key<$ty> = &::std::local_data::Key; ) ) + + // externfn! declares a wrapper for an external function. + // It is intended to be used like: + // + // externfn!(#[nolink] + // #[abi = \"cdecl\"] + // fn memcmp(cx: *u8, ct: *u8, n: u32) -> u32) + // + // Due to limitations in the macro parser, this pattern must be + // implemented with 4 distinct patterns (with attrs / without + // attrs CROSS with args / without ARGS). + // + // Also, this macro grammar allows for any number of return types + // because I couldn't figure out the syntax to specify at most one. + macro_rules! externfn( + (fn $name:ident () $(-> $ret_ty:ty),*) => ( + pub unsafe fn $name() $(-> $ret_ty),* { + // Note: to avoid obscure bug in macros, keep these + // attributes *internal* to the fn + #[fixed_stack_segment]; + #[inline(never)]; + #[allow(missing_doc)]; + + return $name(); + + extern { + fn $name() $(-> $ret_ty),*; + } + } + ); + (fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => ( + pub unsafe fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),* { + // Note: to avoid obscure bug in macros, keep these + // attributes *internal* to the fn + #[fixed_stack_segment]; + #[inline(never)]; + #[allow(missing_doc)]; + + return $name($($arg_name),*); + + extern { + fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*; + } + } + ); + ($($attrs:attr)* fn $name:ident () $(-> $ret_ty:ty),*) => ( + pub unsafe fn $name() $(-> $ret_ty),* { + // Note: to avoid obscure bug in macros, keep these + // attributes *internal* to the fn + #[fixed_stack_segment]; + #[inline(never)]; + #[allow(missing_doc)]; + + return $name(); + + $($attrs)* + extern { + fn $name() $(-> $ret_ty),*; + } + } + ); + ($($attrs:attr)* fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => ( + pub unsafe fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),* { + // Note: to avoid obscure bug in macros, keep these + // attributes *internal* to the fn + #[fixed_stack_segment]; + #[inline(never)]; + #[allow(missing_doc)]; + + return $name($($arg_name),*); + + $($attrs)* + extern { + fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*; + } + } + ) + ) + }"; } |
