wctype.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. /* Copyright (C) 2002 Manuel Novoa III
  2. *
  3. * This library is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU Library General Public
  5. * License as published by the Free Software Foundation; either
  6. * version 2 of the License, or (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Library General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Library General Public
  14. * License along with this library; if not, write to the Free
  15. * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. /* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
  18. *
  19. * Besides uClibc, I'm using this code in my libc for elks, which is
  20. * a 16-bit environment with a fairly limited compiler. It would make
  21. * things much easier for me if this file isn't modified unnecessarily.
  22. * In particular, please put any new or replacement functions somewhere
  23. * else, and modify the makefile to use your version instead.
  24. * Thanks. Manuel
  25. *
  26. * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
  27. #define _GNU_SOURCE
  28. #define __NO_CTYPE
  29. #include <wctype.h>
  30. #include <assert.h>
  31. #include <string.h>
  32. #include <errno.h>
  33. #include <locale.h>
  34. #include <ctype.h>
  35. /* We know wide char support is enabled. We wouldn't be here otherwise. */
  36. /* Define this if you want to unify the towupper and towlower code in the
  37. * towctrans function. */
  38. /* #define SMALL_UPLOW */
  39. #ifndef __LOCALE_C_ONLY
  40. #define __WCTYPE_WITH_LOCALE
  41. #endif
  42. /**********************************************************************/
  43. #ifndef __PASTE
  44. #define __PASTE(X,Y) X ## Y
  45. #endif
  46. #define C_MACRO(X) __PASTE(__C_,X)(wc)
  47. #define CT_MACRO(X) __PASTE(__ctype_,X)(wc)
  48. /**********************************************************************/
  49. /* TODO: fix this! */
  50. #ifdef __WCTYPE_WITH_LOCALE
  51. #define WCctype (__global_locale.tblwctype)
  52. #define WCuplow (__global_locale.tblwuplow)
  53. #define WCcmob (__global_locale.tblwcomb)
  54. #define WCuplow_diff (__global_locale.tblwuplow_diff)
  55. #define ENCODING (__global_locale.encoding)
  56. #define ISW_FUNC_BODY(NAME) \
  57. int NAME (wint_t wc) \
  58. { \
  59. return iswctype(wc, __PASTE(_CTYPE_,NAME)); \
  60. }
  61. #else /* __WCTYPE_WITH_LOCALE */
  62. #define ISW_FUNC_BODY(NAME) \
  63. int NAME (wint_t wc) \
  64. { \
  65. return C_MACRO(NAME); \
  66. }
  67. #endif /* __WCTYPE_WITH_LOCALE */
  68. /**********************************************************************/
  69. #ifdef L_iswalnum
  70. ISW_FUNC_BODY(iswalnum);
  71. #endif
  72. /**********************************************************************/
  73. #ifdef L_iswalpha
  74. ISW_FUNC_BODY(iswalpha);
  75. #endif
  76. /**********************************************************************/
  77. #ifdef L_iswblank
  78. ISW_FUNC_BODY(iswblank);
  79. #endif
  80. /**********************************************************************/
  81. #ifdef L_iswcntrl
  82. ISW_FUNC_BODY(iswcntrl);
  83. #endif
  84. /**********************************************************************/
  85. #ifdef L_iswdigit
  86. int iswdigit(wint_t wc)
  87. {
  88. return __C_iswdigit(wc);
  89. }
  90. #endif
  91. /**********************************************************************/
  92. #ifdef L_iswgraph
  93. ISW_FUNC_BODY(iswgraph);
  94. #endif
  95. /**********************************************************************/
  96. #ifdef L_iswlower
  97. ISW_FUNC_BODY(iswlower);
  98. #endif
  99. /**********************************************************************/
  100. #ifdef L_iswprint
  101. ISW_FUNC_BODY(iswprint);
  102. #endif
  103. /**********************************************************************/
  104. #ifdef L_iswpunct
  105. ISW_FUNC_BODY(iswpunct);
  106. #endif
  107. /**********************************************************************/
  108. #ifdef L_iswspace
  109. ISW_FUNC_BODY(iswspace);
  110. #endif
  111. /**********************************************************************/
  112. #ifdef L_iswupper
  113. ISW_FUNC_BODY(iswupper);
  114. #endif
  115. /**********************************************************************/
  116. #ifdef L_iswxdigit
  117. int iswxdigit(wint_t wc)
  118. {
  119. return __C_iswxdigit(wc);
  120. }
  121. #endif
  122. /**********************************************************************/
  123. #ifdef L_towlower
  124. #ifdef __WCTYPE_WITH_LOCALE
  125. #ifdef SMALL_UPLOW
  126. wint_t towlower(wint_t wc)
  127. {
  128. return towctrans(wc, _CTYPE_tolower);
  129. }
  130. #else
  131. wint_t towlower(wint_t wc)
  132. {
  133. unsigned int sc, n, i;
  134. __uwchar_t u = wc;
  135. if (ENCODING == __ctype_encoding_7_bit) {
  136. /* We're in the C/POSIX locale, so ignore the tables. */
  137. return __C_towlower(wc);
  138. }
  139. if (u <= WC_TABLE_DOMAIN_MAX) {
  140. sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
  141. u >>= WCuplow_TI_SHIFT;
  142. n = u & ((1 << WCuplow_II_SHIFT) - 1);
  143. u >>= WCuplow_II_SHIFT;
  144. i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
  145. i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
  146. << WCuplow_TI_SHIFT;
  147. i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
  148. + i + sc]) << 1;
  149. wc += WCuplow_diff[i + 1];
  150. }
  151. return wc;
  152. }
  153. #endif
  154. #else /* __WCTYPE_WITH_LOCALE */
  155. wint_t towlower(wint_t wc)
  156. {
  157. return __C_towlower(wc);
  158. }
  159. #endif /* __WCTYPE_WITH_LOCALE */
  160. #endif
  161. /**********************************************************************/
  162. #ifdef L_towupper
  163. #ifdef __WCTYPE_WITH_LOCALE
  164. #ifdef SMALL_UPLOW
  165. wint_t towupper(wint_t wc)
  166. {
  167. return towctrans(wc, _CTYPE_toupper);
  168. }
  169. #else
  170. wint_t towupper(wint_t wc)
  171. {
  172. unsigned int sc, n, i;
  173. __uwchar_t u = wc;
  174. if (ENCODING == __ctype_encoding_7_bit) {
  175. /* We're in the C/POSIX locale, so ignore the tables. */
  176. return __C_towupper(wc);
  177. }
  178. if (u <= WC_TABLE_DOMAIN_MAX) {
  179. sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
  180. u >>= WCuplow_TI_SHIFT;
  181. n = u & ((1 << WCuplow_II_SHIFT) - 1);
  182. u >>= WCuplow_II_SHIFT;
  183. i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
  184. i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
  185. << WCuplow_TI_SHIFT;
  186. i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
  187. + i + sc]) << 1;
  188. wc += WCuplow_diff[i];
  189. }
  190. return wc;
  191. }
  192. #endif
  193. #else /* __WCTYPE_WITH_LOCALE */
  194. wint_t towupper(wint_t wc)
  195. {
  196. return __C_towupper(wc);
  197. }
  198. #endif /* __WCTYPE_WITH_LOCALE */
  199. #endif
  200. /**********************************************************************/
  201. #ifdef L_wctype
  202. static const unsigned char typestring[] = __CTYPE_TYPESTRING;
  203. /* extern const unsigned char typestring[]; */
  204. wctype_t wctype(const char *property)
  205. {
  206. const unsigned char *p;
  207. int i;
  208. p = typestring;
  209. i = 1;
  210. do {
  211. if (!strcmp(property, ++p)) {
  212. return i;
  213. }
  214. ++i;
  215. p += p[-1];
  216. } while (*p);
  217. /* TODO - Add locale-specific classifications. */
  218. return 0;
  219. }
  220. #endif
  221. /**********************************************************************/
  222. #ifdef L_iswctype
  223. #ifdef __UCLIBC_MJN3_ONLY__
  224. #warning duh... replace the range-based classification with table lookup!
  225. #endif
  226. #ifdef __WCTYPE_WITH_LOCALE
  227. #ifdef __UCLIBC_MJN3_ONLY__
  228. #warning TODO: need to fix locale ctype table lookup stuff
  229. #endif
  230. #if 0
  231. extern const char ctype_range[];
  232. #else
  233. static const char ctype_range[] = {
  234. __CTYPE_RANGES
  235. };
  236. #endif
  237. #ifdef __UCLIBC_MJN3_ONLY__
  238. #warning TODO: need to handle combining class!
  239. #endif
  240. #define WCctype_TI_MASK ((1 << WCctype_TI_SHIFT) - 1)
  241. #define WCctype_II_MASK ((1 << WCctype_II_SHIFT) - 1)
  242. int iswctype(wint_t wc, wctype_t desc)
  243. {
  244. unsigned int sc, n, i0, i1;
  245. unsigned char d = __CTYPE_unclassified;
  246. if ((ENCODING != __ctype_encoding_7_bit) || (((__uwchar_t) wc) <= 0x7f)){
  247. if (desc < _CTYPE_iswxdigit) {
  248. if (((__uwchar_t) wc) <= WC_TABLE_DOMAIN_MAX) {
  249. /* From here on, we know wc > 0. */
  250. sc = wc & WCctype_TI_MASK;
  251. wc >>= WCctype_TI_SHIFT;
  252. n = wc & WCctype_II_MASK;
  253. wc >>= WCctype_II_SHIFT;
  254. i0 = WCctype[wc];
  255. i0 <<= WCctype_II_SHIFT;
  256. i1 = WCctype[WCctype_II_LEN + i0 + n];
  257. i1 <<= (WCctype_TI_SHIFT-1);
  258. d = WCctype[WCctype_II_LEN + WCctype_TI_LEN + i1 + (sc >> 1)];
  259. d = (sc & 1) ? (d >> 4) : (d & 0xf);
  260. } else if ( ((((__uwchar_t)(wc - 0xe0020UL)) <= 0x5f)
  261. || (wc == 0xe0001UL))
  262. || ( (((__uwchar_t)(wc - 0xf0000UL)) < 0x20000UL)
  263. && ((wc & 0xffffU) <= 0xfffdU))
  264. ) {
  265. d = __CTYPE_punct;
  266. }
  267. return ( ((unsigned char)(d - ctype_range[2*desc]))
  268. <= ctype_range[2*desc + 1] )
  269. && ((desc != _CTYPE_iswblank) || (d & 1));
  270. }
  271. /* TODO - Add locale-specific classifications. */
  272. return (desc == _CTYPE_iswxdigit) ? __C_iswxdigit(wc) : 0;
  273. }
  274. return 0;
  275. }
  276. #else
  277. static const unsigned char WCctype[] = {
  278. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  279. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  280. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  281. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  282. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_space_blank << 4),
  283. __CTYPE_cntrl_space_nonblank | (__CTYPE_cntrl_space_nonblank << 4),
  284. __CTYPE_cntrl_space_nonblank | (__CTYPE_cntrl_space_nonblank << 4),
  285. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  286. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  287. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  288. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  289. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  290. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  291. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  292. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  293. __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4),
  294. __CTYPE_print_space_blank | (__CTYPE_punct << 4),
  295. __CTYPE_punct | (__CTYPE_punct << 4),
  296. __CTYPE_punct | (__CTYPE_punct << 4),
  297. __CTYPE_punct | (__CTYPE_punct << 4),
  298. __CTYPE_punct | (__CTYPE_punct << 4),
  299. __CTYPE_punct | (__CTYPE_punct << 4),
  300. __CTYPE_punct | (__CTYPE_punct << 4),
  301. __CTYPE_punct | (__CTYPE_punct << 4),
  302. __CTYPE_digit | (__CTYPE_digit << 4),
  303. __CTYPE_digit | (__CTYPE_digit << 4),
  304. __CTYPE_digit | (__CTYPE_digit << 4),
  305. __CTYPE_digit | (__CTYPE_digit << 4),
  306. __CTYPE_digit | (__CTYPE_digit << 4),
  307. __CTYPE_punct | (__CTYPE_punct << 4),
  308. __CTYPE_punct | (__CTYPE_punct << 4),
  309. __CTYPE_punct | (__CTYPE_punct << 4),
  310. __CTYPE_punct | (__CTYPE_alpha_upper << 4),
  311. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  312. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  313. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  314. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  315. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  316. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  317. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  318. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  319. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  320. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  321. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  322. __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4),
  323. __CTYPE_alpha_upper | (__CTYPE_punct << 4),
  324. __CTYPE_punct | (__CTYPE_punct << 4),
  325. __CTYPE_punct | (__CTYPE_punct << 4),
  326. __CTYPE_punct | (__CTYPE_alpha_lower << 4),
  327. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  328. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  329. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  330. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  331. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  332. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  333. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  334. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  335. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  336. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  337. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  338. __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4),
  339. __CTYPE_alpha_lower | (__CTYPE_punct << 4),
  340. __CTYPE_punct | (__CTYPE_punct << 4),
  341. __CTYPE_punct | (__CTYPE_cntrl_nonspace << 4),
  342. };
  343. static const char ctype_range[] = {
  344. __CTYPE_RANGES
  345. };
  346. int iswctype(wint_t wc, wctype_t desc)
  347. {
  348. unsigned char d = __CTYPE_unclassified;
  349. if (((__uwchar_t) wc) <= 0x7f) {
  350. if (desc < _CTYPE_iswxdigit) {
  351. d = WCctype[wc >> 1];
  352. d = (wc & 1) ? (d >> 4) : (d & 0xf);
  353. return ( ((unsigned char)(d - ctype_range[2*desc]))
  354. <= ctype_range[2*desc + 1] )
  355. && ((desc != _CTYPE_iswblank) || (d & 1));
  356. }
  357. if (desc == _CTYPE_iswxdigit) {
  358. return __C_isxdigit(((char) wc));
  359. }
  360. }
  361. return 0;
  362. }
  363. #endif
  364. #endif
  365. /**********************************************************************/
  366. #ifdef L_towctrans
  367. #ifdef __WCTYPE_WITH_LOCALE
  368. #ifdef SMALL_UPLOW
  369. wint_t towctrans(wint_t wc, wctrans_t desc)
  370. {
  371. unsigned int sc, n, i;
  372. __uwchar_t u = wc;
  373. /* TODO - clean up */
  374. if (ENCODING == __ctype_encoding_7_bit) {
  375. if ((((__uwchar_t) wc) > 0x7f)
  376. || (((unsigned int)(desc - _CTYPE_tolower))
  377. > (_CTYPE_toupper - _CTYPE_tolower))
  378. ){
  379. /* We're in the C/POSIX locale, so ignore non-ASCII values
  380. * as well an any mappings other than toupper or tolower. */
  381. return wc;
  382. }
  383. }
  384. if (((unsigned int)(desc - _CTYPE_tolower))
  385. <= (_CTYPE_totitle - _CTYPE_tolower)
  386. ) {
  387. if (u <= WC_TABLE_DOMAIN_MAX) {
  388. sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
  389. u >>= WCuplow_TI_SHIFT;
  390. n = u & ((1 << WCuplow_II_SHIFT) - 1);
  391. u >>= WCuplow_II_SHIFT;
  392. i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
  393. i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
  394. << WCuplow_TI_SHIFT;
  395. i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
  396. + i + sc]) << 1;
  397. if (desc == _CTYPE_tolower) {
  398. ++i;
  399. }
  400. wc += WCuplow_diff[i];
  401. if (desc == _CTYPE_totitle) {
  402. /* WARNING! These special cases work for glibc 2.2.4. Changes
  403. * may be needed if the glibc locale tables are updated. */
  404. if ( (((__uwchar_t)(wc - 0x1c4)) <= (0x1cc - 0x1c4))
  405. || (wc == 0x1f1)
  406. ) {
  407. ++wc;
  408. }
  409. }
  410. }
  411. } else {
  412. /* TODO - Deal with other transliterations. */
  413. __set_errno(EINVAL);
  414. }
  415. return wc;
  416. }
  417. #else
  418. wint_t towctrans(wint_t wc, wctrans_t desc)
  419. {
  420. if (ENCODING == __ctype_encoding_7_bit) {
  421. if ((((__uwchar_t) wc) > 0x7f)
  422. || (((unsigned int)(desc - _CTYPE_tolower))
  423. > (_CTYPE_toupper - _CTYPE_tolower))
  424. ){
  425. /* We're in the C/POSIX locale, so ignore non-ASCII values
  426. * as well an any mappings other than toupper or tolower. */
  427. return wc;
  428. }
  429. }
  430. if (desc == _CTYPE_tolower) {
  431. return towlower(wc);
  432. } else if (((unsigned int)(desc - _CTYPE_toupper))
  433. <= (_CTYPE_totitle - _CTYPE_toupper)
  434. ) {
  435. wc = towupper(wc);
  436. if (desc == _CTYPE_totitle) {
  437. /* WARNING! These special cases work for glibc 2.2.4. Changes
  438. * may be needed if the glibc locale tables are updated. */
  439. if ( (((__uwchar_t)(wc - 0x1c4)) <= (0x1cc - 0x1c4))
  440. || (wc == 0x1f1)
  441. ) {
  442. ++wc;
  443. }
  444. }
  445. } else {
  446. /* TODO - Deal with other transliterations. */
  447. __set_errno(EINVAL);
  448. }
  449. return wc;
  450. }
  451. #endif
  452. #else /* __WCTYPE_WITH_LOCALE */
  453. /* Minimal support for C/POSIX locale. */
  454. wint_t towctrans(wint_t wc, wctrans_t desc)
  455. {
  456. if (((unsigned int)(desc - _CTYPE_tolower))
  457. <= (_CTYPE_toupper - _CTYPE_tolower)
  458. ) {
  459. /* Transliteration is either tolower or toupper. */
  460. if (((__uwchar_t) wc) <= 0x7f) {
  461. return (desc == _CTYPE_tolower) ? _tolower(wc) : _toupper(wc);
  462. }
  463. } else {
  464. __set_errno(EINVAL); /* Invalid transliteration. */
  465. }
  466. return wc;
  467. }
  468. #endif /* __WCTYPE_WITH_LOCALE */
  469. #endif
  470. /**********************************************************************/
  471. #ifdef L_wctrans
  472. static const char transstring[] = __CTYPE_TRANSTRING;
  473. wctrans_t wctrans(const char *property)
  474. {
  475. const unsigned char *p;
  476. int i;
  477. p = transstring;
  478. i = 1;
  479. do {
  480. if (!strcmp(property, ++p)) {
  481. return i;
  482. }
  483. ++i;
  484. p += p[-1];
  485. } while (*p);
  486. /* TODO - Add locale-specific translations. */
  487. return 0;
  488. }
  489. #endif
  490. /**********************************************************************/