lib.rs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. //! stdlib implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdlib.h.html
  2. #![no_std]
  3. #![feature(core_intrinsics)]
  4. extern crate ctype;
  5. extern crate errno;
  6. extern crate fcntl;
  7. extern crate platform;
  8. extern crate rand;
  9. extern crate string;
  10. extern crate time;
  11. extern crate unistd;
  12. extern crate wchar;
  13. use core::{ptr, slice, str};
  14. use rand::distributions::Alphanumeric;
  15. use rand::prng::XorShiftRng;
  16. use rand::rngs::JitterRng;
  17. use rand::{Rng, SeedableRng};
  18. use string::*;
  19. use wchar::*;
  20. use errno::*;
  21. use fcntl::*;
  22. use platform::types::*;
  23. mod sort;
  24. pub const EXIT_FAILURE: c_int = 1;
  25. pub const EXIT_SUCCESS: c_int = 0;
  26. pub const RAND_MAX: c_int = 2147483647;
  27. //Maximum number of bytes in a multibyte character for the current locale
  28. pub const MB_CUR_MAX: c_int = 4;
  29. //Maximum number of bytes in a multibyte characters for any locale
  30. pub const MB_LEN_MAX: c_int = 4;
  31. static mut ATEXIT_FUNCS: [Option<extern "C" fn()>; 32] = [None; 32];
  32. static mut RNG: Option<XorShiftRng> = None;
  33. #[no_mangle]
  34. pub unsafe extern "C" fn a64l(s: *const c_char) -> c_long {
  35. if s.is_null() {
  36. return 0;
  37. }
  38. let mut l: c_long = 0;
  39. // a64l does not support more than 6 characters at once
  40. for x in 0..6 {
  41. let c = *s.offset(x);
  42. if c == 0 {
  43. // string is null terminated
  44. return l;
  45. }
  46. // ASCII to base64 conversion:
  47. let mut bits: c_long = if c < 58 {
  48. (c - 46) as c_long // ./0123456789
  49. } else if c < 91 {
  50. (c - 53) as c_long // A-Z
  51. } else {
  52. (c - 59) as c_long // a-z
  53. };
  54. bits <<= 6 * x;
  55. l |= bits;
  56. }
  57. return l;
  58. }
  59. #[no_mangle]
  60. pub unsafe extern "C" fn abort() {
  61. use core::intrinsics;
  62. intrinsics::abort();
  63. }
  64. #[no_mangle]
  65. pub extern "C" fn abs(i: c_int) -> c_int {
  66. if i < 0 {
  67. -i
  68. } else {
  69. i
  70. }
  71. }
  72. #[no_mangle]
  73. pub unsafe extern "C" fn aligned_alloc(alignment: size_t, size: size_t) -> *mut c_void {
  74. if size % alignment != 0 {
  75. return ptr::null_mut();
  76. }
  77. memalign(alignment, size)
  78. }
  79. #[no_mangle]
  80. pub unsafe extern "C" fn atexit(func: Option<extern "C" fn()>) -> c_int {
  81. for i in 0..ATEXIT_FUNCS.len() {
  82. if ATEXIT_FUNCS[i] == None {
  83. ATEXIT_FUNCS[i] = func;
  84. return 0;
  85. }
  86. }
  87. 1
  88. }
  89. #[no_mangle]
  90. pub unsafe extern "C" fn atof(s: *const c_char) -> c_double {
  91. strtod(s, ptr::null_mut())
  92. }
  93. macro_rules! dec_num_from_ascii {
  94. ($s:expr, $t:ty) => {
  95. unsafe {
  96. let mut s = $s;
  97. // Iterate past whitespace
  98. while ctype::isspace(*s as c_int) != 0 {
  99. s = s.offset(1);
  100. }
  101. // Find out if there is a - sign
  102. let neg_sign = match *s {
  103. 0x2d => {
  104. s = s.offset(1);
  105. true
  106. }
  107. // '+' increment s and continue parsing
  108. 0x2b => {
  109. s = s.offset(1);
  110. false
  111. }
  112. _ => false,
  113. };
  114. let mut n: $t = 0;
  115. while ctype::isdigit(*s as c_int) != 0 {
  116. n = 10 * n - (*s as $t - 0x30);
  117. s = s.offset(1);
  118. }
  119. if neg_sign {
  120. n
  121. } else {
  122. -n
  123. }
  124. }
  125. };
  126. }
  127. #[no_mangle]
  128. pub extern "C" fn atoi(s: *const c_char) -> c_int {
  129. dec_num_from_ascii!(s, c_int)
  130. }
  131. #[no_mangle]
  132. pub extern "C" fn atol(s: *const c_char) -> c_long {
  133. dec_num_from_ascii!(s, c_long)
  134. }
  135. unsafe extern "C" fn void_cmp(a: *const c_void, b: *const c_void) -> c_int {
  136. return *(a as *const i32) - *(b as *const i32) as c_int;
  137. }
  138. #[no_mangle]
  139. pub unsafe extern "C" fn bsearch(
  140. key: *const c_void,
  141. base: *const c_void,
  142. nel: size_t,
  143. width: size_t,
  144. compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
  145. ) -> *mut c_void {
  146. let mut start = base;
  147. let mut len = nel;
  148. let cmp_fn = compar.unwrap_or(void_cmp);
  149. while len > 0 {
  150. let med = (start as size_t + (len >> 1) * width) as *const c_void;
  151. let diff = cmp_fn(key, med);
  152. if diff == 0 {
  153. return med as *mut c_void;
  154. } else if diff > 0 {
  155. start = (med as usize + width) as *const c_void;
  156. len -= 1;
  157. }
  158. len >>= 1;
  159. }
  160. ptr::null_mut()
  161. }
  162. #[no_mangle]
  163. pub unsafe extern "C" fn calloc(nelem: size_t, elsize: size_t) -> *mut c_void {
  164. use core::intrinsics;
  165. let size = nelem * elsize;
  166. let ptr = malloc(size);
  167. if !ptr.is_null() {
  168. intrinsics::write_bytes(ptr as *mut u8, 0, size);
  169. }
  170. ptr
  171. }
  172. #[repr(C)]
  173. pub struct div_t {
  174. quot: c_int,
  175. rem: c_int,
  176. }
  177. #[no_mangle]
  178. pub extern "C" fn div(numer: c_int, denom: c_int) -> div_t {
  179. div_t {
  180. quot: numer / denom,
  181. rem: numer % denom,
  182. }
  183. }
  184. // #[no_mangle]
  185. pub extern "C" fn drand48() -> c_double {
  186. unimplemented!();
  187. }
  188. // #[no_mangle]
  189. pub extern "C" fn ecvt(
  190. value: c_double,
  191. ndigit: c_int,
  192. decpt: *mut c_int,
  193. sign: *mut c_int,
  194. ) -> *mut c_char {
  195. unimplemented!();
  196. }
  197. // #[no_mangle]
  198. pub extern "C" fn erand(xsubi: [c_ushort; 3]) -> c_double {
  199. unimplemented!();
  200. }
  201. #[no_mangle]
  202. pub unsafe extern "C" fn exit(status: c_int) {
  203. for i in (0..ATEXIT_FUNCS.len()).rev() {
  204. if let Some(func) = ATEXIT_FUNCS[i] {
  205. (func)();
  206. }
  207. }
  208. platform::exit(status);
  209. }
  210. // #[no_mangle]
  211. pub extern "C" fn fcvt(
  212. value: c_double,
  213. ndigit: c_int,
  214. decpt: *mut c_int,
  215. sign: *mut c_int,
  216. ) -> *mut c_char {
  217. unimplemented!();
  218. }
  219. #[no_mangle]
  220. pub unsafe extern "C" fn free(ptr: *mut c_void) {
  221. platform::free(ptr);
  222. }
  223. // #[no_mangle]
  224. pub extern "C" fn gcvt(value: c_double, ndigit: c_int, buf: *mut c_char) -> *mut c_char {
  225. unimplemented!();
  226. }
  227. unsafe fn find_env(name: *const c_char) -> Option<(usize, *mut c_char)> {
  228. for (i, item) in platform::inner_environ.iter().enumerate() {
  229. let mut item = *item;
  230. if item == ptr::null_mut() {
  231. assert_eq!(
  232. i,
  233. platform::inner_environ.len() - 1,
  234. "an early null pointer in environ vector"
  235. );
  236. break;
  237. }
  238. let mut name = name;
  239. loop {
  240. let end_of_name = *name == 0 || *name == b'=' as c_char;
  241. if *item == 0 || *item == b'=' as c_char || end_of_name {
  242. if *item == b'=' as c_char || end_of_name {
  243. return Some((i, item.offset(1)));
  244. } else {
  245. break;
  246. }
  247. }
  248. if *item != *name {
  249. break;
  250. }
  251. item = item.offset(1);
  252. name = name.offset(1);
  253. }
  254. }
  255. None
  256. }
  257. #[no_mangle]
  258. pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
  259. find_env(name).map(|val| val.1).unwrap_or(ptr::null_mut())
  260. }
  261. // #[no_mangle]
  262. pub extern "C" fn getsubopt(
  263. optionp: *mut *mut c_char,
  264. tokens: *const *mut c_char,
  265. valuep: *mut *mut c_char,
  266. ) -> c_int {
  267. unimplemented!();
  268. }
  269. // #[no_mangle]
  270. pub extern "C" fn grantpt(fildes: c_int) -> c_int {
  271. unimplemented!();
  272. }
  273. // #[no_mangle]
  274. pub extern "C" fn initstate(seec: c_uint, state: *mut c_char, size: size_t) -> *mut c_char {
  275. unimplemented!();
  276. }
  277. // #[no_mangle]
  278. pub extern "C" fn jrand48(xsubi: [c_ushort; 3]) -> c_long {
  279. unimplemented!();
  280. }
  281. // #[no_mangle]
  282. pub extern "C" fn l64a(value: c_long) -> *mut c_char {
  283. unimplemented!();
  284. }
  285. #[no_mangle]
  286. pub extern "C" fn labs(i: c_long) -> c_long {
  287. if i < 0 {
  288. -i
  289. } else {
  290. i
  291. }
  292. }
  293. // #[no_mangle]
  294. pub extern "C" fn lcong48(param: [c_ushort; 7]) {
  295. unimplemented!();
  296. }
  297. #[repr(C)]
  298. pub struct ldiv_t {
  299. quot: c_long,
  300. rem: c_long,
  301. }
  302. #[no_mangle]
  303. pub extern "C" fn ldiv(numer: c_long, denom: c_long) -> ldiv_t {
  304. ldiv_t {
  305. quot: numer / denom,
  306. rem: numer % denom,
  307. }
  308. }
  309. // #[no_mangle]
  310. pub extern "C" fn lrand48() -> c_long {
  311. unimplemented!();
  312. }
  313. #[no_mangle]
  314. pub unsafe extern "C" fn malloc(size: size_t) -> *mut c_void {
  315. platform::alloc(size)
  316. }
  317. #[no_mangle]
  318. pub unsafe extern "C" fn memalign(alignment: size_t, size: size_t) -> *mut c_void {
  319. platform::alloc_align(size, alignment)
  320. }
  321. #[no_mangle]
  322. pub unsafe extern "C" fn mblen(s: *const c_char, n: size_t) -> c_int {
  323. let mut wc: wchar_t = 0;
  324. let mut state: mbstate_t = mbstate_t {};
  325. let result: usize = mbrtowc(&mut wc, s, n, &mut state);
  326. if result == -1isize as usize {
  327. return -1;
  328. }
  329. if result == -2isize as usize {
  330. return -1;
  331. }
  332. result as i32
  333. }
  334. #[no_mangle]
  335. pub unsafe extern "C" fn mbstowcs(pwcs: *mut wchar_t, mut s: *const c_char, n: size_t) -> size_t {
  336. let mut state: mbstate_t = mbstate_t {};
  337. mbsrtowcs(pwcs, &mut s, n, &mut state)
  338. }
  339. #[no_mangle]
  340. pub unsafe extern "C" fn mbtowc(pwc: *mut wchar_t, s: *const c_char, n: size_t) -> c_int {
  341. let mut state: mbstate_t = mbstate_t {};
  342. mbrtowc(pwc, s, n, &mut state) as c_int
  343. }
  344. #[no_mangle]
  345. pub extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
  346. use core::iter;
  347. use core::mem;
  348. let len = unsafe { strlen(name) };
  349. if len < 6 {
  350. unsafe { platform::errno = errno::EINVAL };
  351. unsafe { *name = 0 };
  352. return name;
  353. }
  354. for i in len - 6..len {
  355. if unsafe { *name.offset(i as isize) } != b'X' as c_char {
  356. unsafe { platform::errno = errno::EINVAL };
  357. unsafe { *name = 0 };
  358. return name;
  359. }
  360. }
  361. let mut rng = JitterRng::new_with_timer(get_nstime);
  362. rng.test_timer();
  363. let mut retries = 100;
  364. loop {
  365. let char_iter = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(6);
  366. unsafe {
  367. for (i, c) in char_iter.enumerate() {
  368. *name.offset(len as isize - i as isize - 1) = c as c_char
  369. }
  370. }
  371. unsafe {
  372. let mut st: stat = mem::uninitialized();
  373. if platform::stat(name, &mut st) != 0 {
  374. if platform::errno != ENOENT {
  375. *name = 0;
  376. }
  377. return name;
  378. }
  379. mem::forget(st);
  380. }
  381. retries = retries - 1;
  382. if retries == 0 {
  383. break;
  384. }
  385. }
  386. unsafe { platform::errno = EEXIST };
  387. unsafe { *name = 0 };
  388. name
  389. }
  390. fn get_nstime() -> u64 {
  391. use core::mem;
  392. use time::constants::CLOCK_MONOTONIC;
  393. let mut ts: timespec = unsafe { mem::uninitialized() };
  394. platform::clock_gettime(CLOCK_MONOTONIC, &mut ts);
  395. ts.tv_nsec as u64
  396. }
  397. #[no_mangle]
  398. pub extern "C" fn mkostemps(name: *mut c_char, suffix_len: c_int, mut flags: c_int) -> c_int {
  399. use core::iter;
  400. let len = unsafe { strlen(name) } as c_int;
  401. if len < 6 || suffix_len > len - 6 {
  402. unsafe { platform::errno = errno::EINVAL };
  403. return -1;
  404. }
  405. for i in (len - suffix_len - 6)..(len - suffix_len) {
  406. if unsafe { *name.offset(i as isize) } != b'X' as c_char {
  407. unsafe { platform::errno = errno::EINVAL };
  408. return -1;
  409. }
  410. }
  411. flags -= flags & O_ACCMODE;
  412. let mut rng = JitterRng::new_with_timer(get_nstime);
  413. rng.test_timer();
  414. for _retries in 0..100 {
  415. let char_iter = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(6).enumerate();
  416. unsafe {
  417. for (i, c) in char_iter {
  418. *name.offset((len as isize) - (suffix_len as isize) - (i as isize) - 1) = c as c_char
  419. }
  420. }
  421. let fd = platform::open(name, flags | O_RDWR | O_CREAT | O_EXCL, 0600);
  422. if fd >= 0 {
  423. return fd;
  424. }
  425. unsafe { platform::errno = errno::EEXIST };
  426. }
  427. unsafe {
  428. for i in 0..6 {
  429. *name.offset((len as isize) - (suffix_len as isize) - (i as isize) - 1) = b'X' as c_char;
  430. }
  431. }
  432. -1
  433. }
  434. #[no_mangle]
  435. pub extern "C" fn mkstemp(name: *mut c_char) -> c_int {
  436. mkostemps(name, 0, 0)
  437. }
  438. // #[no_mangle]
  439. pub extern "C" fn mrand48() -> c_long {
  440. unimplemented!();
  441. }
  442. // #[no_mangle]
  443. pub extern "C" fn nrand48(xsubi: [c_ushort; 3]) -> c_long {
  444. unimplemented!();
  445. }
  446. // #[no_mangle]
  447. pub extern "C" fn ptsname(fildes: c_int) -> *mut c_char {
  448. unimplemented!();
  449. }
  450. #[no_mangle]
  451. pub unsafe extern "C" fn putenv(s: *mut c_char) -> c_int {
  452. let mut s_len = 0;
  453. while *s.offset(s_len) != 0 {
  454. s_len += 1;
  455. }
  456. let ptr;
  457. if let Some((i, _)) = find_env(s) {
  458. let mut item = platform::inner_environ[i];
  459. let mut item_len = 0;
  460. while *item.offset(item_len) != 0 {
  461. item_len += 1;
  462. }
  463. if item_len > s_len {
  464. ptr = item;
  465. } else {
  466. platform::free(item as *mut c_void);
  467. ptr = platform::alloc(s_len as usize + 1) as *mut c_char;
  468. platform::inner_environ[i] = ptr;
  469. }
  470. } else {
  471. ptr = platform::alloc(s_len as usize + 1) as *mut c_char;
  472. let i = platform::inner_environ.len() - 1;
  473. assert_eq!(
  474. platform::inner_environ[i],
  475. ptr::null_mut(),
  476. "last element in environ vector was not null"
  477. );
  478. platform::inner_environ[i] = ptr;
  479. platform::inner_environ.push(ptr::null_mut());
  480. platform::environ = platform::inner_environ.as_mut_ptr();
  481. }
  482. for i in 0..=s_len {
  483. *ptr.offset(i) = *s.offset(i);
  484. }
  485. 0
  486. }
  487. #[no_mangle]
  488. pub extern "C" fn qsort(
  489. base: *mut c_void,
  490. nel: size_t,
  491. width: size_t,
  492. compar: Option<extern "C" fn(*const c_void, *const c_void) -> c_int>,
  493. ) {
  494. if let Some(comp) = compar {
  495. // XXX: check width too? not specified
  496. if nel > 0 {
  497. // XXX: maybe try to do mergesort/timsort first and fallback to introsort if memory
  498. // allocation fails? not sure what is ideal
  499. sort::introsort(base as *mut c_char, nel, width, comp);
  500. }
  501. }
  502. }
  503. #[no_mangle]
  504. pub unsafe extern "C" fn rand() -> c_int {
  505. match RNG {
  506. Some(ref mut rng) => rng.gen_range(0, RAND_MAX),
  507. None => {
  508. let mut rng = XorShiftRng::from_seed([1; 16]);
  509. let ret = rng.gen_range(0, RAND_MAX);
  510. RNG = Some(rng);
  511. ret
  512. }
  513. }
  514. }
  515. // #[no_mangle]
  516. pub extern "C" fn rand_r(seed: *mut c_uint) -> c_int {
  517. unimplemented!();
  518. }
  519. // #[no_mangle]
  520. pub extern "C" fn random() -> c_long {
  521. unimplemented!();
  522. }
  523. #[no_mangle]
  524. pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void {
  525. platform::realloc(ptr, size)
  526. }
  527. // #[no_mangle]
  528. pub extern "C" fn realpath(file_name: *const c_char, resolved_name: *mut c_char) -> *mut c_char {
  529. unimplemented!();
  530. }
  531. // #[no_mangle]
  532. pub extern "C" fn seed48(seed16v: [c_ushort; 3]) -> c_ushort {
  533. unimplemented!();
  534. }
  535. // #[no_mangle]
  536. pub extern "C" fn setkey(key: *const c_char) {
  537. unimplemented!();
  538. }
  539. // #[no_mangle]
  540. pub extern "C" fn setstate(state: *const c_char) -> *mut c_char {
  541. unimplemented!();
  542. }
  543. #[no_mangle]
  544. pub unsafe extern "C" fn srand(seed: c_uint) {
  545. RNG = Some(XorShiftRng::from_seed([seed as u8; 16]));
  546. }
  547. // #[no_mangle]
  548. pub extern "C" fn srand48(seed: c_long) {
  549. unimplemented!();
  550. }
  551. // #[no_mangle]
  552. pub extern "C" fn srandom(seed: c_uint) {
  553. unimplemented!();
  554. }
  555. #[no_mangle]
  556. pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double {
  557. // TODO: endptr
  558. use core::str::FromStr;
  559. let s_str = str::from_utf8_unchecked(platform::c_str(s));
  560. match f64::from_str(s_str) {
  561. Ok(ok) => ok as c_double,
  562. Err(_err) => {
  563. platform::errno = EINVAL;
  564. 0.0
  565. }
  566. }
  567. }
  568. pub fn is_positive(ch: c_char) -> Option<(bool, isize)> {
  569. match ch {
  570. 0 => None,
  571. ch if ch == b'+' as c_char => Some((true, 1)),
  572. ch if ch == b'-' as c_char => Some((false, 1)),
  573. _ => Some((true, 0)),
  574. }
  575. }
  576. pub fn detect_base(s: *const c_char) -> Option<(c_int, isize)> {
  577. let first = unsafe { *s } as u8;
  578. match first {
  579. 0 => None,
  580. b'0' => {
  581. let second = unsafe { *s.offset(1) } as u8;
  582. if second == b'X' || second == b'x' {
  583. Some((16, 2))
  584. } else if second >= b'0' && second <= b'7' {
  585. Some((8, 1))
  586. } else {
  587. // in this case, the prefix (0) is going to be the number
  588. Some((8, 0))
  589. }
  590. }
  591. _ => Some((10, 0)),
  592. }
  593. }
  594. pub unsafe fn convert_octal(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
  595. if *s != 0 && *s == b'0' as c_char {
  596. if let Some((val, idx, overflow)) = convert_integer(s.offset(1), 8) {
  597. Some((val, idx + 1, overflow))
  598. } else {
  599. // in case the prefix is not actually a prefix
  600. Some((0, 1, false))
  601. }
  602. } else {
  603. None
  604. }
  605. }
  606. pub unsafe fn convert_hex(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
  607. if (*s != 0 && *s == b'0' as c_char)
  608. && (*s.offset(1) != 0 && (*s.offset(1) == b'x' as c_char || *s.offset(1) == b'X' as c_char))
  609. {
  610. convert_integer(s.offset(2), 16).map(|(val, idx, overflow)| (val, idx + 2, overflow))
  611. } else {
  612. None
  613. }
  614. }
  615. pub fn convert_integer(s: *const c_char, base: c_int) -> Option<(c_ulong, isize, bool)> {
  616. // -1 means the character is invalid
  617. #[cfg_attr(rustfmt, rustfmt_skip)]
  618. const LOOKUP_TABLE: [c_long; 256] = [
  619. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  620. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  621. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  622. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
  623. -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  624. 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
  625. -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  626. 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
  627. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  628. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  629. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  630. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  631. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  632. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  633. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  634. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  635. ];
  636. let mut num: c_ulong = 0;
  637. let mut idx = 0;
  638. let mut overflowed = false;
  639. loop {
  640. let val = unsafe { LOOKUP_TABLE[*s.offset(idx) as usize] };
  641. if val == -1 || val as c_int >= base {
  642. break;
  643. } else {
  644. if let Some(res) = num
  645. .checked_mul(base as c_ulong)
  646. .and_then(|num| num.checked_add(val as c_ulong))
  647. {
  648. num = res;
  649. } else {
  650. unsafe {
  651. platform::errno = ERANGE;
  652. }
  653. num = c_ulong::max_value();
  654. overflowed = true;
  655. }
  656. idx += 1;
  657. }
  658. }
  659. if idx > 0 {
  660. Some((num, idx, overflowed))
  661. } else {
  662. None
  663. }
  664. }
  665. #[macro_export]
  666. macro_rules! strto_impl {
  667. (
  668. $rettype:ty, $signed:expr, $maxval:expr, $minval:expr, $s:ident, $endptr:ident, $base:ident
  669. ) => {{
  670. // ensure these are constants
  671. const CHECK_SIGN: bool = $signed;
  672. const MAX_VAL: $rettype = $maxval;
  673. const MIN_VAL: $rettype = $minval;
  674. let set_endptr = |idx: isize| {
  675. if !$endptr.is_null() {
  676. // This is stupid, but apparently strto* functions want
  677. // const input but mut output, yet the man page says
  678. // "stores the address of the first invalid character in *endptr"
  679. // so obviously it doesn't want us to clone it.
  680. *$endptr = $s.offset(idx) as *mut _;
  681. }
  682. };
  683. let invalid_input = || {
  684. platform::errno = EINVAL;
  685. set_endptr(0);
  686. };
  687. // only valid bases are 2 through 36
  688. if $base != 0 && ($base < 2 || $base > 36) {
  689. invalid_input();
  690. return 0;
  691. }
  692. let mut idx = 0;
  693. // skip any whitespace at the beginning of the string
  694. while ctype::isspace(*$s.offset(idx) as c_int) != 0 {
  695. idx += 1;
  696. }
  697. // check for +/-
  698. let positive = match is_positive(*$s.offset(idx)) {
  699. Some((pos, i)) => {
  700. idx += i;
  701. pos
  702. }
  703. None => {
  704. invalid_input();
  705. return 0;
  706. }
  707. };
  708. // convert the string to a number
  709. let num_str = $s.offset(idx);
  710. let res = match $base {
  711. 0 => detect_base(num_str)
  712. .and_then(|($base, i)| convert_integer(num_str.offset(i), $base)),
  713. 8 => convert_octal(num_str),
  714. 16 => convert_hex(num_str),
  715. _ => convert_integer(num_str, $base),
  716. };
  717. // check for error parsing octal/hex prefix
  718. // also check to ensure a number was indeed parsed
  719. let (num, i, overflow) = match res {
  720. Some(res) => res,
  721. None => {
  722. invalid_input();
  723. return 0;
  724. }
  725. };
  726. idx += i;
  727. let overflow = if CHECK_SIGN {
  728. overflow || (num as c_long).is_negative()
  729. } else {
  730. overflow
  731. };
  732. // account for the sign
  733. let num = num as $rettype;
  734. let num = if overflow {
  735. platform::errno = ERANGE;
  736. if CHECK_SIGN {
  737. if positive {
  738. MAX_VAL
  739. } else {
  740. MIN_VAL
  741. }
  742. } else {
  743. MAX_VAL
  744. }
  745. } else {
  746. if positive {
  747. num
  748. } else {
  749. // not using -num to keep the compiler happy
  750. num.overflowing_neg().0
  751. }
  752. };
  753. set_endptr(idx);
  754. num
  755. }};
  756. }
  757. #[no_mangle]
  758. pub unsafe extern "C" fn strtoul(
  759. s: *const c_char,
  760. endptr: *mut *mut c_char,
  761. base: c_int,
  762. ) -> c_ulong {
  763. strto_impl!(
  764. c_ulong,
  765. false,
  766. c_ulong::max_value(),
  767. c_ulong::min_value(),
  768. s,
  769. endptr,
  770. base
  771. )
  772. }
  773. #[no_mangle]
  774. pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
  775. strto_impl!(
  776. c_long,
  777. true,
  778. c_long::max_value(),
  779. c_long::min_value(),
  780. s,
  781. endptr,
  782. base
  783. )
  784. }
  785. #[no_mangle]
  786. pub unsafe extern "C" fn system(command: *const c_char) -> c_int {
  787. let child_pid = unistd::fork();
  788. if child_pid == 0 {
  789. let command_nonnull = if command.is_null() {
  790. "exit 0\0".as_ptr()
  791. } else {
  792. command as *const u8
  793. };
  794. let shell = "/bin/sh\0".as_ptr();
  795. let args = [
  796. "sh\0".as_ptr(),
  797. "-c\0".as_ptr(),
  798. command_nonnull,
  799. ptr::null(),
  800. ];
  801. unistd::execv(shell as *const c_char, args.as_ptr() as *const *mut c_char);
  802. exit(127);
  803. unreachable!();
  804. } else {
  805. let mut wstatus = 0;
  806. if platform::waitpid(child_pid, &mut wstatus, 0) == !0 {
  807. return -1;
  808. }
  809. wstatus
  810. }
  811. }
  812. // #[no_mangle]
  813. pub extern "C" fn ttyslot() -> c_int {
  814. unimplemented!();
  815. }
  816. // #[no_mangle]
  817. pub extern "C" fn unlockpt(fildes: c_int) -> c_int {
  818. unimplemented!();
  819. }
  820. #[no_mangle]
  821. pub unsafe extern "C" fn valloc(size: size_t) -> *mut c_void {
  822. memalign(4096, size)
  823. }
  824. #[no_mangle]
  825. pub extern "C" fn wcstombs(s: *mut c_char, pwcs: *mut *const wchar_t, n: size_t) -> size_t {
  826. let mut state: mbstate_t = mbstate_t {};
  827. wcsrtombs(s, pwcs, n, &mut state)
  828. }
  829. #[no_mangle]
  830. pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: wchar_t) -> c_int {
  831. let mut state: mbstate_t = mbstate_t {};
  832. let result: usize = wcrtomb(s, wc, &mut state);
  833. if result == -1isize as usize {
  834. return -1;
  835. }
  836. if result == -2isize as usize {
  837. return -1;
  838. }
  839. result as c_int
  840. }