locale.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* setlocale.c
  2. * Load LC_CTYPE locale only special for uclibc
  3. *
  4. * Written by Vladimir Oleynik (c) vodz@usa.net
  5. *
  6. * This file is part of the uClibc C library and is distributed
  7. * under the GNU Library General Public License.
  8. * used ideas is part of the GNU C Library.
  9. */
  10. /*
  11. * No-locale-support setlocale() added.
  12. */
  13. #include <locale.h>
  14. #include <stdio.h> /* NULL, fopen */
  15. #include <stdlib.h> /* malloc */
  16. #include <string.h>
  17. #include <limits.h> /* PATH_MAX */
  18. #include "../ctype/ctype.h"
  19. #undef TEST_LOCALE
  20. #ifdef L_setlocale
  21. #ifdef __UCLIBC_HAS_LOCALE__
  22. static char C_LOCALE_NAME[]="C";
  23. #ifdef TEST_LOCALE
  24. static const char PATH_LOCALE[]="./";
  25. #else
  26. static const char PATH_LOCALE[]=__UCLIBC_LOCALE_DIR;
  27. #endif
  28. static const char LC_CTYPE_STR[]="/LC_CTYPE";
  29. struct SAV_LOADED_LOCALE {
  30. char *locale;
  31. const unsigned char *buf;
  32. struct SAV_LOADED_LOCALE *next;
  33. };
  34. static struct SAV_LOADED_LOCALE sav_loaded_locale [1] = {
  35. { C_LOCALE_NAME, _uc_ctype_b_C, 0 }
  36. };
  37. static struct SAV_LOADED_LOCALE * old_locale = sav_loaded_locale;
  38. static char *set_new_locale(struct SAV_LOADED_LOCALE * s_locale)
  39. {
  40. _uc_ctype_b = s_locale->buf;
  41. _uc_ctype_trans = s_locale->buf+LOCALE_BUF_SIZE/2;
  42. old_locale = s_locale;
  43. return s_locale->locale;
  44. }
  45. /* Current support only LC_CTYPE or LC_ALL category */
  46. char *setlocale(int category, const char *locale)
  47. {
  48. FILE * fl;
  49. struct SAV_LOADED_LOCALE *cur;
  50. struct SAV_LOADED_LOCALE *bottom;
  51. char full_path[PATH_MAX];
  52. char * buf = 0;
  53. int l;
  54. if(category!=LC_CTYPE && category!=LC_ALL)
  55. return NULL;
  56. if(locale==0)
  57. return set_new_locale(old_locale);
  58. if(strcmp(locale, "POSIX")==0)
  59. return set_new_locale(sav_loaded_locale);
  60. else if(*locale == '\0') {
  61. locale = getenv(LC_CTYPE_STR+1);
  62. if(locale == 0 || *locale == 0)
  63. locale = getenv("LANG");
  64. if(locale == 0 || *locale == '\0')
  65. return set_new_locale(old_locale);
  66. if(strcmp(locale, "POSIX")==0)
  67. return set_new_locale(sav_loaded_locale);
  68. }
  69. for(cur = sav_loaded_locale; cur; cur = cur->next)
  70. if(strcmp(cur->locale, locale)==0)
  71. return set_new_locale(cur);
  72. l = strlen(locale);
  73. if((l+sizeof(PATH_LOCALE)+sizeof(LC_CTYPE_STR))>=PATH_MAX)
  74. return NULL;
  75. strcpy(full_path, PATH_LOCALE);
  76. strcat(full_path, locale);
  77. strcat(full_path, LC_CTYPE_STR);
  78. fl = fopen(full_path, "r");
  79. if(fl==0)
  80. return NULL;
  81. cur = malloc(sizeof(struct SAV_LOADED_LOCALE)+LOCALE_BUF_SIZE+l);
  82. if(cur) {
  83. buf = (char *)(cur+1);
  84. if(fread(buf, 1, LOCALE_BUF_SIZE+1, fl)!=(LOCALE_BUF_SIZE)) {
  85. /* broken locale file */
  86. free(cur);
  87. buf = 0;
  88. #ifdef TEST_LOCALE
  89. fprintf(stderr, "\nbroken locale file\n");
  90. #endif
  91. }
  92. }
  93. fclose(fl);
  94. if(cur==0) /* not enough memory */
  95. return NULL;
  96. if(buf==0) /* broken locale file, set to "C" */
  97. return set_new_locale(sav_loaded_locale);
  98. cur->next = 0;
  99. strcpy(buf+LOCALE_BUF_SIZE, locale);
  100. bottom = sav_loaded_locale;
  101. while(bottom->next!=0)
  102. bottom = bottom->next;
  103. bottom->next = cur;
  104. /* next two line only pedantic */
  105. cur->buf = buf;
  106. cur->locale = buf+LOCALE_BUF_SIZE;
  107. return set_new_locale(cur);
  108. }
  109. #else /* no locale support */
  110. char *setlocale(int category, const char *locale)
  111. {
  112. /* Allow locales "C" and "" (native). Both are "C" for our purposes. */
  113. if (locale) {
  114. if (*locale == 'C') {
  115. ++locale;
  116. }
  117. if (*locale) { /* locale wasn't "C" or ""!! */
  118. return NULL;
  119. }
  120. }
  121. /* Allow any legal category for "C" or "" (native) locale. */
  122. if((category < LC_CTYPE) || (category > LC_ALL)) { /* Illegal category! */
  123. return NULL;
  124. }
  125. return "C";
  126. }
  127. #endif
  128. #endif /* L_setlocale */