Added a build script.
The build script was added to obtain the correct values of the errno C preprocessor definitions. This way no matter what the platform has defined them as, they will be correct in the libraries code.
This commit is contained in:
parent
6e350daf26
commit
43abe9d95f
10
Cargo.toml
10
Cargo.toml
@ -7,18 +7,26 @@ license = ""
|
||||
repository = "https://gitlab.com/CyberMages/pact.git"
|
||||
documentation = ""
|
||||
keywords = ["c", "libc", "binding", "ffi", "pact", "nostd"]
|
||||
build = "build.rs"
|
||||
|
||||
|
||||
[features]
|
||||
default = []
|
||||
use_std = ["scribe/use_std", "binding/use_std"]
|
||||
use_std = ["scribe/use_std", "binding/use_std", "weave/use_std"]
|
||||
rust_lib = []
|
||||
no_mem_manip = []
|
||||
weak = []
|
||||
|
||||
|
||||
[build-dependencies.scribe]
|
||||
git = "https://gitlab.com/CyberMages/scribe.git"
|
||||
|
||||
|
||||
[dependencies.scribe]
|
||||
git = "https://gitlab.com/CyberMages/scribe.git"
|
||||
|
||||
[dependencies.binding]
|
||||
git = "https://gitlab.com/CyberMages/binding.git"
|
||||
|
||||
[dependencies.weave]
|
||||
git = "https://gitlab.com/CyberMages/weave.git"
|
||||
|
202
build.rs
Normal file
202
build.rs
Normal file
@ -0,0 +1,202 @@
|
||||
#[macro_use]
|
||||
extern crate scribe;
|
||||
|
||||
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
||||
|
||||
pub const BUILD_DIR: &'static str = "build";
|
||||
|
||||
pub const ERRNO_GENERATOR_FILENAME: &'static str = "errno.c";
|
||||
pub const ERRNO_GENERATOR_OUTPUT_FILENAME: &'static str = "errno.gen";
|
||||
|
||||
pub const GENERATED_ERRNO_FILENAME: &'static str = "errno_values.rs";
|
||||
|
||||
|
||||
|
||||
fn determine_base_dir() -> PathBuf
|
||||
{
|
||||
// Get the cargo manifest directory.
|
||||
match ::std::env::var_os("CARGO_MANIFEST_DIR")
|
||||
{
|
||||
Some(dir) =>
|
||||
{
|
||||
PathBuf::from(dir)
|
||||
}
|
||||
|
||||
None =>
|
||||
{
|
||||
PathBuf::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn determine_output_dir() -> PathBuf
|
||||
{
|
||||
let output_dir: PathBuf;
|
||||
|
||||
// Get the output directory for the build.
|
||||
match ::std::env::var_os("OUT_DIR")
|
||||
{
|
||||
Some(dir) =>
|
||||
{
|
||||
output_dir = PathBuf::from(dir);
|
||||
}
|
||||
|
||||
None =>
|
||||
{
|
||||
// Try to just get the current directory.
|
||||
match env::current_dir()
|
||||
{
|
||||
Ok(dir) =>
|
||||
{
|
||||
output_dir = PathBuf::from(dir);
|
||||
}
|
||||
|
||||
Err(error) =>
|
||||
{
|
||||
// Then just default to "".
|
||||
warn!("{}", error);
|
||||
output_dir = PathBuf::new();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output_dir
|
||||
}
|
||||
|
||||
fn determine_build_dir() -> PathBuf
|
||||
{
|
||||
let mut build_dir: PathBuf;
|
||||
|
||||
build_dir = determine_base_dir();
|
||||
build_dir.push(BUILD_DIR);
|
||||
|
||||
build_dir
|
||||
}
|
||||
|
||||
fn determine_c_compiler() -> OsString
|
||||
{
|
||||
match ::std::env::var_os("CC")
|
||||
{
|
||||
Some(compiler) =>
|
||||
{
|
||||
OsString::from(compiler)
|
||||
}
|
||||
|
||||
None =>
|
||||
{
|
||||
OsString::from("gcc")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_output_file(filename: &str) -> PathBuf
|
||||
{
|
||||
let mut output_dir: PathBuf;
|
||||
|
||||
output_dir = determine_output_dir();
|
||||
output_dir.push(filename);
|
||||
|
||||
output_dir
|
||||
}
|
||||
|
||||
fn build_src_file(filename: &str) -> PathBuf
|
||||
{
|
||||
let mut build_dir: PathBuf;
|
||||
|
||||
build_dir = determine_build_dir();
|
||||
build_dir.push(filename);
|
||||
|
||||
build_dir
|
||||
}
|
||||
|
||||
fn compile(src_files: &[PathBuf], output_name: &str) -> PathBuf
|
||||
{
|
||||
let c_compiler: OsString;
|
||||
let mut output_file: PathBuf;
|
||||
let mut initial_command: ::std::process::Command;
|
||||
let command: &mut ::std::process::Command;
|
||||
let last_command: &mut ::std::process::Command;
|
||||
let final_command: &mut ::std::process::Command;
|
||||
|
||||
c_compiler = determine_c_compiler();
|
||||
output_file = build_output_file(output_name);
|
||||
|
||||
initial_command = ::std::process::Command::new(c_compiler);
|
||||
command = initial_command.args(src_files);
|
||||
last_command = command.arg("-o");
|
||||
final_command = last_command.arg(output_file.clone());
|
||||
|
||||
match final_command.output()
|
||||
{
|
||||
Ok(output) =>
|
||||
{
|
||||
if output.status.success() == false
|
||||
{
|
||||
error!("{:?}", output);
|
||||
}
|
||||
}
|
||||
|
||||
Err(error) =>
|
||||
{
|
||||
error!("{}", error);
|
||||
}
|
||||
}
|
||||
|
||||
output_file
|
||||
}
|
||||
|
||||
fn run(executable: PathBuf, args: &[PathBuf])
|
||||
{
|
||||
let mut initial_command: ::std::process::Command;
|
||||
let final_command: &mut ::std::process::Command;
|
||||
|
||||
initial_command = ::std::process::Command::new(executable);
|
||||
final_command = initial_command.args(args);
|
||||
|
||||
match final_command.output()
|
||||
{
|
||||
Ok(output) =>
|
||||
{
|
||||
if output.status.success() == false
|
||||
{
|
||||
error!("{:?}", output);
|
||||
}
|
||||
}
|
||||
|
||||
Err(error) =>
|
||||
{
|
||||
error!("{}", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_and_run(output_name: &str, src_files: &[PathBuf], args: &[PathBuf])
|
||||
{
|
||||
let executable: PathBuf;
|
||||
|
||||
executable = compile(src_files, output_name);
|
||||
run(executable, args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn main()
|
||||
{
|
||||
let mut errno_file: PathBuf;
|
||||
let mut gen_file: PathBuf;
|
||||
let mut gen_errno_file: PathBuf;
|
||||
|
||||
errno_file = build_src_file(ERRNO_GENERATOR_FILENAME);
|
||||
gen_file = build_output_file(ERRNO_GENERATOR_OUTPUT_FILENAME);
|
||||
gen_errno_file = build_output_file(GENERATED_ERRNO_FILENAME);
|
||||
|
||||
compile_and_run(ERRNO_GENERATOR_OUTPUT_FILENAME,
|
||||
&[errno_file], &[gen_errno_file]);
|
||||
}
|
51
build/errno.c
Normal file
51
build/errno.c
Normal file
@ -0,0 +1,51 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
// Writes a public constant value to the desired file.
|
||||
void write_constant(FILE* file, const char* name,
|
||||
const char* type, const int val)
|
||||
{
|
||||
fprintf(file, "pub const %s: %s = %d;\n", name, type, val);
|
||||
}
|
||||
|
||||
// Writes the header of the errno file.
|
||||
void write_file_header(FILE* file)
|
||||
{
|
||||
fprintf(file, "// This was generated by a build script to obtain\n");
|
||||
fprintf(file, "// the correct values of C preprocessor values to\n");
|
||||
fprintf(file, "// be used as errno constant values.\n");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char* filename;
|
||||
FILE* output_file;
|
||||
|
||||
// This requires a filename to be given for writing to.
|
||||
if (argc == 2)
|
||||
{
|
||||
filename = argv[1];
|
||||
}
|
||||
else if (argc > 2 || argc < 2)
|
||||
{
|
||||
printf("\nThis program requires a filename be given.\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Open a file for writing.
|
||||
output_file = fopen(filename, "w");
|
||||
|
||||
// Write the errno file header.
|
||||
write_file_header(output_file);
|
||||
|
||||
// Write the errno constants we are trying to capture.
|
||||
write_constant(output_file, "EDOM", "CInt", EDOM);
|
||||
write_constant(output_file, "ERANGE", "CInt", ERANGE);
|
||||
write_constant(output_file, "EILSEQ", "CInt", EILSEQ);
|
||||
|
||||
// Close the file.
|
||||
fclose(output_file);
|
||||
return 0;
|
||||
}
|
167
src/c/errno.rs
Normal file
167
src/c/errno.rs
Normal file
@ -0,0 +1,167 @@
|
||||
use weave::Error;
|
||||
use binding::CInt;
|
||||
|
||||
|
||||
|
||||
/// This signifies that there is no current error.
|
||||
/// This can be used for clearing an error.
|
||||
pub const NO_ERROR: CInt = 0;
|
||||
|
||||
/// Include the generated C error values.
|
||||
include!(concat!(env!("OUT_DIR"), "/errno_values.rs"));
|
||||
|
||||
|
||||
|
||||
///
|
||||
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub enum CError
|
||||
{
|
||||
/// There is no Error.
|
||||
None,
|
||||
|
||||
/// Some mathematical functions are only defined
|
||||
/// for certain real values, which is called its domain,
|
||||
/// for example the square root function is only defined for
|
||||
/// non-negative numbers, therefore the sqrt function sets
|
||||
/// errno to EDOM if called with a negative argument.
|
||||
Domain,
|
||||
|
||||
/// The range of values that can be represented
|
||||
/// with a variable is limited. For example, mathematical functions
|
||||
/// such as pow can easily outbound the range representable by a
|
||||
/// floating point variable, or functions such as strtod can
|
||||
/// encounter sequences of digits longer than the range
|
||||
/// representable values. In these cases, errno is set to ERANGE.
|
||||
Range,
|
||||
|
||||
/// Multibyte character sequence may have a
|
||||
/// restricted set of valid sequences. When a set of multibyte
|
||||
/// characters is translated by functions such as mbrtowc,
|
||||
/// errno is set to EILSEQ when an invalid sequence is encountered.
|
||||
IllegalSequence,
|
||||
|
||||
/// There was a detected error, but it
|
||||
/// is not one handled by CError.
|
||||
Unhandled
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl CError
|
||||
{
|
||||
/// Returns if the given value is a handled CError.
|
||||
pub fn is_handled_error(errno: i32) -> bool
|
||||
{
|
||||
let error: CError;
|
||||
|
||||
// Turn the error value into a CError and
|
||||
// check if it is an Unhandled error.
|
||||
error = CError::from(errno);
|
||||
if error != CError::Unhandled
|
||||
{
|
||||
true
|
||||
}
|
||||
else
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Check the last Error that was posted.
|
||||
pub fn get_current_error() -> CError
|
||||
{
|
||||
CError::from(get_errno())
|
||||
}
|
||||
|
||||
/// Set the current Error for the system.
|
||||
pub fn set_current_error(error: CError)
|
||||
{
|
||||
set_errno(error as i32);
|
||||
}
|
||||
|
||||
/// Clear the current Error.
|
||||
pub fn clear()
|
||||
{
|
||||
CError::set_current_error(CError::None);
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for CError
|
||||
{
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
|
||||
{
|
||||
::std::fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for CError
|
||||
{
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
|
||||
{
|
||||
//write!(f, "{}", self.to_str())
|
||||
write!(f, "{}", self.get_description())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for CError
|
||||
{
|
||||
fn from(val: i32) -> CError
|
||||
{
|
||||
match val
|
||||
{
|
||||
NO_ERROR => { CError::None }
|
||||
EDOM => { CError::Domain }
|
||||
ERANGE => { CError::Range }
|
||||
EILSEQ => { CError::IllegalSequence }
|
||||
_ => { CError::Unhandled }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for CError
|
||||
{
|
||||
fn get_description(&self) -> &str
|
||||
{
|
||||
match *self
|
||||
{
|
||||
CError::None => { "There was no error" }
|
||||
CError::Domain => { "Math argument out of domain of function" }
|
||||
CError::Range => { "Math result not representable" }
|
||||
CError::IllegalSequence => { "Illegal byte sequence" }
|
||||
CError::Unhandled => { "Detected an Error not handled by CError" }
|
||||
}
|
||||
}
|
||||
|
||||
fn get_cause(&self) -> Option<&Error>
|
||||
{
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// A helper function for getting the current error.
|
||||
fn get_errno() -> i32
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
*__errno_location() as i32
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper function for setting the current error.
|
||||
fn set_errno(errnum: i32)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
*__errno_location() = errnum as CInt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// The function to get the errno memory location.
|
||||
extern
|
||||
{
|
||||
fn __errno_location() -> *mut CInt;
|
||||
}
|
@ -3,10 +3,12 @@
|
||||
//! this library is as up-to-date as it can be.
|
||||
|
||||
|
||||
mod errno;
|
||||
mod string;
|
||||
mod time;
|
||||
|
||||
|
||||
|
||||
pub use self::errno::*;
|
||||
pub use self::string::*;
|
||||
pub use self::time::*;
|
||||
|
@ -18,6 +18,8 @@ extern crate scribe;
|
||||
#[macro_use]
|
||||
extern crate binding;
|
||||
|
||||
extern crate weave;
|
||||
|
||||
|
||||
|
||||
#[cfg(not(feature="rust_lib"))]
|
||||
|
Loading…
x
Reference in New Issue
Block a user