lib.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. //! stdlib implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdlib.h.html
  2. #![no_std]
  3. #![feature(core_intrinsics)]
  4. #![feature(global_allocator)]
  5. extern crate ctype;
  6. extern crate errno;
  7. extern crate platform;
  8. extern crate ralloc;
  9. extern crate rand;
  10. use core::{ptr, str};
  11. use rand::{Rng, SeedableRng, XorShiftRng};
  12. use errno::*;
  13. use platform::types::*;
  14. mod sort;
  15. #[global_allocator]
  16. static ALLOCATOR: ralloc::Allocator = ralloc::Allocator;
  17. pub const EXIT_FAILURE: c_int = 1;
  18. pub const EXIT_SUCCESS: c_int = 0;
  19. pub const RAND_MAX: c_int = 2147483647;
  20. static mut ATEXIT_FUNCS: [Option<extern "C" fn()>; 32] = [None; 32];
  21. static mut RNG: Option<XorShiftRng> = None;
  22. #[no_mangle]
  23. pub unsafe extern "C" fn a64l(s: *const c_char) -> c_long {
  24. if s.is_null() {
  25. return 0;
  26. }
  27. let mut l: c_long = 0;
  28. // a64l does not support more than 6 characters at once
  29. for x in 0..6 {
  30. let c = *s.offset(x);
  31. if c == 0 {
  32. // string is null terminated
  33. return l;
  34. }
  35. // ASCII to base64 conversion:
  36. let mut bits: c_long = if c < 58 {
  37. (c - 46) as c_long // ./0123456789
  38. } else if c < 91 {
  39. (c - 53) as c_long // A-Z
  40. } else {
  41. (c - 59) as c_long // a-z
  42. };
  43. bits <<= 6 * x;
  44. l |= bits;
  45. }
  46. return l;
  47. }
  48. #[no_mangle]
  49. pub unsafe extern "C" fn abort() {
  50. use core::intrinsics;
  51. intrinsics::abort();
  52. }
  53. #[no_mangle]
  54. pub extern "C" fn abs(i: c_int) -> c_int {
  55. if i < 0 {
  56. -i
  57. } else {
  58. i
  59. }
  60. }
  61. #[no_mangle]
  62. pub unsafe extern "C" fn atexit(func: Option<extern "C" fn()>) -> c_int {
  63. for i in 0..ATEXIT_FUNCS.len() {
  64. if ATEXIT_FUNCS[i] == None {
  65. ATEXIT_FUNCS[i] = func;
  66. return 0;
  67. }
  68. }
  69. 1
  70. }
  71. #[no_mangle]
  72. pub unsafe extern "C" fn atof(s: *const c_char) -> c_double {
  73. strtod(s, ptr::null_mut())
  74. }
  75. macro_rules! dec_num_from_ascii {
  76. ($s: expr, $t: ty) => {
  77. unsafe {
  78. let mut s = $s;
  79. // Iterate past whitespace
  80. while ctype::isspace(*s as c_int) != 0 {
  81. s = s.offset(1);
  82. }
  83. // Find out if there is a - sign
  84. let neg_sign = match *s {
  85. 0x2d => {
  86. s = s.offset(1);
  87. true
  88. }
  89. // '+' increment s and continue parsing
  90. 0x2b => {
  91. s = s.offset(1);
  92. false
  93. }
  94. _ => false,
  95. };
  96. let mut n: $t = 0;
  97. while ctype::isdigit(*s as c_int) != 0 {
  98. n = 10 * n - (*s as $t - 0x30);
  99. s = s.offset(1);
  100. }
  101. if neg_sign {
  102. n
  103. } else {
  104. -n
  105. }
  106. }
  107. };
  108. }
  109. #[no_mangle]
  110. pub extern "C" fn atoi(s: *const c_char) -> c_int {
  111. dec_num_from_ascii!(s, c_int)
  112. }
  113. #[no_mangle]
  114. pub extern "C" fn atol(s: *const c_char) -> c_long {
  115. dec_num_from_ascii!(s, c_long)
  116. }
  117. unsafe extern "C" fn void_cmp(a: *const c_void, b: *const c_void) -> c_int {
  118. return *(a as *const i32) - *(b as *const i32) as c_int;
  119. }
  120. #[no_mangle]
  121. pub unsafe extern "C" fn bsearch(
  122. key: *const c_void,
  123. base: *const c_void,
  124. nel: size_t,
  125. width: size_t,
  126. compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
  127. ) -> *mut c_void {
  128. let mut start = base;
  129. let mut len = nel;
  130. let cmp_fn = compar.unwrap_or(void_cmp);
  131. while len > 0 {
  132. let med = (start as size_t + (len >> 1) * width) as *const c_void;
  133. let diff = cmp_fn(key, med);
  134. if diff == 0 {
  135. return med as *mut c_void;
  136. } else if diff > 0 {
  137. start = (med as usize + width) as *const c_void;
  138. len -= 1;
  139. }
  140. len >>= 1;
  141. }
  142. ptr::null_mut()
  143. }
  144. #[no_mangle]
  145. pub unsafe extern "C" fn calloc(nelem: size_t, elsize: size_t) -> *mut c_void {
  146. use core::intrinsics;
  147. let size = nelem * elsize;
  148. let ptr = malloc(size);
  149. if !ptr.is_null() {
  150. intrinsics::write_bytes(ptr as *mut u8, 0, size);
  151. }
  152. ptr
  153. }
  154. #[repr(C)]
  155. pub struct div_t {
  156. quot: c_int,
  157. rem: c_int,
  158. }
  159. #[no_mangle]
  160. pub extern "C" fn div(numer: c_int, denom: c_int) -> div_t {
  161. div_t {
  162. quot: numer / denom,
  163. rem: numer % denom,
  164. }
  165. }
  166. #[no_mangle]
  167. pub extern "C" fn drand48() -> c_double {
  168. unimplemented!();
  169. }
  170. #[no_mangle]
  171. pub extern "C" fn ecvt(
  172. value: c_double,
  173. ndigit: c_int,
  174. decpt: *mut c_int,
  175. sign: *mut c_int,
  176. ) -> *mut c_char {
  177. unimplemented!();
  178. }
  179. #[no_mangle]
  180. pub extern "C" fn erand(xsubi: [c_ushort; 3]) -> c_double {
  181. unimplemented!();
  182. }
  183. #[no_mangle]
  184. pub unsafe extern "C" fn exit(status: c_int) {
  185. for i in (0..ATEXIT_FUNCS.len()).rev() {
  186. if let Some(func) = ATEXIT_FUNCS[i] {
  187. (func)();
  188. }
  189. }
  190. platform::exit(status);
  191. }
  192. #[no_mangle]
  193. pub extern "C" fn fcvt(
  194. value: c_double,
  195. ndigit: c_int,
  196. decpt: *mut c_int,
  197. sign: *mut c_int,
  198. ) -> *mut c_char {
  199. unimplemented!();
  200. }
  201. #[no_mangle]
  202. pub unsafe extern "C" fn free(ptr: *mut c_void) {
  203. let ptr = (ptr as *mut u8).offset(-16);
  204. let size = *(ptr as *mut u64);
  205. let _align = *(ptr as *mut u64).offset(1);
  206. ralloc::free(ptr, size as usize);
  207. }
  208. #[no_mangle]
  209. pub extern "C" fn gcvt(value: c_double, ndigit: c_int, buf: *mut c_char) -> *mut c_char {
  210. unimplemented!();
  211. }
  212. #[no_mangle]
  213. pub extern "C" fn getenv(name: *const c_char) -> *mut c_char {
  214. unimplemented!();
  215. }
  216. #[no_mangle]
  217. pub extern "C" fn getsubopt(
  218. optionp: *mut *mut c_char,
  219. tokens: *const *mut c_char,
  220. valuep: *mut *mut c_char,
  221. ) -> c_int {
  222. unimplemented!();
  223. }
  224. #[no_mangle]
  225. pub extern "C" fn grantpt(fildes: c_int) -> c_int {
  226. unimplemented!();
  227. }
  228. #[no_mangle]
  229. pub extern "C" fn initstate(seec: c_uint, state: *mut c_char, size: size_t) -> *mut c_char {
  230. unimplemented!();
  231. }
  232. #[no_mangle]
  233. pub extern "C" fn jrand48(xsubi: [c_ushort; 3]) -> c_long {
  234. unimplemented!();
  235. }
  236. #[no_mangle]
  237. pub extern "C" fn l64a(value: c_long) -> *mut c_char {
  238. unimplemented!();
  239. }
  240. #[no_mangle]
  241. pub extern "C" fn labs(i: c_long) -> c_long {
  242. if i < 0 {
  243. -i
  244. } else {
  245. i
  246. }
  247. }
  248. #[no_mangle]
  249. pub extern "C" fn lcong48(param: [c_ushort; 7]) {
  250. unimplemented!();
  251. }
  252. #[repr(C)]
  253. pub struct ldiv_t {
  254. quot: c_long,
  255. rem: c_long,
  256. }
  257. #[no_mangle]
  258. pub extern "C" fn ldiv(numer: c_long, denom: c_long) -> ldiv_t {
  259. ldiv_t {
  260. quot: numer / denom,
  261. rem: numer % denom,
  262. }
  263. }
  264. #[no_mangle]
  265. pub extern "C" fn lrand48() -> c_long {
  266. unimplemented!();
  267. }
  268. unsafe fn malloc_inner(size: usize, offset: usize, align: usize) -> *mut c_void {
  269. let ptr = ralloc::alloc(size + offset, align);
  270. if !ptr.is_null() {
  271. *(ptr as *mut u64) = (size + offset) as u64;
  272. *(ptr as *mut u64).offset(1) = align as u64;
  273. ptr.offset(offset as isize) as *mut c_void
  274. } else {
  275. ptr as *mut c_void
  276. }
  277. }
  278. #[no_mangle]
  279. pub unsafe extern "C" fn malloc(size: size_t) -> *mut c_void {
  280. malloc_inner(size, 16, 8)
  281. }
  282. #[no_mangle]
  283. pub unsafe extern "C" fn memalign(alignment: size_t, size: size_t) -> *mut c_void {
  284. let mut align = 32;
  285. while align <= alignment as usize {
  286. align *= 2;
  287. }
  288. malloc_inner(size, align / 2, align)
  289. }
  290. #[no_mangle]
  291. pub extern "C" fn mblen(s: *const c_char, n: size_t) -> c_int {
  292. unimplemented!();
  293. }
  294. #[no_mangle]
  295. pub extern "C" fn mbstowcs(pwcs: *mut wchar_t, s: *const c_char, n: size_t) -> size_t {
  296. unimplemented!();
  297. }
  298. #[no_mangle]
  299. pub extern "C" fn mbtowc(pwc: *mut wchar_t, s: *const c_char, n: size_t) -> c_int {
  300. unimplemented!();
  301. }
  302. #[no_mangle]
  303. pub extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
  304. unimplemented!();
  305. }
  306. #[no_mangle]
  307. pub extern "C" fn mkstemp(name: *mut c_char) -> c_int {
  308. unimplemented!();
  309. }
  310. #[no_mangle]
  311. pub extern "C" fn mrand48() -> c_long {
  312. unimplemented!();
  313. }
  314. #[no_mangle]
  315. pub extern "C" fn nrand48(xsubi: [c_ushort; 3]) -> c_long {
  316. unimplemented!();
  317. }
  318. #[no_mangle]
  319. pub extern "C" fn ptsname(fildes: c_int) -> *mut c_char {
  320. unimplemented!();
  321. }
  322. #[no_mangle]
  323. pub extern "C" fn putenv(s: *mut c_char) -> c_int {
  324. unimplemented!();
  325. }
  326. #[no_mangle]
  327. pub extern "C" fn qsort(
  328. base: *mut c_void,
  329. nel: size_t,
  330. width: size_t,
  331. compar: Option<extern "C" fn(*const c_void, *const c_void) -> c_int>,
  332. ) {
  333. if let Some(comp) = compar {
  334. // XXX: check width too? not specified
  335. if nel > 0 {
  336. // XXX: maybe try to do mergesort/timsort first and fallback to introsort if memory
  337. // allocation fails? not sure what is ideal
  338. sort::introsort(base as *mut c_char, nel, width, comp);
  339. }
  340. }
  341. }
  342. #[no_mangle]
  343. pub unsafe extern "C" fn rand() -> c_int {
  344. match RNG {
  345. Some(ref mut rng) => rng.gen_range::<c_int>(0, RAND_MAX),
  346. None => {
  347. let mut rng = XorShiftRng::from_seed([1; 16]);
  348. let ret = rng.gen_range::<c_int>(0, RAND_MAX);
  349. RNG = Some(rng);
  350. ret
  351. }
  352. }
  353. }
  354. #[no_mangle]
  355. pub extern "C" fn rand_r(seed: *mut c_uint) -> c_int {
  356. unimplemented!();
  357. }
  358. #[no_mangle]
  359. pub extern "C" fn random() -> c_long {
  360. unimplemented!();
  361. }
  362. #[no_mangle]
  363. pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void {
  364. let old_ptr = (ptr as *mut u8).offset(-16);
  365. let old_size = *(old_ptr as *mut u64);
  366. let align = *(old_ptr as *mut u64).offset(1);
  367. let ptr = ralloc::realloc(old_ptr, old_size as usize, size + 16, align as usize);
  368. if !ptr.is_null() {
  369. *(ptr as *mut u64) = (size + 16) as u64;
  370. *(ptr as *mut u64).offset(1) = align;
  371. ptr.offset(16) as *mut c_void
  372. } else {
  373. ptr as *mut c_void
  374. }
  375. }
  376. #[no_mangle]
  377. pub extern "C" fn realpath(file_name: *const c_char, resolved_name: *mut c_char) -> *mut c_char {
  378. unimplemented!();
  379. }
  380. #[no_mangle]
  381. pub extern "C" fn seed48(seed16v: [c_ushort; 3]) -> c_ushort {
  382. unimplemented!();
  383. }
  384. #[no_mangle]
  385. pub extern "C" fn setkey(key: *const c_char) {
  386. unimplemented!();
  387. }
  388. #[no_mangle]
  389. pub extern "C" fn setstate(state: *const c_char) -> *mut c_char {
  390. unimplemented!();
  391. }
  392. #[no_mangle]
  393. pub unsafe extern "C" fn srand(seed: c_uint) {
  394. RNG = Some(XorShiftRng::from_seed([seed as u8; 16]));
  395. }
  396. #[no_mangle]
  397. pub extern "C" fn srand48(seed: c_long) {
  398. unimplemented!();
  399. }
  400. #[no_mangle]
  401. pub extern "C" fn srandom(seed: c_uint) {
  402. unimplemented!();
  403. }
  404. #[no_mangle]
  405. pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double {
  406. // TODO: endptr
  407. use core::str::FromStr;
  408. let s_str = str::from_utf8_unchecked(platform::c_str(s));
  409. match f64::from_str(s_str) {
  410. Ok(ok) => ok as c_double,
  411. Err(_err) => {
  412. platform::errno = EINVAL;
  413. 0.0
  414. }
  415. }
  416. }
  417. fn is_positive(ch: c_char) -> Option<(bool, isize)> {
  418. match ch {
  419. 0 => None,
  420. ch if ch == b'+' as c_char => Some((true, 1)),
  421. ch if ch == b'-' as c_char => Some((false, 1)),
  422. _ => Some((true, 0)),
  423. }
  424. }
  425. fn detect_base(s: *const c_char) -> Option<(c_int, isize)> {
  426. let first = unsafe { *s } as u8;
  427. match first {
  428. 0 => None,
  429. b'0' => {
  430. let second = unsafe { *s.offset(1) } as u8;
  431. if second == b'X' || second == b'x' {
  432. Some((16, 2))
  433. } else if second >= b'0' && second <= b'7' {
  434. Some((8, 1))
  435. } else {
  436. // in this case, the prefix (0) is going to be the number
  437. Some((8, 0))
  438. }
  439. }
  440. _ => Some((10, 0)),
  441. }
  442. }
  443. unsafe fn convert_octal(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
  444. if *s != 0 && *s == b'0' as c_char {
  445. if let Some((val, idx, overflow)) = convert_integer(s.offset(1), 8) {
  446. Some((val, idx + 1, overflow))
  447. } else {
  448. // in case the prefix is not actually a prefix
  449. Some((0, 1, false))
  450. }
  451. } else {
  452. None
  453. }
  454. }
  455. unsafe fn convert_hex(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
  456. if (*s != 0 && *s == b'0' as c_char)
  457. && (*s.offset(1) != 0 && (*s.offset(1) == b'x' as c_char || *s.offset(1) == b'X' as c_char))
  458. {
  459. convert_integer(s.offset(2), 16).map(|(val, idx, overflow)| (val, idx + 2, overflow))
  460. } else {
  461. None
  462. }
  463. }
  464. fn convert_integer(s: *const c_char, base: c_int) -> Option<(c_ulong, isize, bool)> {
  465. // -1 means the character is invalid
  466. #[cfg_attr(rustfmt, rustfmt_skip)]
  467. const LOOKUP_TABLE: [c_long; 256] = [
  468. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  469. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  470. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  471. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
  472. -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  473. 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
  474. -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  475. 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
  476. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  477. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  478. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  479. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  480. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  481. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  482. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  483. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  484. ];
  485. let mut num: c_ulong = 0;
  486. let mut idx = 0;
  487. let mut overflowed = false;
  488. loop {
  489. let val = unsafe { LOOKUP_TABLE[*s.offset(idx) as usize] };
  490. if val == -1 || val as c_int >= base {
  491. break;
  492. } else {
  493. if let Some(res) = num.checked_mul(base as c_ulong)
  494. .and_then(|num| num.checked_add(val as c_ulong))
  495. {
  496. num = res;
  497. } else {
  498. unsafe {
  499. platform::errno = ERANGE;
  500. }
  501. num = c_ulong::max_value();
  502. overflowed = true;
  503. }
  504. idx += 1;
  505. }
  506. }
  507. if idx > 0 {
  508. Some((num, idx, overflowed))
  509. } else {
  510. None
  511. }
  512. }
  513. macro_rules! strto_impl {
  514. (
  515. $rettype:ty,
  516. $signed:expr,
  517. $maxval:expr,
  518. $minval:expr,
  519. $s:ident,
  520. $endptr:ident,
  521. $base:ident
  522. ) => {{
  523. // ensure these are constants
  524. const CHECK_SIGN: bool = $signed;
  525. const MAX_VAL: $rettype = $maxval;
  526. const MIN_VAL: $rettype = $minval;
  527. let set_endptr = |idx: isize| {
  528. if !$endptr.is_null() {
  529. *$endptr = $s.offset(idx);
  530. }
  531. };
  532. let invalid_input = || {
  533. platform::errno = EINVAL;
  534. set_endptr(0);
  535. };
  536. // only valid bases are 2 through 36
  537. if $base != 0 && ($base < 2 || $base > 36) {
  538. invalid_input();
  539. return 0;
  540. }
  541. let mut idx = 0;
  542. // skip any whitespace at the beginning of the string
  543. while ctype::isspace(*$s.offset(idx) as c_int) != 0 {
  544. idx += 1;
  545. }
  546. // check for +/-
  547. let positive = match is_positive(*$s.offset(idx)) {
  548. Some((pos, i)) => {
  549. idx += i;
  550. pos
  551. }
  552. None => {
  553. invalid_input();
  554. return 0;
  555. }
  556. };
  557. // convert the string to a number
  558. let num_str = $s.offset(idx);
  559. let res = match $base {
  560. 0 => detect_base(num_str).and_then(|($base, i)| {
  561. convert_integer(num_str.offset(i), $base)
  562. }),
  563. 8 => convert_octal(num_str),
  564. 16 => convert_hex(num_str),
  565. _ => convert_integer(num_str, $base),
  566. };
  567. // check for error parsing octal/hex prefix
  568. // also check to ensure a number was indeed parsed
  569. let (num, i, overflow) = match res {
  570. Some(res) => res,
  571. None => {
  572. invalid_input();
  573. return 0;
  574. }
  575. };
  576. idx += i;
  577. let overflow = if CHECK_SIGN {
  578. overflow || (num as c_long).is_negative()
  579. } else {
  580. overflow
  581. };
  582. // account for the sign
  583. let num = num as $rettype;
  584. let num = if overflow {
  585. platform::errno = ERANGE;
  586. if CHECK_SIGN {
  587. if positive {
  588. MAX_VAL
  589. } else {
  590. MIN_VAL
  591. }
  592. } else {
  593. MAX_VAL
  594. }
  595. } else {
  596. if positive {
  597. num
  598. } else {
  599. // not using -num to keep the compiler happy
  600. num.overflowing_neg().0
  601. }
  602. };
  603. set_endptr(idx);
  604. num
  605. }}
  606. }
  607. #[no_mangle]
  608. pub unsafe extern "C" fn strtoul(s: *const c_char,
  609. endptr: *mut *const c_char,
  610. base: c_int)
  611. -> c_ulong {
  612. strto_impl!(
  613. c_ulong,
  614. false,
  615. c_ulong::max_value(),
  616. c_ulong::min_value(),
  617. s,
  618. endptr,
  619. base
  620. )
  621. }
  622. #[no_mangle]
  623. pub unsafe extern "C" fn strtol(s: *const c_char,
  624. endptr: *mut *const c_char,
  625. base: c_int)
  626. -> c_long {
  627. strto_impl!(
  628. c_long,
  629. true,
  630. c_long::max_value(),
  631. c_long::min_value(),
  632. s,
  633. endptr,
  634. base
  635. )
  636. }
  637. #[no_mangle]
  638. pub extern "C" fn system(command: *const c_char) -> c_int {
  639. unimplemented!();
  640. }
  641. #[no_mangle]
  642. pub extern "C" fn ttyslot() -> c_int {
  643. unimplemented!();
  644. }
  645. #[no_mangle]
  646. pub extern "C" fn unlockpt(fildes: c_int) -> c_int {
  647. unimplemented!();
  648. }
  649. #[no_mangle]
  650. pub unsafe extern "C" fn valloc(size: size_t) -> *mut c_void {
  651. let align = 4096;
  652. let ptr = ralloc::alloc(size + 16, align);
  653. if !ptr.is_null() {
  654. *(ptr as *mut u64) = (size + 16) as u64;
  655. *(ptr as *mut u64).offset(1) = align as u64;
  656. ptr.offset(16) as *mut c_void
  657. } else {
  658. ptr as *mut c_void
  659. }
  660. }
  661. #[no_mangle]
  662. pub extern "C" fn wcstombs(s: *mut c_char, pwcs: *const wchar_t, n: size_t) -> size_t {
  663. unimplemented!();
  664. }
  665. #[no_mangle]
  666. pub extern "C" fn wctomb(s: *mut c_char, wchar: wchar_t) -> c_int {
  667. unimplemented!();
  668. }