poptint.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include "system.h"
  2. #include <stdarg.h>
  3. #include "poptint.h"
  4. /* Any pair of 32 bit hashes can be used. lookup3.c generates pairs, will do. */
  5. #define _JLU3_jlu32lpair 1
  6. #define jlu32lpair poptJlu32lpair
  7. #include "lookup3.c"
  8. /*@-varuse +charint +ignoresigns @*/
  9. /*@unchecked@*/ /*@observer@*/
  10. static const unsigned char utf8_skip_data[256] = {
  11. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  12. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  13. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  14. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  15. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  16. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  17. 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  18. 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
  19. };
  20. /*@=varuse =charint =ignoresigns @*/
  21. const char *
  22. POPT_prev_char (const char *str)
  23. {
  24. const char *p = str;
  25. while (1) {
  26. p--;
  27. if (((unsigned)*p & 0xc0) != (unsigned)0x80)
  28. return p;
  29. }
  30. }
  31. const char *
  32. POPT_next_char (const char *str)
  33. {
  34. const char *p = str;
  35. while (*p != '\0') {
  36. p++;
  37. if (((unsigned)*p & 0xc0) != (unsigned)0x80)
  38. break;
  39. }
  40. return p;
  41. }
  42. #if !defined(POPT_fprintf) /* XXX lose all the goop ... */
  43. #if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
  44. /*
  45. * Rebind a "UTF-8" codeset for popt's internal use.
  46. */
  47. char *
  48. POPT_dgettext(const char * dom, const char * str)
  49. {
  50. char * codeset = NULL;
  51. char * retval = NULL;
  52. if (!dom)
  53. dom = textdomain(NULL);
  54. codeset = bind_textdomain_codeset(dom, NULL);
  55. bind_textdomain_codeset(dom, "UTF-8");
  56. retval = dgettext(dom, str);
  57. bind_textdomain_codeset(dom, codeset);
  58. return retval;
  59. }
  60. #endif
  61. #ifdef HAVE_ICONV
  62. /**
  63. * Return malloc'd string converted from UTF-8 to current locale.
  64. * @param istr input string (UTF-8 encoding assumed)
  65. * @return localized string
  66. */
  67. static /*@only@*/ /*@null@*/ char *
  68. strdup_locale_from_utf8 (/*@null@*/ char * istr)
  69. /*@*/
  70. {
  71. char * codeset = NULL;
  72. char * ostr = NULL;
  73. iconv_t cd;
  74. if (istr == NULL)
  75. return NULL;
  76. #ifdef HAVE_LANGINFO_H
  77. codeset = nl_langinfo ((nl_item)CODESET);
  78. #endif
  79. if (codeset != NULL && strcmp(codeset, "UTF-8") != 0
  80. && (cd = iconv_open(codeset, "UTF-8")) != (iconv_t)-1)
  81. {
  82. char * shift_pin = NULL;
  83. size_t db = strlen(istr);
  84. /*@owned@*/
  85. char * dstr = malloc((db + 1) * sizeof(*dstr));
  86. char * pin = istr;
  87. char * pout = dstr;
  88. size_t ib = db;
  89. size_t ob = db;
  90. size_t err;
  91. if (dstr == NULL)
  92. return NULL;
  93. err = iconv(cd, NULL, NULL, NULL, NULL);
  94. while (1) {
  95. *pout = '\0';
  96. err = iconv(cd, &pin, &ib, &pout, &ob);
  97. if (err != (size_t)-1) {
  98. if (shift_pin == NULL) {
  99. shift_pin = pin;
  100. pin = NULL;
  101. ib = 0;
  102. continue;
  103. }
  104. } else
  105. switch (errno) {
  106. case E2BIG:
  107. { size_t used = (size_t)(pout - dstr);
  108. db *= 2;
  109. dstr = realloc(dstr, (db + 1) * sizeof(*dstr));
  110. if (dstr != NULL) {
  111. pout = dstr + used;
  112. ob = db - used;
  113. continue;
  114. }
  115. } /*@switchbreak@*/ break;
  116. case EINVAL:
  117. case EILSEQ:
  118. default:
  119. /*@switchbreak@*/ break;
  120. }
  121. break;
  122. }
  123. (void) iconv_close(cd);
  124. *pout = '\0';
  125. ostr = xstrdup(dstr);
  126. free(dstr);
  127. } else
  128. ostr = xstrdup(istr);
  129. return ostr;
  130. }
  131. #endif
  132. int
  133. POPT_fprintf (FILE * stream, const char * format, ...)
  134. {
  135. char * b = NULL, * ob = NULL;
  136. int rc;
  137. va_list ap;
  138. #if defined(HAVE_VASPRINTF) && !defined(__LCLINT__)
  139. va_start(ap, format);
  140. if ((rc = vasprintf(&b, format, ap)) < 0)
  141. b = NULL;
  142. va_end(ap);
  143. #else
  144. size_t nb = (size_t)1;
  145. /* HACK: add +1 to the realloc no. of bytes "just in case". */
  146. /* XXX Likely unneeded, the issues wrto vsnprintf(3) return b0rkage have
  147. * to do with whether the final '\0' is counted (or not). The code
  148. * below already adds +1 for the (possibly already counted) trailing NUL.
  149. */
  150. while ((b = realloc(b, nb+1)) != NULL) {
  151. va_start(ap, format);
  152. rc = vsnprintf(b, nb, format, ap);
  153. va_end(ap);
  154. if (rc > -1) { /* glibc 2.1 */
  155. if ((size_t)rc < nb)
  156. break;
  157. nb = (size_t)(rc + 1); /* precise buffer length known */
  158. } else /* glibc 2.0 */
  159. nb += (nb < (size_t)100 ? (size_t)100 : nb);
  160. ob = b;
  161. }
  162. #endif
  163. rc = 0;
  164. if (b != NULL) {
  165. #ifdef HAVE_ICONV
  166. ob = strdup_locale_from_utf8(b);
  167. if (ob != NULL) {
  168. rc = fprintf(stream, "%s", ob);
  169. free(ob);
  170. } else
  171. #endif
  172. rc = fprintf(stream, "%s", b);
  173. free (b);
  174. }
  175. return rc;
  176. }
  177. #endif /* !defined(POPT_fprintf) */