Kaynağa Gözat

Add ctype functions and atoi/atol

Add ctype functions
  - isalnum
  - isalpha
  - isascii
  - isdigit
  - islower
  - isspace
  - isupper
Add stdlib functions
  - atoi
  - atol
Fix some warnings
Make a fmt run
Dan Robertson 7 yıl önce
ebeveyn
işleme
ec288a1b53

+ 1 - 0
Cargo.lock

@@ -453,6 +453,7 @@ name = "stdlib"
 version = "0.1.0"
 dependencies = [
  "cbindgen 0.5.0",
+ "ctype 0.1.0",
  "platform 0.1.0",
  "ralloc 1.0.0",
 ]

+ 17 - 9
src/ctype/src/lib.rs

@@ -8,17 +8,17 @@ use platform::types::*;
 
 #[no_mangle]
 pub extern "C" fn isalnum(c: c_int) -> c_int {
-    unimplemented!();
+    (isdigit(c) != 0 || isalpha(c) != 0) as c_int
 }
 
 #[no_mangle]
 pub extern "C" fn isalpha(c: c_int) -> c_int {
-    unimplemented!();
+    (islower(c) != 0 || isupper(c) != 0) as c_int
 }
 
 #[no_mangle]
 pub extern "C" fn isascii(c: c_int) -> c_int {
-    unimplemented!();
+    (!(c & !0x7f)) as c_int
 }
 
 #[no_mangle]
@@ -28,7 +28,7 @@ pub extern "C" fn iscntrl(c: c_int) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn isdigit(c: c_int) -> c_int {
-    unimplemented!();
+    (((c - 0x30) as c_uint) < 10) as c_int
 }
 
 #[no_mangle]
@@ -38,7 +38,7 @@ pub extern "C" fn isgraph(c: c_int) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn islower(c: c_int) -> c_int {
-    unimplemented!();
+    (((c - 0x61) as c_uint) < 26) as c_int
 }
 
 #[no_mangle]
@@ -53,12 +53,12 @@ pub extern "C" fn ispunct(c: c_int) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn isspace(c: c_int) -> c_int {
-    unimplemented!();
+    (c == 0x20) as c_int
 }
 
 #[no_mangle]
 pub extern "C" fn isupper(c: c_int) -> c_int {
-    unimplemented!();
+    (((c - 0x41) as c_uint) < 26) as c_int
 }
 
 #[no_mangle]
@@ -73,10 +73,18 @@ pub extern "C" fn toascii(c: c_int) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn tolower(c: c_int) -> c_int {
-    unimplemented!();
+    if isupper(c) != 0 {
+        c + 0x20
+    } else {
+        c
+    }
 }
 
 #[no_mangle]
 pub extern "C" fn toupper(c: c_int) -> c_int {
-    unimplemented!();
+    if islower(c) != 0 {
+        c - 0x20
+    } else {
+        c
+    }
 }

+ 99 - 99
src/errno/src/lib.rs

@@ -6,105 +6,105 @@ extern crate platform;
 
 use platform::types::*;
 
-pub const EPERM: c_int = 1;  /* Operation not permitted */
-pub const ENOENT: c_int = 2;  /* No such file or directory */
-pub const ESRCH: c_int = 3;  /* No such process */
-pub const EINTR: c_int = 4;  /* Interrupted system call */
-pub const EIO: c_int = 5;  /* I/O error */
-pub const ENXIO: c_int = 6;  /* No such device or address */
-pub const E2BIG: c_int = 7;  /* Argument list too long */
-pub const ENOEXEC: c_int = 8;  /* Exec format error */
-pub const EBADF: c_int = 9;  /* Bad file number */
-pub const ECHILD: c_int = 10;  /* No child processes */
-pub const EAGAIN: c_int = 11;  /* Try again */
-pub const ENOMEM: c_int = 12;  /* Out of memory */
-pub const EACCES: c_int = 13;  /* Permission denied */
-pub const EFAULT: c_int = 14;  /* Bad address */
-pub const ENOTBLK: c_int = 15;  /* Block device required */
-pub const EBUSY: c_int = 16;  /* Device or resource busy */
-pub const EEXIST: c_int = 17;  /* File exists */
-pub const EXDEV: c_int = 18;  /* Cross-device link */
-pub const ENODEV: c_int = 19;  /* No such device */
-pub const ENOTDIR: c_int = 20;  /* Not a directory */
-pub const EISDIR: c_int = 21;  /* Is a directory */
-pub const EINVAL: c_int = 22;  /* Invalid argument */
-pub const ENFILE: c_int = 23;  /* File table overflow */
-pub const EMFILE: c_int = 24;  /* Too many open files */
-pub const ENOTTY: c_int = 25;  /* Not a typewriter */
-pub const ETXTBSY: c_int = 26;  /* Text file busy */
-pub const EFBIG: c_int = 27;  /* File too large */
-pub const ENOSPC: c_int = 28;  /* No space left on device */
-pub const ESPIPE: c_int = 29;  /* Illegal seek */
-pub const EROFS: c_int = 30;  /* Read-only file system */
-pub const EMLINK: c_int = 31;  /* Too many links */
-pub const EPIPE: c_int = 32;  /* Broken pipe */
-pub const EDOM: c_int = 33;  /* Math argument out of domain of func */
-pub const ERANGE: c_int = 34;  /* Math result not representable */
-pub const EDEADLK: c_int = 35;  /* Resource deadlock would occur */
-pub const ENAMETOOLONG: c_int = 36;  /* File name too long */
-pub const ENOLCK: c_int = 37;  /* No record locks available */
-pub const ENOSYS: c_int = 38;  /* Function not implemented */
-pub const ENOTEMPTY: c_int = 39;  /* Directory not empty */
-pub const ELOOP: c_int = 40;  /* Too many symbolic links encountered */
-pub const EWOULDBLOCK: c_int = 41;  /* Operation would block */
-pub const ENOMSG: c_int = 42;  /* No message of desired type */
-pub const EIDRM: c_int = 43;  /* Identifier removed */
-pub const ECHRNG: c_int = 44;  /* Channel number out of range */
-pub const EL2NSYNC: c_int = 45;  /* Level 2 not synchronized */
-pub const EL3HLT: c_int = 46;  /* Level 3 halted */
-pub const EL3RST: c_int = 47;  /* Level 3 reset */
-pub const ELNRNG: c_int = 48;  /* Link number out of range */
-pub const EUNATCH: c_int = 49;  /* Protocol driver not attached */
-pub const ENOCSI: c_int = 50;  /* No CSI structure available */
-pub const EL2HLT: c_int = 51;  /* Level 2 halted */
-pub const EBADE: c_int = 52;  /* Invalid exchange */
-pub const EBADR: c_int = 53;  /* Invalid request descriptor */
-pub const EXFULL: c_int = 54;  /* Exchange full */
-pub const ENOANO: c_int = 55;  /* No anode */
-pub const EBADRQC: c_int = 56;  /* Invalid request code */
-pub const EBADSLT: c_int = 57;  /* Invalid slot */
+pub const EPERM: c_int = 1; /* Operation not permitted */
+pub const ENOENT: c_int = 2; /* No such file or directory */
+pub const ESRCH: c_int = 3; /* No such process */
+pub const EINTR: c_int = 4; /* Interrupted system call */
+pub const EIO: c_int = 5; /* I/O error */
+pub const ENXIO: c_int = 6; /* No such device or address */
+pub const E2BIG: c_int = 7; /* Argument list too long */
+pub const ENOEXEC: c_int = 8; /* Exec format error */
+pub const EBADF: c_int = 9; /* Bad file number */
+pub const ECHILD: c_int = 10; /* No child processes */
+pub const EAGAIN: c_int = 11; /* Try again */
+pub const ENOMEM: c_int = 12; /* Out of memory */
+pub const EACCES: c_int = 13; /* Permission denied */
+pub const EFAULT: c_int = 14; /* Bad address */
+pub const ENOTBLK: c_int = 15; /* Block device required */
+pub const EBUSY: c_int = 16; /* Device or resource busy */
+pub const EEXIST: c_int = 17; /* File exists */
+pub const EXDEV: c_int = 18; /* Cross-device link */
+pub const ENODEV: c_int = 19; /* No such device */
+pub const ENOTDIR: c_int = 20; /* Not a directory */
+pub const EISDIR: c_int = 21; /* Is a directory */
+pub const EINVAL: c_int = 22; /* Invalid argument */
+pub const ENFILE: c_int = 23; /* File table overflow */
+pub const EMFILE: c_int = 24; /* Too many open files */
+pub const ENOTTY: c_int = 25; /* Not a typewriter */
+pub const ETXTBSY: c_int = 26; /* Text file busy */
+pub const EFBIG: c_int = 27; /* File too large */
+pub const ENOSPC: c_int = 28; /* No space left on device */
+pub const ESPIPE: c_int = 29; /* Illegal seek */
+pub const EROFS: c_int = 30; /* Read-only file system */
+pub const EMLINK: c_int = 31; /* Too many links */
+pub const EPIPE: c_int = 32; /* Broken pipe */
+pub const EDOM: c_int = 33; /* Math argument out of domain of func */
+pub const ERANGE: c_int = 34; /* Math result not representable */
+pub const EDEADLK: c_int = 35; /* Resource deadlock would occur */
+pub const ENAMETOOLONG: c_int = 36; /* File name too long */
+pub const ENOLCK: c_int = 37; /* No record locks available */
+pub const ENOSYS: c_int = 38; /* Function not implemented */
+pub const ENOTEMPTY: c_int = 39; /* Directory not empty */
+pub const ELOOP: c_int = 40; /* Too many symbolic links encountered */
+pub const EWOULDBLOCK: c_int = 41; /* Operation would block */
+pub const ENOMSG: c_int = 42; /* No message of desired type */
+pub const EIDRM: c_int = 43; /* Identifier removed */
+pub const ECHRNG: c_int = 44; /* Channel number out of range */
+pub const EL2NSYNC: c_int = 45; /* Level 2 not synchronized */
+pub const EL3HLT: c_int = 46; /* Level 3 halted */
+pub const EL3RST: c_int = 47; /* Level 3 reset */
+pub const ELNRNG: c_int = 48; /* Link number out of range */
+pub const EUNATCH: c_int = 49; /* Protocol driver not attached */
+pub const ENOCSI: c_int = 50; /* No CSI structure available */
+pub const EL2HLT: c_int = 51; /* Level 2 halted */
+pub const EBADE: c_int = 52; /* Invalid exchange */
+pub const EBADR: c_int = 53; /* Invalid request descriptor */
+pub const EXFULL: c_int = 54; /* Exchange full */
+pub const ENOANO: c_int = 55; /* No anode */
+pub const EBADRQC: c_int = 56; /* Invalid request code */
+pub const EBADSLT: c_int = 57; /* Invalid slot */
 pub const EDEADLOCK: c_int = 58; /* Resource deadlock would occur */
-pub const EBFONT: c_int = 59;  /* Bad font file format */
-pub const ENOSTR: c_int = 60;  /* Device not a stream */
-pub const ENODATA: c_int = 61;  /* No data available */
-pub const ETIME: c_int = 62;  /* Timer expired */
-pub const ENOSR: c_int = 63;  /* Out of streams resources */
-pub const ENONET: c_int = 64;  /* Machine is not on the network */
-pub const ENOPKG: c_int = 65;  /* Package not installed */
-pub const EREMOTE: c_int = 66;  /* Object is remote */
-pub const ENOLINK: c_int = 67;  /* Link has been severed */
-pub const EADV: c_int = 68;  /* Advertise error */
-pub const ESRMNT: c_int = 69;  /* Srmount error */
-pub const ECOMM: c_int = 70;  /* Communication error on send */
-pub const EPROTO: c_int = 71;  /* Protocol error */
-pub const EMULTIHOP: c_int = 72;  /* Multihop attempted */
-pub const EDOTDOT: c_int = 73;  /* RFS specific error */
-pub const EBADMSG: c_int = 74;  /* Not a data message */
-pub const EOVERFLOW: c_int = 75;  /* Value too large for defined data type */
-pub const ENOTUNIQ: c_int = 76;  /* Name not unique on network */
-pub const EBADFD: c_int = 77;  /* File descriptor in bad state */
-pub const EREMCHG: c_int = 78;  /* Remote address changed */
-pub const ELIBACC: c_int = 79;  /* Can not access a needed shared library */
-pub const ELIBBAD: c_int = 80;  /* Accessing a corrupted shared library */
-pub const ELIBSCN: c_int = 81;  /* .lib section in a.out corrupted */
-pub const ELIBMAX: c_int = 82;  /* Attempting to link in too many shared libraries */
-pub const ELIBEXEC: c_int = 83;  /* Cannot exec a shared library directly */
-pub const EILSEQ: c_int = 84;  /* Illegal byte sequence */
-pub const ERESTART: c_int = 85;  /* Interrupted system call should be restarted */
-pub const ESTRPIPE: c_int = 86;  /* Streams pipe error */
-pub const EUSERS: c_int = 87;  /* Too many users */
-pub const ENOTSOCK: c_int = 88;  /* Socket operation on non-socket */
-pub const EDESTADDRREQ: c_int = 89;  /* Destination address required */
-pub const EMSGSIZE: c_int = 90;  /* Message too long */
-pub const EPROTOTYPE: c_int = 91;  /* Protocol wrong type for socket */
-pub const ENOPROTOOPT: c_int = 92;  /* Protocol not available */
-pub const EPROTONOSUPPORT: c_int = 93;  /* Protocol not supported */
-pub const ESOCKTNOSUPPORT: c_int = 94;  /* Socket type not supported */
-pub const EOPNOTSUPP: c_int = 95;  /* Operation not supported on transport endpoint */
-pub const EPFNOSUPPORT: c_int = 96;  /* Protocol family not supported */
-pub const EAFNOSUPPORT: c_int = 97;  /* Address family not supported by protocol */
-pub const EADDRINUSE: c_int = 98;  /* Address already in use */
-pub const EADDRNOTAVAIL: c_int = 99;  /* Cannot assign requested address */
+pub const EBFONT: c_int = 59; /* Bad font file format */
+pub const ENOSTR: c_int = 60; /* Device not a stream */
+pub const ENODATA: c_int = 61; /* No data available */
+pub const ETIME: c_int = 62; /* Timer expired */
+pub const ENOSR: c_int = 63; /* Out of streams resources */
+pub const ENONET: c_int = 64; /* Machine is not on the network */
+pub const ENOPKG: c_int = 65; /* Package not installed */
+pub const EREMOTE: c_int = 66; /* Object is remote */
+pub const ENOLINK: c_int = 67; /* Link has been severed */
+pub const EADV: c_int = 68; /* Advertise error */
+pub const ESRMNT: c_int = 69; /* Srmount error */
+pub const ECOMM: c_int = 70; /* Communication error on send */
+pub const EPROTO: c_int = 71; /* Protocol error */
+pub const EMULTIHOP: c_int = 72; /* Multihop attempted */
+pub const EDOTDOT: c_int = 73; /* RFS specific error */
+pub const EBADMSG: c_int = 74; /* Not a data message */
+pub const EOVERFLOW: c_int = 75; /* Value too large for defined data type */
+pub const ENOTUNIQ: c_int = 76; /* Name not unique on network */
+pub const EBADFD: c_int = 77; /* File descriptor in bad state */
+pub const EREMCHG: c_int = 78; /* Remote address changed */
+pub const ELIBACC: c_int = 79; /* Can not access a needed shared library */
+pub const ELIBBAD: c_int = 80; /* Accessing a corrupted shared library */
+pub const ELIBSCN: c_int = 81; /* .lib section in a.out corrupted */
+pub const ELIBMAX: c_int = 82; /* Attempting to link in too many shared libraries */
+pub const ELIBEXEC: c_int = 83; /* Cannot exec a shared library directly */
+pub const EILSEQ: c_int = 84; /* Illegal byte sequence */
+pub const ERESTART: c_int = 85; /* Interrupted system call should be restarted */
+pub const ESTRPIPE: c_int = 86; /* Streams pipe error */
+pub const EUSERS: c_int = 87; /* Too many users */
+pub const ENOTSOCK: c_int = 88; /* Socket operation on non-socket */
+pub const EDESTADDRREQ: c_int = 89; /* Destination address required */
+pub const EMSGSIZE: c_int = 90; /* Message too long */
+pub const EPROTOTYPE: c_int = 91; /* Protocol wrong type for socket */
+pub const ENOPROTOOPT: c_int = 92; /* Protocol not available */
+pub const EPROTONOSUPPORT: c_int = 93; /* Protocol not supported */
+pub const ESOCKTNOSUPPORT: c_int = 94; /* Socket type not supported */
+pub const EOPNOTSUPP: c_int = 95; /* Operation not supported on transport endpoint */
+pub const EPFNOSUPPORT: c_int = 96; /* Protocol family not supported */
+pub const EAFNOSUPPORT: c_int = 97; /* Address family not supported by protocol */
+pub const EADDRINUSE: c_int = 98; /* Address already in use */
+pub const EADDRNOTAVAIL: c_int = 99; /* Cannot assign requested address */
 pub const ENETDOWN: c_int = 100; /* Network is down */
 pub const ENETUNREACH: c_int = 101; /* Network is unreachable */
 pub const ENETRESET: c_int = 102; /* Network dropped connection because of reset */
@@ -270,5 +270,5 @@ pub static STR_ERROR: [&'static str; 132] = [
     "Key has been revoked",
     "Key was rejected by service",
     "Owner died",
-    "State not recoverable"
+    "State not recoverable",
 ];

+ 1 - 0
src/platform/src/lib.rs

@@ -29,6 +29,7 @@ use core::fmt;
 use types::*;
 
 //TODO #[thread_local]
+#[allow(non_upper_case_globals)]
 #[no_mangle]
 pub static mut errno: c_int = 0;
 

+ 2 - 0
src/stdio/src/lib.rs

@@ -20,9 +20,11 @@ pub type fpos_t = off_t;
 
 pub struct FILE;
 
+#[allow(non_upper_case_globals)]
 #[no_mangle]
 pub static mut stdout: *mut FILE = 1 as *mut FILE;
 
+#[allow(non_upper_case_globals)]
 #[no_mangle]
 pub static mut stderr: *mut FILE = 2 as *mut FILE;
 

+ 1 - 0
src/stdlib/Cargo.toml

@@ -10,3 +10,4 @@ cbindgen = { path = "../../cbindgen" }
 [dependencies]
 platform = { path = "../platform" }
 ralloc = { path = "../../ralloc", default-features = false }
+ctype = { path = "../ctype" }

+ 41 - 4
src/stdlib/src/lib.rs

@@ -4,6 +4,7 @@
 #![feature(core_intrinsics)]
 #![feature(global_allocator)]
 
+extern crate ctype;
 extern crate platform;
 extern crate ralloc;
 
@@ -55,14 +56,52 @@ pub extern "C" fn atof(s: *const c_char) -> c_double {
     unimplemented!();
 }
 
+macro_rules! dec_num_from_ascii {
+    ($s: expr, $t: ty) => {
+        unsafe {
+            let mut s = $s;
+            // Iterate past whitespace
+            while ctype::isspace(*s as c_int) != 0 {
+                s = s.offset(1);
+            }
+
+            // Find out if there is a - sign
+            let neg_sign = match *s {
+                0x2d => {
+                    s = s.offset(1);
+                    true
+                }
+                // '+' increment s and continue parsing
+                0x2b => {
+                    s = s.offset(1);
+                    false
+                }
+                _ => false,
+            };
+
+            let mut n: $t = 0;
+            while ctype::isdigit(*s as c_int) != 0 {
+                n = 10 * n - (*s as $t - 0x30);
+                s = s.offset(1);
+            }
+
+            if neg_sign {
+                n
+            } else {
+                -n
+            }
+        }
+    };
+}
+
 #[no_mangle]
 pub extern "C" fn atoi(s: *const c_char) -> c_int {
-    unimplemented!();
+    dec_num_from_ascii!(s, c_int)
 }
 
 #[no_mangle]
 pub extern "C" fn atol(s: *const c_char) -> c_long {
-    unimplemented!();
+    dec_num_from_ascii!(s, c_long)
 }
 
 #[no_mangle]
@@ -124,8 +163,6 @@ pub extern "C" fn erand(xsubi: [c_ushort; 3]) -> c_double {
 
 #[no_mangle]
 pub unsafe extern "C" fn exit(status: c_int) {
-    use core::mem;
-
     for i in (0..ATEXIT_FUNCS.len()).rev() {
         if let Some(func) = ATEXIT_FUNCS[i] {
             (func)();

+ 2 - 0
tests/.gitignore

@@ -1,9 +1,11 @@
 /alloc
 /args
+/atoi
 /brk
 /chdir
 /create
 /create.out
+/ctype
 /dup
 /dup.out
 /error

+ 2 - 0
tests/Makefile

@@ -1,9 +1,11 @@
 BINS=\
 	alloc \
+	atoi \
 	brk \
 	args \
 	chdir \
 	create \
+	ctype \
 	dup \
 	error \
 	fchdir \

+ 12 - 0
tests/atoi.c

@@ -0,0 +1,12 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+int main(int argc, char* argv[]) {
+    printf("%d\n", atoi("         -42"));
+    printf("%d\n", atoi(" +555"));
+    printf("%d\n", atoi("   1234567890    "));
+    printf("%ld\n", atol("         -42"));
+    printf("%ld\n", atol(" +555"));
+    printf("%ld\n", atol("   1234567890    "));
+    return 0;
+}

+ 46 - 0
tests/ctype.c

@@ -0,0 +1,46 @@
+#include <ctype.h>
+#include <stdio.h>
+
+struct test_case {
+    char c;
+    int isalnum;
+    int isalpha;
+    int isascii;
+    int isdigit;
+    int islower;
+    int isspace;
+    int isupper;
+} test_cases[] = {
+    { 'A', 1, 1, 1, 0, 0, 0, 1},
+    { 'z', 1, 1, 1, 0, 1, 0, 0},
+    { ' ', 0, 0, 1, 0, 0, 1, 0},
+    { '1', 1, 0, 1, 1, 0, 0, 0},
+    { '9', 1, 0, 1, 1, 0, 0, 0},
+    {0x80, 0, 0, 0, 0, 0, 0, 0}
+};
+size_t num_test_cases = sizeof(test_cases)/sizeof(struct test_case);
+
+#define CHECK_TEST(tc, fn, retval) \
+    if (fn(tc.c) != tc.fn) { \
+        retval = -1; \
+        printf("Unexpected result: " #fn "('%c') != %d\n", tc.c, tc.fn); \
+    }
+int main(int argc, char* argv[]) {
+    int retval = 0;
+    for(int i = 0; i < num_test_cases; ++i) {
+        struct test_case tc = test_cases[i];
+        CHECK_TEST(tc, isalnum, retval);
+        CHECK_TEST(tc, isalpha, retval);
+        CHECK_TEST(tc, isascii, retval);
+        CHECK_TEST(tc, isdigit, retval);
+        CHECK_TEST(tc, islower, retval);
+        CHECK_TEST(tc, isspace, retval);
+        CHECK_TEST(tc, isupper, retval);
+    }
+    if (!retval) {
+        printf("Success: %d\n", retval);
+    } else {
+        printf("Failure: %d\n", retval);
+    }
+    return retval;
+}