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