Fixed the memory functions required for LLVM to properly work.
This required the fixing of the features section to properly handle passing on the use_std feature. It also required that the memory functions were moved to the main library module instead of within the rust module as was previously desired. The C module then correctly skips defining the external C library functions. Basic time functionality was also added.
This commit is contained in:
parent
102713417d
commit
89e37b017b
14
Cargo.toml
14
Cargo.toml
@ -1,12 +1,20 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "c_rs"
|
name = "pact"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Jason Travis Smith <Myrddin@CyberMagesLLC.com>"]
|
authors = ["Jason Travis Smith <Myrddin@CyberMagesLLC.com>"]
|
||||||
description = "Rust bindings for standard C functions."
|
description = "Rust bindings for standard C functions."
|
||||||
license = ""
|
license = ""
|
||||||
repository = "https://gitlab.com/CyberMages/c_rs.git"
|
repository = "https://gitlab.com/CyberMages/pact.git"
|
||||||
documentation = ""
|
documentation = ""
|
||||||
keywords = ["c", "libc", "binding", "ffi"]
|
keywords = ["c", "libc", "binding", "ffi", "pact", "nostd"]
|
||||||
|
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["c_lib"]
|
||||||
|
use_std = ["scribe/use_std", "binding/use_std"]
|
||||||
|
c_lib = []
|
||||||
|
no_mem_manip = []
|
||||||
|
weak = []
|
||||||
|
|
||||||
|
|
||||||
[dependencies.scribe]
|
[dependencies.scribe]
|
||||||
|
61
README.md
61
README.md
@ -1,3 +1,58 @@
|
|||||||
# C #
|
# Pact #
|
||||||
This library will provided binding for the standard C functions. Later, as a
|
This library will provided the binding for the standard 'C' functions.
|
||||||
stretch goal, this library will attempt to implement those functions in Rust.
|
Later, as a stretch goal, this library will attempt to implement those
|
||||||
|
functions in Rust.
|
||||||
|
|
||||||
|
## Features ##
|
||||||
|
This library handles several different ways of providing what is needed
|
||||||
|
at the 'C' binding level.
|
||||||
|
|
||||||
|
### Standard C Library ###
|
||||||
|
|
||||||
|
This is the default feature set. Or you can add:
|
||||||
|
|
||||||
|
```
|
||||||
|
default-features = false
|
||||||
|
features = ["c_lib"]
|
||||||
|
```
|
||||||
|
|
||||||
|
It will provide a link to the 'C' standard library. This will make it so
|
||||||
|
that your code is executable and can call functions and use structures from
|
||||||
|
the standard 'C' library.
|
||||||
|
|
||||||
|
### Rust C Library ###
|
||||||
|
|
||||||
|
```
|
||||||
|
default-features = false
|
||||||
|
features = ["rust_lib"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Currently, this does not work. Later, this will provide a Rust version of
|
||||||
|
all the 'C' standard library functions. This is a **huge** stretch goal.
|
||||||
|
It may not happen, or it may take a really long time to get this done.
|
||||||
|
This will require alot of platform specific work.
|
||||||
|
|
||||||
|
### No Memory Manipulation ###
|
||||||
|
|
||||||
|
```
|
||||||
|
default-features = false
|
||||||
|
features = ["no_mem_manip"]
|
||||||
|
```
|
||||||
|
|
||||||
|
This feature tells the library to not define the memory manipulation
|
||||||
|
functions that Rust requires for LLVM. These are:
|
||||||
|
|
||||||
|
* memcpy
|
||||||
|
* memmove
|
||||||
|
* memset
|
||||||
|
* memcmp
|
||||||
|
|
||||||
|
### Weak ###
|
||||||
|
|
||||||
|
```
|
||||||
|
default-features = false
|
||||||
|
features = ["no_mem_manip", "weak"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Activates weak linkage on ELF objects. This is only useful when combined with
|
||||||
|
the 'no_mem_manip' feature.
|
||||||
|
12
src/c/mod.rs
Normal file
12
src/c/mod.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//! Handle defining the external functions from what ever C library is
|
||||||
|
//! being linked against. These will use the C99 definitions so that
|
||||||
|
//! this library is as up-to-date as it can be.
|
||||||
|
|
||||||
|
|
||||||
|
mod string;
|
||||||
|
mod time;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub use self::string::*;
|
||||||
|
pub use self::time::*;
|
56
src/c/string.rs
Normal file
56
src/c/string.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#[link(name="c")]
|
||||||
|
extern
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature="no_mem_manip"))]
|
||||||
|
#[link(name="c")]
|
||||||
|
extern
|
||||||
|
{
|
||||||
|
/// Copies the values of n bytes from the location pointed to by
|
||||||
|
/// src directly to the memory block pointed to by dest.
|
||||||
|
///
|
||||||
|
/// The underlying type of the objects pointed to by both the src
|
||||||
|
/// and dest pointers are irrelevant for this function; The
|
||||||
|
/// result is a binary copy of the data.
|
||||||
|
///
|
||||||
|
/// The function does not check for any terminating null character
|
||||||
|
/// in source - it always copies exactly n bytes.
|
||||||
|
///
|
||||||
|
/// To avoid overflows, the size of the arrays pointed to by both
|
||||||
|
/// the dest and src parameters, shall be at least n bytes,
|
||||||
|
/// and should not overlap (for overlapping memory blocks, memmove
|
||||||
|
/// is a safer approach).
|
||||||
|
pub fn memcpy(dest: *mut u8, src: *const u8, n: usize);
|
||||||
|
|
||||||
|
/// Copies the values of n bytes from the location pointed by src
|
||||||
|
/// to the memory block pointed by dest. Copying takes place
|
||||||
|
/// as if an intermediate buffer were used, allowing the dest
|
||||||
|
/// and src to overlap.
|
||||||
|
///
|
||||||
|
/// The underlying type of the objects pointed by both the src and
|
||||||
|
/// dest pointers are irrelevant for this function; The result
|
||||||
|
/// is a binary copy of the data.
|
||||||
|
///
|
||||||
|
/// The function does not check for any terminating null character
|
||||||
|
/// in source - it always copies exactly n bytes.
|
||||||
|
///
|
||||||
|
/// To avoid overflows, the size of the arrays pointed by both
|
||||||
|
/// the dest and src parameters, shall be at least n bytes.
|
||||||
|
pub fn memmove(dest: *mut u8, src: *const u8, n: usize);
|
||||||
|
|
||||||
|
|
||||||
|
/// Compares the first n bytes of the block of memory pointed by
|
||||||
|
/// s1 to the first num bytes pointed by s2, returning zero if
|
||||||
|
/// they all match or a value different from zero representing which
|
||||||
|
/// is greater if they do not.
|
||||||
|
///
|
||||||
|
/// Notice that, unlike strcmp, the function does not stop comparing
|
||||||
|
/// after finding a null character.
|
||||||
|
pub fn memcmp(s1: *const u8, s2: *const u8, n: usize);
|
||||||
|
|
||||||
|
|
||||||
|
/// Sets the first n bytes of the block of memory pointed by s
|
||||||
|
/// to the specified value c (interpreted as an unsigned char).
|
||||||
|
pub fn memset(s: *mut u8, c: i32, n: usize);
|
||||||
|
}
|
55
src/c/time.rs
Normal file
55
src/c/time.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use binding::{CInt, CLong};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// The type used for seconds in the time structures.
|
||||||
|
pub type Seconds = CLong;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// The local time of the system. This can be used
|
||||||
|
/// to get more specific calendar type information.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct LocalTime
|
||||||
|
{
|
||||||
|
/// Seconds [0-60] **Note** 1 leap second.
|
||||||
|
second: CInt,
|
||||||
|
|
||||||
|
/// Minutes [0-59].
|
||||||
|
minute: CInt,
|
||||||
|
|
||||||
|
/// Hours [0-23].
|
||||||
|
hour: CInt,
|
||||||
|
|
||||||
|
/// Day of the month [1-31].
|
||||||
|
day_of_month: CInt,
|
||||||
|
|
||||||
|
/// Month of the year [0-11].
|
||||||
|
month: CInt,
|
||||||
|
|
||||||
|
/// Years since 1900.
|
||||||
|
year: CInt,
|
||||||
|
|
||||||
|
/// Days since Sunday [0-6].
|
||||||
|
day_of_week: CInt,
|
||||||
|
|
||||||
|
/// Days since January 1 [0-365].
|
||||||
|
day_of_year: CInt,
|
||||||
|
|
||||||
|
/// DST [-1/0/1]. Greater than zero if DST is in effect,
|
||||||
|
/// zero if DST is not in effect, and less than zero if
|
||||||
|
/// the information is not available.
|
||||||
|
is_dst: CInt,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[link(name="c")]
|
||||||
|
extern
|
||||||
|
{
|
||||||
|
/// Uses the value pointed by time to fill a LocalTime structure with
|
||||||
|
/// the values that represent the corresponding time, expressed
|
||||||
|
/// for the local timezone.
|
||||||
|
pub fn localtime(time: *const Seconds) -> *const LocalTime;
|
||||||
|
}
|
35
src/lib.rs
35
src/lib.rs
@ -1,6 +1,41 @@
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
|
// Handle using the core or the std of Rust depending on the chosen feature.
|
||||||
|
#![cfg_attr(not(feature="use_std"), no_std)]
|
||||||
|
|
||||||
|
// This crate can only use parts of Rust that are in both the core
|
||||||
|
// and the standard library. This way the logging system will work for
|
||||||
|
// libraries that use either.
|
||||||
|
//
|
||||||
|
// This is handled by coding using the std library and referencing the core
|
||||||
|
// library as the std library if the core library is desired.
|
||||||
|
#[cfg(not(feature="use_std"))]
|
||||||
|
extern crate core as std;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate scribe;
|
extern crate scribe;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate binding;
|
extern crate binding;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(feature="c_lib")]
|
||||||
|
mod c;
|
||||||
|
|
||||||
|
#[cfg(not(feature="c_lib"))]
|
||||||
|
mod rust;
|
||||||
|
|
||||||
|
#[cfg(feature="no_mem_manip")]
|
||||||
|
mod mem;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(feature="c_lib")]
|
||||||
|
pub use self::c::*;
|
||||||
|
|
||||||
|
#[cfg(not(feature="c_lib"))]
|
||||||
|
pub use self::rust::*;
|
||||||
|
|
||||||
|
#[cfg(feature="no_mem_manip")]
|
||||||
|
pub use self::mem::*;
|
||||||
|
144
src/mem.rs
Normal file
144
src/mem.rs
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
//! This section deals with the memory manipulation functions. These should
|
||||||
|
//! be in the string module inside the rust module to more closely match
|
||||||
|
//! the 'C' library, but the no library feature needs them as well.
|
||||||
|
//! These functions are here so that there does not need to be
|
||||||
|
//! any duplication of the code.
|
||||||
|
|
||||||
|
// There is nothing to do on windows or macos as weak linkage seems to
|
||||||
|
// only work with ELF objects.
|
||||||
|
#![cfg_attr(all(feature="weak", not(windows), not(target_os="macos")),
|
||||||
|
feature(linkage))]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Copies the values of n bytes from the location pointed to by
|
||||||
|
/// src directly to the memory block pointed to by dest.
|
||||||
|
///
|
||||||
|
/// The underlying type of the objects pointed to by both the src
|
||||||
|
/// and dest pointers are irrelevant for this function; The
|
||||||
|
/// result is a binary copy of the data.
|
||||||
|
///
|
||||||
|
/// The function does not check for any terminating null character
|
||||||
|
/// in source - it always copies exactly n bytes.
|
||||||
|
///
|
||||||
|
/// To avoid overflows, the size of the arrays pointed to by both
|
||||||
|
/// the dest and src parameters, shall be at least n bytes,
|
||||||
|
/// and should not overlap (for overlapping memory blocks, memmove
|
||||||
|
/// is a safer approach).
|
||||||
|
#[cfg_attr(all(feature="weak", not(windows), not(target_os="macos")),
|
||||||
|
linkage="weak")]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, n: usize)
|
||||||
|
-> *mut u8
|
||||||
|
{
|
||||||
|
let mut i: usize;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while i < n
|
||||||
|
{
|
||||||
|
*dest.offset(i as isize) = *src.offset(i as isize);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copies the values of n bytes from the location pointed by src
|
||||||
|
/// to the memory block pointed by dest. Copying takes place
|
||||||
|
/// as if an intermediate buffer were used, allowing the dest
|
||||||
|
/// and src to overlap.
|
||||||
|
///
|
||||||
|
/// The underlying type of the objects pointed by both the src and
|
||||||
|
/// dest pointers are irrelevant for this function; The result
|
||||||
|
/// is a binary copy of the data.
|
||||||
|
///
|
||||||
|
/// The function does not check for any terminating null character
|
||||||
|
/// in source - it always copies exactly n bytes.
|
||||||
|
///
|
||||||
|
/// To avoid overflows, the size of the arrays pointed by both
|
||||||
|
/// the dest and src parameters, shall be at least n bytes.
|
||||||
|
#[cfg_attr(all(feature = "weak", not(windows), not(target_os = "macos")),
|
||||||
|
linkage = "weak")]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, n: usize)
|
||||||
|
-> *mut u8
|
||||||
|
{
|
||||||
|
let mut i: usize;
|
||||||
|
|
||||||
|
if src < dest as *const u8
|
||||||
|
{
|
||||||
|
// copy from end
|
||||||
|
i = n;
|
||||||
|
while i != 0
|
||||||
|
{
|
||||||
|
i -= 1;
|
||||||
|
*dest.offset(i as isize) = *src.offset(i as isize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// copy from beginning
|
||||||
|
i = 0;
|
||||||
|
while i < n
|
||||||
|
{
|
||||||
|
*dest.offset(i as isize) = *src.offset(i as isize);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compares the first n bytes of the block of memory pointed by
|
||||||
|
/// s1 to the first num bytes pointed by s2, returning zero if
|
||||||
|
/// they all match or a value different from zero representing which
|
||||||
|
/// is greater if they do not.
|
||||||
|
///
|
||||||
|
/// Notice that, unlike strcmp, the function does not stop comparing
|
||||||
|
/// after finding a null character.
|
||||||
|
#[cfg_attr(all(feature = "weak", not(windows), not(target_os = "macos")),
|
||||||
|
linkage = "weak")]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize)
|
||||||
|
-> i32
|
||||||
|
{
|
||||||
|
let mut a: u8;
|
||||||
|
let mut b: u8;
|
||||||
|
let mut i: usize;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while i < n
|
||||||
|
{
|
||||||
|
a = *s1.offset(i as isize);
|
||||||
|
b = *s2.offset(i as isize);
|
||||||
|
|
||||||
|
if a != b
|
||||||
|
{
|
||||||
|
return (a as i32) - (b as i32)
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the first n bytes of the block of memory pointed by s
|
||||||
|
/// to the specified value c (interpreted as an unsigned char).
|
||||||
|
#[cfg_attr(all(feature = "weak", not(windows), not(target_os = "macos")),
|
||||||
|
linkage = "weak")]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern fn memset(s: *mut u8, c: i32, n: usize)
|
||||||
|
-> *mut u8
|
||||||
|
{
|
||||||
|
let mut i: usize;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while i < n
|
||||||
|
{
|
||||||
|
*s.offset(i as isize) = c as u8;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
0
src/rust/mod.rs
Normal file
0
src/rust/mod.rs
Normal file
Loading…
x
Reference in New Issue
Block a user