pastebin - collaborative debugging tool
rovema.kpaste.net RSS


thread_locale1.c - Per-thread locale demo
Posted by Anonymous on Tue 16th May 2023 16:16
raw | new post
modification of post by Anonymous (view diff)

  1. /*
  2.  * thread_multi_locale1.c - Per-thread locale demo
  3.  *
  4.  * Written by Roland Mainz <roland.mainz@nrubsig.org>
  5.  */
  6.  
  7. #define _XOPEN_SOURCE 700
  8.  
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <locale.h>
  13. #include <errno.h>
  14.  
  15. #define CURSED_GLIBC_DOES_NOT_HAVE_PRINTF_L 1
  16.  
  17. #if defined(WIN32) && !defined(LC_GLOBAL_LOCATE)
  18. #define EMULATE_POSIX_NEWLOCALE_ON_WINDOWS 1
  19. #endif /* defined(WIN32) && !defined(LC_GLOBAL_LOCATE) */
  20.  
  21.  
  22. #if EMULATE_POSIX_NEWLOCALE_ON_WINDOWS
  23. #include <xlocinfo.h>
  24.  
  25. typedef _locale_t locale_t;
  26.  
  27. #define LC_ALL_MASK     (LC_ALL)
  28.  
  29. locale_t newlocale(int mask, const char * locale, locale_t base_not_implemented)
  30. {
  31.         return _create_locale(mask, locale);
  32. }
  33.  
  34. locale_t uselocale(locale_t newlocobj)
  35. {
  36.         locale_t old_locale = _get_current_locale();
  37.    
  38.         /*
  39.          * uselocale() sets the thread's locale by definition, so
  40.          * unconditionally use thread-local locale
  41.          */
  42.         (void)_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
  43.  
  44. #define ElementsInArray(x)   (sizeof(x) / sizeof((x)[0]))  
  45.         /*
  46.          * sets all categories - right now our poor man's emulation
  47.          * can't do it better
  48.          */
  49.         for(int i=0 ; i < ElementsInArray(newlocobj->locinfo->lc_category) ; i++) {
  50.                 const char *curr_ln = newlocobj->locinfo->lc_category[1].locale;
  51. #if 0
  52.                 (void)fprintf(stderr,
  53.                         "uselocale: switching to locale %d/|%s|\n",
  54.                         i, curr_ln);
  55. #endif
  56.                 (void)setlocale(i, curr_ln);
  57.         }
  58.  
  59.         /* return the old locale_t */
  60.         return old_locale;
  61. }
  62.  
  63. void freelocale(locale_t locobj)
  64. {
  65.         _free_locale(locobj);
  66. }
  67. #endif /* EMULATE_POSIX_NEWLOCALE_ON_WINDOWS */
  68.  
  69. #ifdef __GLIBC__
  70. /* { BSD, MacOSX, Illumos, ... } do not need this! */
  71. #define CURSED_GLIBC_DOES_NOT_HAVE_PRINTF_L
  72. #endif
  73.  
  74. #ifdef CURSED_GLIBC_DOES_NOT_HAVE_PRINTF_L
  75. #include <stdarg.h>
  76. #include <errno.h>
  77. #endif /* CURSED_GLIBC_DOES_NOT_HAVE_PRINTF_L */
  78.  
  79. #ifdef CURSED_GLIBC_DOES_NOT_HAVE_PRINTF_L
  80. /* cursed glibc does not provide |printf_l()| */
  81. int vprintf_l(locale_t loc, const char *format, va_list ap)
  82. {
  83.         locale_t prev_loc;
  84.         int ret;
  85.         int saved_errno;
  86.  
  87.         prev_loc = uselocale(loc);
  88.        
  89.         ret = vprintf(format, ap);
  90.         saved_errno = errno;
  91.  
  92.         (void)uselocale(prev_loc);
  93.  
  94.         errno = saved_errno;
  95.         return ret;
  96. }
  97.  
  98. int printf_l(locale_t loc, const char *format, ...)
  99. {
  100.         va_list args;
  101.         int res;
  102.  
  103.         va_start(args, format);
  104.         res = vprintf_l(loc, format, args);
  105.         va_end(args);
  106.  
  107.         return res;
  108. }
  109. #endif /* CURSED_GLIBC_DOES_NOT_HAVE_PRINTF_L */
  110.  
  111.  
  112. int main(int ac, char *av[])
  113. {
  114.         locale_t my_en_l;
  115.         locale_t my_de_l;
  116.         double x;
  117.  
  118.         (void)puts("# thread_multi_locale1: start"
  119. #ifdef EMULATE_POSIX_NEWLOCALE_ON_WINDOWS
  120.         " (emulated)"
  121. #endif /* EMULATE_POSIX_NEWLOCALE_ON_WINDOWS */
  122.         ".");
  123.  
  124. #if EMULATE_POSIX_NEWLOCALE_ON_WINDOWS
  125.         my_en_l = newlocale(LC_ALL_MASK, "C", NULL);
  126.         my_de_l = newlocale(LC_ALL_MASK, "German", NULL);
  127. #else
  128.         my_en_l = newlocale(LC_ALL_MASK, "en_US.UTF-8", NULL);
  129.         my_de_l = newlocale(LC_ALL_MASK, "de_DE.UTF-8", NULL);
  130. #endif /* EMULATE_POSIX_NEWLOCALE_ON_WINDOWS */
  131.         if ((my_en_l == (locale_t)0) || (my_de_l == (locale_t)0)) {
  132.                 fprintf(stderr, "Could not create locale object [%s], %tx/%tx",
  133.                         strerror(errno),
  134.                         (ptrdiff_t)((char*)my_en_l-0),
  135.                         (ptrdiff_t)((char*)my_de_l-0));
  136.                 return EXIT_FAILURE;
  137.         }
  138. #if 0
  139.         (void)printf("de_DE locale decimal_point=|%s|\n",
  140.                 my_de_l->locinfo->lconv->decimal_point);
  141. #endif
  142.         x = 123456.789123456789;
  143.         (void)printf_l(my_en_l, "%8.8f\n", x);
  144.         (void)printf_l(my_de_l, "%8.8f\n", x);
  145.  
  146.         /*
  147.          * If we use |uselocale()| we must set the current thread
  148.          * locale to something else before freeing the current
  149.          * locale_t object!!
  150.          */
  151.         freelocale(my_de_l);
  152.         freelocale(my_en_l);
  153.  
  154.         (void)puts("# thread_multi_locale1: done.");
  155.  
  156.         return EXIT_SUCCESS;
  157. }

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at