diff --git a/.gitignore b/.gitignore index b83d22266ac8aa2f8df2edef68082c789727841d..431845ed05927f3a23c9b23d4ae3d7a2626dd668 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target/ +.idea/ diff --git a/.travis.yml b/.travis.yml index 15083598be4e0726fba9aa4840687cef44533d82..6fd8524c7700b6135599834c4beed11ee3d2a348 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,17 @@ language: rust +env: + - + - TARGET=aarch64-unknown-linux-gnu + - TARGET=x86_64-unknown-redox rust: - nightly cache: cargo before_script: - rustup component add rustfmt-preview - - rustup target add x86_64-unknown-redox - - rustup target add aarch64-unknown-linux-gnu + - if [ -n "$TARGET" ]; then rustup target add $TARGET; fi script: - - bash ./ci.sh + - ./fmt.sh -- --write-mode=diff + - cargo build $([ -n "$TARGET" ] && echo --target="$TARGET") + - if [ -z "$TARGET" ]; then ./test.sh; fi notifications: email: false diff --git a/Cargo.lock b/Cargo.lock index 224eaaa31cdbea9180878fde3e90fa4e3b122b5d..b69becf5443ba5bfc82ef60de2acc639d5ccb7b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -139,6 +139,14 @@ dependencies = [ "platform 0.1.0", ] +[[package]] +name = "in_h" +version = "0.1.0" +dependencies = [ + "cbindgen 0.5.2", + "platform 0.1.0", +] + [[package]] name = "itoa" version = "0.3.4" @@ -182,6 +190,13 @@ dependencies = [ "platform 0.1.0", ] +[[package]] +name = "netinet" +version = "0.1.0" +dependencies = [ + "in_h 0.1.0", +] + [[package]] name = "num-traits" version = "0.2.1" @@ -259,10 +274,12 @@ dependencies = [ "float 0.1.0", "grp 0.1.0", "mman 0.1.0", + "netinet 0.1.0", "platform 0.1.0", "resource 0.1.0", "semaphore 0.1.0", "signal 0.1.0", + "socket 0.1.0", "stat 0.1.0", "stdio 0.1.0", "stdlib 0.1.0", @@ -351,6 +368,14 @@ dependencies = [ "platform 0.1.0", ] +[[package]] +name = "socket" +version = "0.1.0" +dependencies = [ + "cbindgen 0.5.2", + "platform 0.1.0", +] + [[package]] name = "standalone-quote" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index ffd5eea4ec7497341ebdb38d40dc67f919b115d4..42b6f836216ebcedcd8e765be556f0231fb87f95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,10 +19,12 @@ fenv = { path = "src/fenv" } float = { path = "src/float" } grp = { path = "src/grp" } mman = { path = "src/mman" } +netinet = { path = "src/netinet" } platform = { path = "src/platform" } resource = { path = "src/resource" } semaphore = { path = "src/semaphore" } signal = { path = "src/signal" } +socket = { path = "src/socket" } stat = { path = "src/stat" } stdio = { path = "src/stdio" } stdlib = { path = "src/stdlib" } diff --git a/ci.sh b/ci.sh deleted file mode 100755 index fd7dd91a480ac2b1f8ee9d3230b3210b3367440d..0000000000000000000000000000000000000000 --- a/ci.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -ex - -./fmt.sh -- --write-mode=diff -./test.sh -cargo build --target=x86_64-unknown-redox -if [ $(arch) == "x86_64" ] -then - cargo build --target=aarch64-unknown-linux-gnu -else - cargo build --target=x86_64-unknown-linux-gnu -fi diff --git a/src/lib.rs b/src/lib.rs index a2589ae7954e34050a55f4d29a63d6e4135dc36f..6e584d30b803b72cecabce7f8dc0ccd924c14b1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,8 +11,10 @@ extern crate fenv; extern crate float; extern crate grp; extern crate mman; +extern crate netinet; extern crate resource; extern crate semaphore; +extern crate socket; extern crate stat; extern crate stdio; extern crate stdlib; diff --git a/src/netinet/Cargo.toml b/src/netinet/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..eccbe4ee946f16f08bdc0199b9f56eddae72f4e6 --- /dev/null +++ b/src/netinet/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "netinet" +version = "0.1.0" +authors = ["Dan Robertson <danlrobertson89@gmail.com>"] + +[dependencies] +in_h = { path = "in" } diff --git a/src/netinet/in/Cargo.toml b/src/netinet/in/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..4bd5518ba25d7b3200171f5777861d8f1fd56353 --- /dev/null +++ b/src/netinet/in/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "in_h" +version = "0.1.0" +authors = ["Dan Robertson <danlrobertson89@gmail.com>"] +build = "build.rs" + +[build-dependencies] +cbindgen = { path = "../../../cbindgen" } + +[dependencies] +platform = { path = "../../platform" } +socket = { path = "../../socket" } diff --git a/src/netinet/in/build.rs b/src/netinet/in/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..f9df3f1a781856bd52f511d854dc728929e80483 --- /dev/null +++ b/src/netinet/in/build.rs @@ -0,0 +1,12 @@ +extern crate cbindgen; + +use std::{env, fs}; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); + fs::create_dir_all("../../../target/include").expect("failed to create include directory"); + fs::create_dir_all("../../../target/include/netinet").expect("failed to create include directory"); + cbindgen::generate(crate_dir) + .expect("failed to generate bindings") + .write_to_file("../../../target/include/netinet/in.h"); +} diff --git a/src/netinet/in/cbindgen.toml b/src/netinet/in/cbindgen.toml new file mode 100644 index 0000000000000000000000000000000000000000..0067295d34e11baab150431dfa4dc8246bb5a541 --- /dev/null +++ b/src/netinet/in/cbindgen.toml @@ -0,0 +1,10 @@ +sys_includes = ["sys/types.h", "sys/socket.h"] +include_guard = "_NETINET_IN_H" +style = "Tag" +language = "C" + +[export] +include = ["sockaddr_in6", "sockaddr_in", "ipv6_mreq"] + +[enum] +prefix_with_name = true diff --git a/src/netinet/in/src/lib.rs b/src/netinet/in/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..789a9e4b4b02309951b05a7ce0da7863dbd7f791 --- /dev/null +++ b/src/netinet/in/src/lib.rs @@ -0,0 +1,58 @@ +#![no_std] + +#![allow(non_camel_case_types)] + +extern crate platform; +extern crate socket; + +use platform::types::*; +use socket::sa_family_t; + +pub type in_addr_t = u32; +pub type in_port_t = u16; + +#[repr(C)] +#[derive(Debug)] +pub struct in_addr { + pub s_addr: in_addr_t +} + +#[repr(C)] +pub struct in6_addr { + pub s6_addr: [u8; 16] +} + +#[repr(C)] +pub struct sockaddr_in { + pub sa_family: sa_family_t, + pub sin_port: in_port_t, + pub sin_addr: in_addr +} + +#[repr(C)] +pub struct sockaddr_in6 { + pub sin6_family: sa_family_t, + pub sin6_port: in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: in6_addr, + pub sin6_scope_id: u32 +} + +#[repr(C)] +pub struct ipv6_mreq { + pub ipv6mr_multiaddr: in6_addr, + pub ipv6mr_interface: u32, +} + +// Address String Lengths +pub const INET_ADDRSTRLEN: c_int = 16; +pub const INET6_ADDRSTRLEN: c_int = 46; + +// Protocol Numbers +pub const IPPROTO_IP: u8 = 0x00; +pub const IPPROTO_ICMP: u8 = 0x01; +pub const IPPROTO_TCP: u8 = 0x06; +pub const IPPROTO_UDP: u8 = 0x11; +pub const IPPROTO_IPV6: u8 = 0x29; +pub const IPPROTO_RAW: u8 = 0xff; +pub const IPPROTO_MAX: u8 = 0xff; diff --git a/src/netinet/src/lib.rs b/src/netinet/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..40de25ffa28c14860ecd6c0810bc3bdefef45359 --- /dev/null +++ b/src/netinet/src/lib.rs @@ -0,0 +1,3 @@ +#![no_std] + +extern crate in_h; diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs index a183c42fa703c23bcf1c79e027161acc7f0e5b98..3e03bbde9005b19ce4cec9c9bc2835b0975ba24e 100644 --- a/src/platform/src/redox/mod.rs +++ b/src/platform/src/redox/mod.rs @@ -146,27 +146,23 @@ pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int { } pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int { - unsafe { - let redox_rqtp = redox_timespec { - tv_sec: (*rqtp).tv_sec, - tv_nsec: (*rqtp).tv_nsec as i32, - }; - let mut redox_rmtp: redox_timespec; - if rmtp.is_null() { - redox_rmtp = redox_timespec::default(); - } else { - redox_rmtp = redox_timespec { - tv_sec: (*rmtp).tv_sec, - tv_nsec: (*rmtp).tv_nsec as i32, - }; - } - match e(syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)) as c_int { - -1 => -1, - _ => { - (*rmtp).tv_sec = redox_rmtp.tv_sec; - (*rmtp).tv_nsec = redox_rmtp.tv_nsec as i64; - 0 + let redox_rqtp = unsafe { redox_timespec::from(&*rqtp) }; + let mut redox_rmtp: redox_timespec; + if rmtp.is_null() { + redox_rmtp = redox_timespec::default(); + } else { + redox_rmtp = unsafe { redox_timespec::from(&*rmtp) }; + } + match e(syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)) as c_int { + -1 => -1, + _ => { + unsafe { + if !rmtp.is_null() { + (*rmtp).tv_sec = redox_rmtp.tv_sec; + (*rmtp).tv_nsec = redox_rmtp.tv_nsec as i64; + } } + 0 } } } diff --git a/src/platform/src/types.rs b/src/platform/src/types.rs index 9268bf55c319265d6cd424479ae4394720993799..d6e19dbd580c8ad2b5bbbe1934cacabacc1bfc22 100644 --- a/src/platform/src/types.rs +++ b/src/platform/src/types.rs @@ -1,3 +1,5 @@ +#[cfg(target_os = "redox")] +use syscall::data::TimeSpec as redox_timespec; // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help enable // more optimization opportunities around it recognizing things like // malloc/free. @@ -70,3 +72,13 @@ pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } + +#[cfg(target_os = "redox")] +impl<'a> From<&'a timespec> for redox_timespec { + fn from(tp: ×pec) -> redox_timespec { + redox_timespec { + tv_sec: tp.tv_sec, + tv_nsec: tp.tv_nsec as i32, + } + } +} diff --git a/src/socket/Cargo.toml b/src/socket/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..12801f04aa3576e1aa1d6df54a575dfc5f4b94d3 --- /dev/null +++ b/src/socket/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "socket" +version = "0.1.0" +authors = ["Dan Robertson <danlrobertson89@gmail.com>"] +build = "build.rs" + +[build-dependencies] +cbindgen = { path = "../../cbindgen" } + +[dependencies] +platform = { path = "../platform" } diff --git a/src/socket/build.rs b/src/socket/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..ad891ecb68eb3bbc69e6a63579c2f9770976317b --- /dev/null +++ b/src/socket/build.rs @@ -0,0 +1,11 @@ +extern crate cbindgen; + +use std::{env, fs}; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); + fs::create_dir_all("../../target/include").expect("failed to create include directory"); + cbindgen::generate(crate_dir) + .expect("failed to generate bindings") + .write_to_file("../../target/include/sys/socket.h"); +} diff --git a/src/socket/cbindgen.toml b/src/socket/cbindgen.toml new file mode 100644 index 0000000000000000000000000000000000000000..fc968ead013d2be8ce589680553bb382e82309a9 --- /dev/null +++ b/src/socket/cbindgen.toml @@ -0,0 +1,11 @@ +sys_includes = ["sys/types.h"] +include_guard = "_SYS_SOCKET_H" +style = "Tag" +language = "C" + +[defines] +"target_os=linux" = "__linux__" +"target_os=redox" = "__redox__" + +[enum] +prefix_with_name = true diff --git a/src/socket/src/lib.rs b/src/socket/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..c7c0b5f2bca242700e727bab1645ff7853dd6ecd --- /dev/null +++ b/src/socket/src/lib.rs @@ -0,0 +1,153 @@ +//! socket implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xns/syssocket.h.html + +#![no_std] +#![allow(non_camel_case_types)] + +extern crate platform; + +use platform::types::*; + +pub type sa_family_t = u16; +pub type socklen_t = u32; + +#[repr(C)] +pub struct sockaddr { + pub sa_family: sa_family_t, + pub sa_data: [c_char; 14], +} + +#[no_mangle] +pub unsafe extern "C" fn accept( + socket: c_int, + address: *mut sockaddr, + address_len: *mut socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn bind( + socket: c_int, + address: *const sockaddr, + address_len: socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn connect( + socket: c_int, + address: *const sockaddr, + address_len: socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn getpeername( + socket: c_int, + address: *const sockaddr, + address_len: socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn getsockname( + socket: c_int, + address: *mut sockaddr, + address_len: *mut socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn getsockopt( + socket: c_int, + level: c_int, + option_name: c_int, + option_value: *mut c_void, + option_len: *mut socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn listen(socket: c_int, backlog: c_int) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn recv( + socket: c_int, + buffer: *mut c_void, + length: size_t, + flags: c_int, +) -> ssize_t { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn recvfrom( + socket: c_int, + buffer: *mut c_void, + length: size_t, + flags: c_int, + address: *mut sockaddr, + address_len: *mut socklen_t, +) -> ssize_t { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn send( + socket: c_int, + message: *const c_void, + length: size_t, + flags: c_int, +) -> ssize_t { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn sento( + socket: c_int, + message: *const c_void, + length: size_t, + flags: c_int, + dest_addr: *const sockaddr, + dest_len: socklen_t, +) -> ssize_t { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn setsockopt( + socket: c_int, + level: c_int, + option_name: c_int, + option_value: *const c_void, + option_len: socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn shutdown(socket: c_int, how: c_int) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn socket(domain: c_int, _type: c_int, protocol: c_int) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn socketpair( + domain: c_int, + _type: c_int, + protocol: c_int, + socket_vector: [c_int; 2], +) -> c_int { + unimplemented!(); +} diff --git a/src/stdlib/src/lib.rs b/src/stdlib/src/lib.rs index 7813b9bdc953c45e9a8a8a173f130f6022c95d4a..575f759a264f4eb6624c2577be08145114bbac14 100644 --- a/src/stdlib/src/lib.rs +++ b/src/stdlib/src/lib.rs @@ -130,15 +130,33 @@ pub extern "C" fn atol(s: *const c_char) -> c_long { dec_num_from_ascii!(s, c_long) } +unsafe extern "C" fn void_cmp(a: *const c_void, b: *const c_void) -> c_int { + return *(a as *const i32) - *(b as *const i32) as c_int; +} + #[no_mangle] -pub extern "C" fn bsearch( +pub unsafe extern "C" fn bsearch( key: *const c_void, base: *const c_void, nel: size_t, width: size_t, - compar: Option<extern "C" fn(*const c_void, *const c_void) -> c_int>, + compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>, ) -> *mut c_void { - unimplemented!(); + let mut start = base; + let mut len = nel; + let cmp_fn = compar.unwrap_or(void_cmp); + while len > 0 { + let med = (start as size_t + (len >> 1) * width) as *const c_void; + let diff = cmp_fn(key, med); + if diff == 0 { + return med as *mut c_void; + } else if diff > 0 { + start = (med as usize + width) as *const c_void; + len -= 1; + } + len >>= 1; + } + ptr::null_mut() } #[no_mangle] diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index 49bfe11be989518b266ec96e7942e38a3c819ad2..c97302b92bf44cefacf6f081c32275c5dc8ecb70 100644 --- a/src/string/src/lib.rs +++ b/src/string/src/lib.rs @@ -323,17 +323,49 @@ pub unsafe extern "C" fn strstr(s1: *const c_char, s2: *const c_char) -> *mut c_ } #[no_mangle] -pub extern "C" fn strtok(s1: *mut c_char, s2: *const c_char) -> *mut c_char { - unimplemented!(); +pub extern "C" fn strtok(s1: *mut c_char, delimiter: *const c_char) -> *mut c_char { + static mut HAYSTACK: *mut c_char = ptr::null_mut(); + unsafe { + return strtok_r(s1, delimiter, &mut HAYSTACK); + } } #[no_mangle] pub extern "C" fn strtok_r( s: *mut c_char, - sep: *const c_char, + delimiter: *const c_char, lasts: *mut *mut c_char, ) -> *mut c_char { - unimplemented!(); + // Loosely based on GLIBC implementation + unsafe { + let mut haystack = s; + if haystack.is_null() { + if (*lasts).is_null() { + return ptr::null_mut(); + } + haystack = *lasts; + } + + // Skip past any extra delimiter left over from previous call + haystack = haystack.add(strspn(haystack, delimiter)); + if *haystack == 0 { + *lasts = ptr::null_mut(); + return ptr::null_mut(); + } + + // Build token by injecting null byte into delimiter + let token = haystack; + haystack = strpbrk(token, delimiter); + if !haystack.is_null() { + haystack.write(0); + haystack = haystack.add(1); + *lasts = haystack; + } else { + *lasts = ptr::null_mut(); + } + + return token; + } } #[no_mangle] diff --git a/tests/.gitignore b/tests/.gitignore index 685d52e548000dea037e8637e02dbb1a634eb524..9d10cf8d9dacf5688c49091371051e3be52bea5f 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -26,6 +26,7 @@ /rmdir /setid /sprintf +/stdlib/bsearch /stdlib/strtol /stdlib/a64l /stdio/fwrite diff --git a/tests/Makefile b/tests/Makefile index 120530f22ee9541172f25a62f0d705ca9b1feaeb..c7214961583a1e6e72f2a7206d703a553a947f0c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -25,6 +25,7 @@ EXPECT_BINS=\ stdio/fwrite \ stdio/all \ stdio/freopen \ + stdlib/bsearch \ stdlib/strtol \ stdlib/a64l \ string/strncmp \ @@ -34,6 +35,8 @@ EXPECT_BINS=\ string/strspn \ string/strstr \ string/strpbrk \ + string/strtok \ + string/strtok_r \ unlink \ waitpid \ write diff --git a/tests/expected/string/strtok.stderr b/tests/expected/string/strtok.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/string/strtok.stdout b/tests/expected/string/strtok.stdout new file mode 100644 index 0000000000000000000000000000000000000000..201357e8cbf62d9b06cde1d92cb068ae08b42c89 --- /dev/null +++ b/tests/expected/string/strtok.stdout @@ -0,0 +1,2 @@ +I'd_just_like_to_interject_for_a_moment.__What_you're_referring_to_as_Linux, +is_in_fact,_GNU/Linux,_or_as_I've_recently_taken_to_calling_it,_GNU_plus_Linux. diff --git a/tests/expected/string/strtok_r.stderr b/tests/expected/string/strtok_r.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/string/strtok_r.stdout b/tests/expected/string/strtok_r.stdout new file mode 100644 index 0000000000000000000000000000000000000000..201357e8cbf62d9b06cde1d92cb068ae08b42c89 --- /dev/null +++ b/tests/expected/string/strtok_r.stdout @@ -0,0 +1,2 @@ +I'd_just_like_to_interject_for_a_moment.__What_you're_referring_to_as_Linux, +is_in_fact,_GNU/Linux,_or_as_I've_recently_taken_to_calling_it,_GNU_plus_Linux. diff --git a/tests/stdlib/bsearch.c b/tests/stdlib/bsearch.c new file mode 100644 index 0000000000000000000000000000000000000000..efe8d46521278021be48e6574e1e120e4d834cc7 --- /dev/null +++ b/tests/stdlib/bsearch.c @@ -0,0 +1,55 @@ +#include <stdlib.h> +#include <stdio.h> + +int int_cmp(const void* a, const void* b) { + return *(const int*) a - *(const int*) b; +} + +#define BSEARCH_TEST_INT(key, arr, len, expect) \ + do { \ + void* res = bsearch((const void*) &key, (void*) arr, len, sizeof(int), int_cmp); \ + if (res != expect) { \ + printf("FAIL bsearch for %d in [", key); \ + size_t i = 0; \ + for (; i < len; ++i) printf("%d,", arr[i]); \ + printf("] expected %p but got %p\n", (void*) expect, res); \ + return 1; \ + } \ + } while (0); + + + +int main(int argc, char* argv[]) { + int x = 0; + int y = 1024; + int empty[] = {}; + BSEARCH_TEST_INT(x, empty, 0, NULL); + + int singleton[] = {42}; + printf("%p\n%p\n", singleton, &singleton[1]); + BSEARCH_TEST_INT(x, singleton, 1, NULL); + BSEARCH_TEST_INT(singleton[0], singleton, 1, &singleton[0]); + BSEARCH_TEST_INT(y, singleton, 1, NULL); + + int two[] = {14, 42}; + BSEARCH_TEST_INT(x, two, 2, NULL); + BSEARCH_TEST_INT(y, two, 2, NULL); + BSEARCH_TEST_INT(two[0], two, 2, &two[0]); + BSEARCH_TEST_INT(two[0], two, 1, &two[0]); + BSEARCH_TEST_INT(two[1], two, 2, &two[1]); + BSEARCH_TEST_INT(two[1], two, 1, NULL); + + int three[] = {-5, -1, 4}; + BSEARCH_TEST_INT(three[0], three, 3, &three[0]); + BSEARCH_TEST_INT(three[1], three, 3, &three[1]); + BSEARCH_TEST_INT(three[2], three, 3, &three[2]); + + int big[] = {-19, -13, -7, -3, 2, 5, 11}; + BSEARCH_TEST_INT(big[0], big, 7, big); + BSEARCH_TEST_INT(big[6], big, 7, &big[6]); + BSEARCH_TEST_INT(big[3], big, 7, &big[3]); + BSEARCH_TEST_INT(x, big, 7, NULL); + + printf("PASS bsearch\n"); + return 0; +} diff --git a/tests/string/strtok.c b/tests/string/strtok.c new file mode 100644 index 0000000000000000000000000000000000000000..9809fdf054f4ca51c77a657e3d30e86af60d5ace --- /dev/null +++ b/tests/string/strtok.c @@ -0,0 +1,17 @@ +#include <string.h> +#include <stdio.h> + +int main(int argc, char* argv[]) { + char source[] = "I'd just like to interject for a moment. What you're referring to as Linux, " + "is in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus Linux.\n"; + + char* token = strtok(source, " "); + while (token) { + printf("%s", token); + if (token = strtok(NULL, " ")) { + printf("_"); + } + } + + return 0; +} diff --git a/tests/string/strtok_r.c b/tests/string/strtok_r.c new file mode 100644 index 0000000000000000000000000000000000000000..36becfe2969093dcd80246a1dcef0b03a0892770 --- /dev/null +++ b/tests/string/strtok_r.c @@ -0,0 +1,18 @@ +#include <string.h> +#include <stdio.h> + +int main(int argc, char* argv[]) { + char source[] = "I'd just like to interject for a moment. What you're referring to as Linux, " + "is in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus Linux.\n"; + char* sp; + + char* token = strtok_r(source, " ", &sp); + while (token) { + printf("%s", token); + if (token = strtok_r(NULL, " ", &sp)) { + printf("_"); + } + } + + return 0; +}