mod.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. //! wchar implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/wchar.h.html
  2. use core::{mem, ptr, usize};
  3. use va_list::VaList as va_list;
  4. use header::stdio::*;
  5. use header::stdlib::MB_CUR_MAX;
  6. use header::string;
  7. use header::time::*;
  8. use platform;
  9. use platform::types::*;
  10. mod utf8;
  11. const WEOF: wint_t = 0xFFFF_FFFFu32;
  12. #[repr(C)]
  13. #[derive(Clone, Copy)]
  14. pub struct mbstate_t;
  15. #[no_mangle]
  16. pub unsafe extern "C" fn btowc(c: c_int) -> wint_t {
  17. //Check for EOF
  18. if c == EOF {
  19. return WEOF;
  20. }
  21. let uc = c as u8;
  22. let c = uc as c_char;
  23. let mut ps: mbstate_t = mbstate_t;
  24. let mut wc: wchar_t = 0;
  25. let saved_errno = platform::errno;
  26. let status = mbrtowc(&mut wc, &c as (*const c_char), 1, &mut ps);
  27. if status == usize::max_value() || status == usize::max_value() - 1 {
  28. platform::errno = saved_errno;
  29. return WEOF;
  30. }
  31. wc as wint_t
  32. }
  33. #[no_mangle]
  34. pub unsafe extern "C" fn fgetwc(stream: *mut FILE) -> wint_t {
  35. //TODO: Real multibyte
  36. btowc(fgetc(stream))
  37. }
  38. #[no_mangle]
  39. pub unsafe extern "C" fn fgetws(ws: *mut wchar_t, n: c_int, stream: *mut FILE) -> *mut wchar_t {
  40. //TODO: lock
  41. let mut i = 0;
  42. while ((i + 1) as c_int) < n {
  43. let wc = fgetwc(stream);
  44. if wc == WEOF {
  45. return ptr::null_mut();
  46. }
  47. *ws.add(i) = wc as wchar_t;
  48. i += 1;
  49. }
  50. while (i as c_int) < n {
  51. *ws.add(i) = 0;
  52. i += 1;
  53. }
  54. ws
  55. }
  56. #[no_mangle]
  57. pub unsafe extern "C" fn fputwc(wc: wchar_t, stream: *mut FILE) -> wint_t {
  58. //Convert wchar_t to multibytes first
  59. static mut INTERNAL: mbstate_t = mbstate_t;
  60. let mut bytes: [c_char; MB_CUR_MAX as usize] = [0; MB_CUR_MAX as usize];
  61. let amount = wcrtomb(bytes.as_mut_ptr(), wc, &mut INTERNAL);
  62. for i in 0..amount {
  63. fputc(bytes[i] as c_int, &mut *stream);
  64. }
  65. wc as wint_t
  66. }
  67. #[no_mangle]
  68. pub unsafe extern "C" fn fputws(ws: *const wchar_t, stream: *mut FILE) -> c_int {
  69. let mut i = 0;
  70. loop {
  71. let wc = *ws.add(i);
  72. if wc == 0 {
  73. return 0;
  74. }
  75. if fputwc(wc, stream) == WEOF {
  76. return -1;
  77. }
  78. i += 1;
  79. }
  80. }
  81. // #[no_mangle]
  82. pub extern "C" fn fwide(stream: *mut FILE, mode: c_int) -> c_int {
  83. unimplemented!();
  84. }
  85. #[no_mangle]
  86. pub unsafe extern "C" fn getwc(stream: *mut FILE) -> wint_t {
  87. fgetwc(stream)
  88. }
  89. #[no_mangle]
  90. pub unsafe extern "C" fn getwchar() -> wint_t {
  91. fgetwc(stdin)
  92. }
  93. #[no_mangle]
  94. pub unsafe extern "C" fn mbsinit(ps: *const mbstate_t) -> c_int {
  95. //Add a check for the state maybe
  96. if ps.is_null() {
  97. 1
  98. } else {
  99. 0
  100. }
  101. }
  102. #[no_mangle]
  103. pub unsafe extern "C" fn mbrlen(s: *const c_char, n: size_t, ps: *mut mbstate_t) -> size_t {
  104. static mut INTERNAL: mbstate_t = mbstate_t;
  105. mbrtowc(ptr::null_mut(), s, n, &mut INTERNAL)
  106. }
  107. //Only works for UTF8 at the moment
  108. #[no_mangle]
  109. pub unsafe extern "C" fn mbrtowc(
  110. pwc: *mut wchar_t,
  111. s: *const c_char,
  112. n: size_t,
  113. ps: *mut mbstate_t,
  114. ) -> size_t {
  115. static mut INTERNAL: mbstate_t = mbstate_t;
  116. if ps.is_null() {
  117. let ps = &mut INTERNAL;
  118. }
  119. if s.is_null() {
  120. let xs: [c_char; 1] = [0];
  121. utf8::mbrtowc(pwc, &xs[0] as *const c_char, 1, ps)
  122. } else {
  123. utf8::mbrtowc(pwc, s, n, ps)
  124. }
  125. }
  126. //Convert a multibyte string to a wide string with a limited amount of bytes
  127. //Required for in POSIX.1-2008
  128. #[no_mangle]
  129. pub unsafe extern "C" fn mbsnrtowcs(
  130. dst_ptr: *mut wchar_t,
  131. src_ptr: *mut *const c_char,
  132. src_len: size_t,
  133. dst_len: size_t,
  134. ps: *mut mbstate_t,
  135. ) -> size_t {
  136. static mut INTERNAL: mbstate_t = mbstate_t;
  137. if ps.is_null() {
  138. let ps = &mut INTERNAL;
  139. }
  140. let mut src = *src_ptr;
  141. let mut dst_offset: usize = 0;
  142. let mut src_offset: usize = 0;
  143. while (dst_ptr.is_null() || dst_offset < dst_len) && src_offset < src_len {
  144. let ps_copy = *ps;
  145. let mut wc: wchar_t = 0;
  146. let amount = mbrtowc(&mut wc, src.add(src_offset), src_len - src_offset, ps);
  147. // Stop in the event a decoding error occured.
  148. if amount == -1isize as usize {
  149. *src_ptr = src.add(src_offset);
  150. return 1isize as usize;
  151. }
  152. // Stop decoding early in the event we encountered a partial character.
  153. if amount == -2isize as usize {
  154. *ps = ps_copy;
  155. break;
  156. }
  157. // Store the decoded wide character in the destination buffer.
  158. if !dst_ptr.is_null() {
  159. *dst_ptr.add(dst_offset) = wc;
  160. }
  161. // Stop decoding after decoding a null character and return a NULL
  162. // source pointer to the caller, not including the null character in the
  163. // number of characters stored in the destination buffer.
  164. if wc == 0 {
  165. src = ptr::null();
  166. src_offset = 0;
  167. break;
  168. }
  169. dst_offset += 1;
  170. src_offset += amount;
  171. }
  172. *src_ptr = src.add(src_offset);
  173. dst_offset
  174. }
  175. //Convert a multibyte string to a wide string
  176. #[no_mangle]
  177. pub unsafe extern "C" fn mbsrtowcs(
  178. dst: *mut wchar_t,
  179. src: *mut *const c_char,
  180. len: size_t,
  181. ps: *mut mbstate_t,
  182. ) -> size_t {
  183. mbsnrtowcs(dst, src, size_t::max_value(), len, ps)
  184. }
  185. #[no_mangle]
  186. pub unsafe extern "C" fn putwc(wc: wchar_t, stream: *mut FILE) -> wint_t {
  187. fputwc(wc, &mut *stream)
  188. }
  189. #[no_mangle]
  190. pub unsafe extern "C" fn putwchar(wc: wchar_t) -> wint_t {
  191. fputwc(wc, &mut *stdout)
  192. }
  193. // #[no_mangle]
  194. pub extern "C" fn swprintf(
  195. s: *mut wchar_t,
  196. n: size_t,
  197. format: *const wchar_t,
  198. ap: va_list,
  199. ) -> c_int {
  200. unimplemented!();
  201. }
  202. // #[no_mangle]
  203. pub extern "C" fn swscanf(s: *const wchar_t, format: *const wchar_t, ap: va_list) -> c_int {
  204. unimplemented!();
  205. }
  206. // #[no_mangle]
  207. pub extern "C" fn towlower(wc: wint_t) -> wint_t {
  208. unimplemented!();
  209. }
  210. // #[no_mangle]
  211. pub extern "C" fn towupper(wc: wint_t) -> wint_t {
  212. unimplemented!();
  213. }
  214. // #[no_mangle]
  215. pub extern "C" fn ungetwc(wc: wint_t, stream: *mut FILE) -> wint_t {
  216. unimplemented!();
  217. }
  218. // #[no_mangle]
  219. pub extern "C" fn vfwprintf(stream: *mut FILE, format: *const wchar_t, arg: va_list) -> c_int {
  220. unimplemented!();
  221. }
  222. // #[no_mangle]
  223. pub extern "C" fn vwprintf(format: *const wchar_t, arg: va_list) -> c_int {
  224. unimplemented!();
  225. }
  226. // #[no_mangle]
  227. pub extern "C" fn vswprintf(
  228. s: *mut wchar_t,
  229. n: size_t,
  230. format: *const wchar_t,
  231. arg: va_list,
  232. ) -> c_int {
  233. unimplemented!();
  234. }
  235. //widechar to multibyte
  236. #[no_mangle]
  237. pub unsafe extern "C" fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t) -> size_t {
  238. let mut buffer: [c_char; MB_CUR_MAX as usize] = [0; MB_CUR_MAX as usize];
  239. let (s_cpy, wc_cpy) = if s.is_null() {
  240. (buffer.as_mut_ptr(), 0)
  241. } else {
  242. (s, wc)
  243. };
  244. utf8::wcrtomb(s_cpy, wc_cpy, ps)
  245. }
  246. #[no_mangle]
  247. pub unsafe extern "C" fn wcscat(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
  248. wcsncat(ws1, ws2, usize::MAX)
  249. }
  250. #[no_mangle]
  251. pub unsafe extern "C" fn wcschr(ws: *const wchar_t, wc: wchar_t) -> *mut wchar_t {
  252. let mut i = 0;
  253. loop {
  254. if *ws.add(i) == wc {
  255. return ws.add(i) as *mut wchar_t;
  256. } else if *ws.add(i) == 0 {
  257. return 0 as *mut wchar_t;
  258. }
  259. i += 1;
  260. }
  261. }
  262. #[no_mangle]
  263. pub unsafe extern "C" fn wcscmp(ws1: *const wchar_t, ws2: *const wchar_t) -> c_int {
  264. wcsncmp(ws1, ws2, usize::MAX)
  265. }
  266. #[no_mangle]
  267. pub unsafe extern "C" fn wcscoll(ws1: *const wchar_t, ws2: *const wchar_t) -> c_int {
  268. //TODO: locale comparison
  269. wcscmp(ws1, ws2)
  270. }
  271. #[no_mangle]
  272. pub unsafe extern "C" fn wcscpy(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
  273. let mut i = 0;
  274. loop {
  275. let wc = *ws2.add(i);
  276. *ws1.add(i) = wc;
  277. i += 1;
  278. if wc == 0 {
  279. return ws1;
  280. }
  281. }
  282. }
  283. #[no_mangle]
  284. pub unsafe extern "C" fn wcscspn(ws1: *const wchar_t, ws2: *const wchar_t) -> size_t {
  285. let mut i = 0;
  286. loop {
  287. let wc = *ws1.add(i);
  288. if wc == 0 || wcschr(ws2, wc) != 0 as *mut wchar_t {
  289. return i;
  290. }
  291. i += 1;
  292. }
  293. }
  294. // #[no_mangle]
  295. pub extern "C" fn wcsftime(
  296. wcs: *mut wchar_t,
  297. maxsize: size_t,
  298. format: *const wchar_t,
  299. timptr: *mut tm,
  300. ) -> size_t {
  301. unimplemented!();
  302. }
  303. #[no_mangle]
  304. pub unsafe extern "C" fn wcslen(ws: *const wchar_t) -> c_ulong {
  305. let mut i = 0;
  306. loop {
  307. if *ws.add(i) == 0 {
  308. return i as c_ulong;
  309. }
  310. i += 1;
  311. }
  312. }
  313. #[no_mangle]
  314. pub unsafe extern "C" fn wcsncat(
  315. ws1: *mut wchar_t,
  316. ws2: *const wchar_t,
  317. n: size_t,
  318. ) -> *mut wchar_t {
  319. let len = wcslen(ws1);
  320. let dest = ws1.add(len as usize);
  321. let mut i = 0;
  322. while i < n {
  323. let wc = *ws2.add(i);
  324. if wc == 0 {
  325. break;
  326. }
  327. *dest.add(i) = wc;
  328. i += 1;
  329. }
  330. *dest.add(i) = 0;
  331. ws1
  332. }
  333. #[no_mangle]
  334. pub unsafe extern "C" fn wcsncmp(ws1: *const wchar_t, ws2: *const wchar_t, n: size_t) -> c_int {
  335. let mut i = 0;
  336. while i < n {
  337. let wc1 = *ws1.add(i);
  338. let wc2 = *ws2.add(i);
  339. if wc1 != wc2 {
  340. return wc1 - wc2;
  341. } else if wc1 == 0 {
  342. break;
  343. }
  344. i += 1;
  345. }
  346. 0
  347. }
  348. #[no_mangle]
  349. pub unsafe extern "C" fn wcsncpy(
  350. ws1: *mut wchar_t,
  351. ws2: *const wchar_t,
  352. n: size_t,
  353. ) -> *mut wchar_t {
  354. let mut i = 0;
  355. while i < n {
  356. let wc = *ws2.add(i);
  357. *ws1.add(i) = wc;
  358. i += 1;
  359. if wc == 0 {
  360. break;
  361. }
  362. }
  363. while i < n {
  364. *ws1.add(i) = 0;
  365. i += 1;
  366. }
  367. ws1
  368. }
  369. // #[no_mangle]
  370. pub extern "C" fn wcspbrk(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
  371. unimplemented!();
  372. }
  373. // #[no_mangle]
  374. pub extern "C" fn wcsrchr(ws1: *const wchar_t, ws2: wchar_t) -> *mut wchar_t {
  375. unimplemented!();
  376. }
  377. // #[no_mangle]
  378. pub extern "C" fn wcsrtombs(
  379. dst: *mut c_char,
  380. src: *mut *const wchar_t,
  381. len: size_t,
  382. ps: *mut mbstate_t,
  383. ) -> size_t {
  384. unimplemented!();
  385. }
  386. // #[no_mangle]
  387. pub extern "C" fn wcsspn(ws1: *const wchar_t, ws2: *const wchar_t) -> size_t {
  388. unimplemented!();
  389. }
  390. // #[no_mangle]
  391. pub extern "C" fn wcsstr(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
  392. unimplemented!();
  393. }
  394. // #[no_mangle]
  395. pub extern "C" fn wcstod(nptr: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 {
  396. unimplemented!();
  397. }
  398. // #[no_mangle]
  399. pub extern "C" fn wcstok(
  400. ws1: *mut wchar_t,
  401. ws2: *const wchar_t,
  402. ptr: *mut *mut wchar_t,
  403. ) -> *mut wchar_t {
  404. unimplemented!();
  405. }
  406. // #[no_mangle]
  407. pub extern "C" fn wcstol(nptr: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_long {
  408. unimplemented!();
  409. }
  410. // #[no_mangle]
  411. pub extern "C" fn wcstoul(nptr: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulong {
  412. unimplemented!();
  413. }
  414. // #[no_mangle]
  415. pub extern "C" fn wcswcs(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
  416. unimplemented!();
  417. }
  418. // #[no_mangle]
  419. pub extern "C" fn wcswidth(pwcs: *const wchar_t, n: size_t) -> c_int {
  420. unimplemented!();
  421. }
  422. // #[no_mangle]
  423. pub extern "C" fn wcsxfrm(ws1: *mut wchar_t, ws2: *const wchar_t, n: size_t) -> size_t {
  424. unimplemented!();
  425. }
  426. #[no_mangle]
  427. pub extern "C" fn wctob(c: wint_t) -> c_int {
  428. if c <= 0x7F {
  429. c as c_int
  430. } else {
  431. EOF
  432. }
  433. }
  434. // #[no_mangle]
  435. pub extern "C" fn wcwidth(wc: wchar_t) -> c_int {
  436. unimplemented!();
  437. }
  438. #[no_mangle]
  439. pub unsafe extern "C" fn wmemchr(ws: *const wchar_t, wc: wchar_t, n: size_t) -> *mut wchar_t {
  440. let mut i = 0;
  441. while i < n {
  442. if *ws.add(i) == wc {
  443. return ws.add(i) as *mut wchar_t;
  444. }
  445. i += 1;
  446. }
  447. 0 as *mut wchar_t
  448. }
  449. #[no_mangle]
  450. pub unsafe extern "C" fn wmemcmp(ws1: *const wchar_t, ws2: *const wchar_t, n: size_t) -> c_int {
  451. let mut i = 0;
  452. while i < n {
  453. let wc1 = *ws1.add(i);
  454. let wc2 = *ws2.add(i);
  455. if wc1 != wc2 {
  456. return wc1 - wc2;
  457. }
  458. i += 1;
  459. }
  460. 0
  461. }
  462. #[no_mangle]
  463. pub unsafe extern "C" fn wmemcpy(
  464. ws1: *mut wchar_t,
  465. ws2: *const wchar_t,
  466. n: size_t,
  467. ) -> *mut wchar_t {
  468. string::memcpy(
  469. ws1 as *mut c_void,
  470. ws2 as *const c_void,
  471. n * mem::size_of::<wchar_t>(),
  472. ) as *mut wchar_t
  473. }
  474. #[no_mangle]
  475. pub unsafe extern "C" fn wmemmove(
  476. ws1: *mut wchar_t,
  477. ws2: *const wchar_t,
  478. n: size_t,
  479. ) -> *mut wchar_t {
  480. string::memmove(
  481. ws1 as *mut c_void,
  482. ws2 as *const c_void,
  483. n * mem::size_of::<wchar_t>(),
  484. ) as *mut wchar_t
  485. }
  486. #[no_mangle]
  487. pub unsafe extern "C" fn wmemset(ws: *mut wchar_t, wc: wchar_t, n: size_t) -> *mut wchar_t {
  488. let mut i = 0;
  489. while i < n {
  490. *ws.add(i) = wc;
  491. i += 1;
  492. }
  493. ws
  494. }
  495. // #[no_mangle]
  496. pub extern "C" fn wprintf(format: *const wchar_t, ap: va_list) -> c_int {
  497. unimplemented!();
  498. }
  499. // #[no_mangle]
  500. pub extern "C" fn wscanf(format: *const wchar_t, ap: va_list) -> c_int {
  501. unimplemented!();
  502. }