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