~ubuntu-branches/ubuntu/precise/wget/precise-proposed

« back to all changes in this revision

Viewing changes to lib/mbrtowc.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-10-19 00:00:09 UTC
  • mfrom: (2.1.13 sid)
  • Revision ID: james.westby@ubuntu.com-20111019000009-8p33w3wz4b1rdri0
Tags: 1.13-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add wget-udeb to ship wget.gnu as alternative to busybox wget
    implementation.
  - Depend on libssl-dev 0.9.8k-7ubuntu4 (LP: #503339)
* Dropped changes, superseded in Debian:
  - Keep build dependencies in main:
    + debian/control: remove info2man build-dep
    + debian/patches/series: disable wget-infopod_generated_manpage
  - Mark wget Multi-Arch: foreign, so packages that aren't of the same arch
    can depend on it.
* Pass --with-ssl=openssl; we don't want to use gnutls, there's no udeb for
  it.
* Add a second build pass for the udeb, so we can build without libidn.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Convert multibyte character to wide character.
2
 
   Copyright (C) 1999-2002, 2005-2009 Free Software Foundation, Inc.
 
2
   Copyright (C) 1999-2002, 2005-2011 Free Software Foundation, Inc.
3
3
   Written by Bruno Haible <bruno@clisp.org>, 2008.
4
4
 
5
5
   This program is free software: you can redistribute it and/or modify
40
40
{
41
41
  char *pstate = (char *)ps;
42
42
 
43
 
  if (pstate == NULL)
44
 
    pstate = internal_state;
45
 
 
46
43
  if (s == NULL)
47
44
    {
48
45
      pwc = NULL;
54
51
    return (size_t)(-2);
55
52
 
56
53
  /* Here n > 0.  */
 
54
 
 
55
  if (pstate == NULL)
 
56
    pstate = internal_state;
 
57
 
57
58
  {
58
59
    size_t nstate = pstate[0];
59
60
    char buf[4];
63
64
    switch (nstate)
64
65
      {
65
66
      case 0:
66
 
        p = s;
67
 
        m = n;
68
 
        break;
 
67
        p = s;
 
68
        m = n;
 
69
        break;
69
70
      case 3:
70
 
        buf[2] = pstate[3];
71
 
        /*FALLTHROUGH*/
 
71
        buf[2] = pstate[3];
 
72
        /*FALLTHROUGH*/
72
73
      case 2:
73
 
        buf[1] = pstate[2];
74
 
        /*FALLTHROUGH*/
 
74
        buf[1] = pstate[2];
 
75
        /*FALLTHROUGH*/
75
76
      case 1:
76
 
        buf[0] = pstate[1];
77
 
        p = buf;
78
 
        m = nstate;
79
 
        buf[m++] = s[0];
80
 
        if (n >= 2 && m < 4)
81
 
          {
82
 
            buf[m++] = s[1];
83
 
            if (n >= 3 && m < 4)
84
 
              buf[m++] = s[2];
85
 
          }
86
 
        break;
 
77
        buf[0] = pstate[1];
 
78
        p = buf;
 
79
        m = nstate;
 
80
        buf[m++] = s[0];
 
81
        if (n >= 2 && m < 4)
 
82
          {
 
83
            buf[m++] = s[1];
 
84
            if (n >= 3 && m < 4)
 
85
              buf[m++] = s[2];
 
86
          }
 
87
        break;
87
88
      default:
88
 
        errno = EINVAL;
89
 
        return (size_t)(-1);
 
89
        errno = EINVAL;
 
90
        return (size_t)(-1);
90
91
      }
91
92
 
92
93
    /* Here m > 0.  */
93
94
 
94
 
# if __GLIBC__
 
95
# if __GLIBC__ || defined __UCLIBC__
95
96
    /* Work around bug <http://sourceware.org/bugzilla/show_bug.cgi?id=9674> */
96
97
    mbtowc (NULL, NULL, 0);
97
98
# endif
99
100
      int res = mbtowc (pwc, p, m);
100
101
 
101
102
      if (res >= 0)
102
 
        {
103
 
          if (pwc != NULL && ((*pwc == 0) != (res == 0)))
104
 
            abort ();
105
 
          if (nstate >= (res > 0 ? res : 1))
106
 
            abort ();
107
 
          res -= nstate;
108
 
          pstate[0] = 0;
109
 
          return res;
110
 
        }
 
103
        {
 
104
          if (pwc != NULL && ((*pwc == 0) != (res == 0)))
 
105
            abort ();
 
106
          if (nstate >= (res > 0 ? res : 1))
 
107
            abort ();
 
108
          res -= nstate;
 
109
          pstate[0] = 0;
 
110
          return res;
 
111
        }
111
112
 
112
113
      /* mbtowc does not distinguish between invalid and incomplete multibyte
113
 
         sequences.  But mbrtowc needs to make this distinction.
114
 
         There are two possible approaches:
115
 
           - Use iconv() and its return value.
116
 
           - Use built-in knowledge about the possible encodings.
117
 
         Given the low quality of implementation of iconv() on the systems that
118
 
         lack mbrtowc(), we use the second approach.
119
 
         The possible encodings are:
120
 
           - 8-bit encodings,
121
 
           - EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS,
122
 
           - UTF-8.
123
 
         Use specialized code for each.  */
 
114
         sequences.  But mbrtowc needs to make this distinction.
 
115
         There are two possible approaches:
 
116
           - Use iconv() and its return value.
 
117
           - Use built-in knowledge about the possible encodings.
 
118
         Given the low quality of implementation of iconv() on the systems that
 
119
         lack mbrtowc(), we use the second approach.
 
120
         The possible encodings are:
 
121
           - 8-bit encodings,
 
122
           - EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS,
 
123
           - UTF-8.
 
124
         Use specialized code for each.  */
124
125
      if (m >= 4 || m >= MB_CUR_MAX)
125
 
        goto invalid;
 
126
        goto invalid;
126
127
      /* Here MB_CUR_MAX > 1 and 0 < m < 4.  */
127
128
      {
128
 
        const char *encoding = locale_charset ();
129
 
 
130
 
        if (STREQ (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0))
131
 
          {
132
 
            /* Cf. unistr/u8-mblen.c.  */
133
 
            unsigned char c = (unsigned char) p[0];
134
 
 
135
 
            if (c >= 0xc2)
136
 
              {
137
 
                if (c < 0xe0)
138
 
                  {
139
 
                    if (m == 1)
140
 
                      goto incomplete;
141
 
                  }
142
 
                else if (c < 0xf0)
143
 
                  {
144
 
                    if (m == 1)
145
 
                      goto incomplete;
146
 
                    if (m == 2)
147
 
                      {
148
 
                        unsigned char c2 = (unsigned char) p[1];
149
 
 
150
 
                        if ((c2 ^ 0x80) < 0x40
151
 
                            && (c >= 0xe1 || c2 >= 0xa0)
152
 
                            && (c != 0xed || c2 < 0xa0))
153
 
                          goto incomplete;
154
 
                      }
155
 
                  }
156
 
                else if (c <= 0xf4)
157
 
                  {
158
 
                    if (m == 1)
159
 
                      goto incomplete;
160
 
                    else /* m == 2 || m == 3 */
161
 
                      {
162
 
                        unsigned char c2 = (unsigned char) p[1];
163
 
 
164
 
                        if ((c2 ^ 0x80) < 0x40
165
 
                            && (c >= 0xf1 || c2 >= 0x90)
166
 
                            && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
167
 
                          {
168
 
                            if (m == 2)
169
 
                              goto incomplete;
170
 
                            else /* m == 3 */
171
 
                              {
172
 
                                unsigned char c3 = (unsigned char) p[2];
173
 
 
174
 
                                if ((c3 ^ 0x80) < 0x40)
175
 
                                  goto incomplete;
176
 
                              }
177
 
                          }
178
 
                      }
179
 
                  }
180
 
              }
181
 
            goto invalid;
182
 
          }
183
 
 
184
 
        /* As a reference for this code, you can use the GNU libiconv
185
 
           implementation.  Look for uses of the RET_TOOFEW macro.  */
186
 
 
187
 
        if (STREQ (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0))
188
 
          {
189
 
            if (m == 1)
190
 
              {
191
 
                unsigned char c = (unsigned char) p[0];
192
 
 
193
 
                if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f)
194
 
                  goto incomplete;
195
 
              }
196
 
            if (m == 2)
197
 
              {
198
 
                unsigned char c = (unsigned char) p[0];
199
 
 
200
 
                if (c == 0x8f)
201
 
                  {
202
 
                    unsigned char c2 = (unsigned char) p[1];
203
 
 
204
 
                    if (c2 >= 0xa1 && c2 < 0xff)
205
 
                      goto incomplete;
206
 
                  }
207
 
              }
208
 
            goto invalid;
209
 
          }
210
 
        if (STREQ (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0)
211
 
            || STREQ (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0)
212
 
            || STREQ (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0))
213
 
          {
214
 
            if (m == 1)
215
 
              {
216
 
                unsigned char c = (unsigned char) p[0];
217
 
 
218
 
                if (c >= 0xa1 && c < 0xff)
219
 
                  goto incomplete;
220
 
              }
221
 
            goto invalid;
222
 
          }
223
 
        if (STREQ (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0))
224
 
          {
225
 
            if (m == 1)
226
 
              {
227
 
                unsigned char c = (unsigned char) p[0];
228
 
 
229
 
                if ((c >= 0xa1 && c < 0xff) || c == 0x8e)
230
 
                  goto incomplete;
231
 
              }
232
 
            else /* m == 2 || m == 3 */
233
 
              {
234
 
                unsigned char c = (unsigned char) p[0];
235
 
 
236
 
                if (c == 0x8e)
237
 
                  goto incomplete;
238
 
              }
239
 
            goto invalid;
240
 
          }
241
 
        if (STREQ (encoding, "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0))
242
 
          {
243
 
            if (m == 1)
244
 
              {
245
 
                unsigned char c = (unsigned char) p[0];
246
 
 
247
 
                if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe))
248
 
                  goto incomplete;
249
 
              }
250
 
            else /* m == 2 || m == 3 */
251
 
              {
252
 
                unsigned char c = (unsigned char) p[0];
253
 
 
254
 
                if (c >= 0x90 && c <= 0xe3)
255
 
                  {
256
 
                    unsigned char c2 = (unsigned char) p[1];
257
 
 
258
 
                    if (c2 >= 0x30 && c2 <= 0x39)
259
 
                      {
260
 
                        if (m == 2)
261
 
                          goto incomplete;
262
 
                        else /* m == 3 */
263
 
                          {
264
 
                            unsigned char c3 = (unsigned char) p[2];
265
 
 
266
 
                            if (c3 >= 0x81 && c3 <= 0xfe)
267
 
                              goto incomplete;
268
 
                          }
269
 
                      }
270
 
                  }
271
 
              }
272
 
            goto invalid;
273
 
          }
274
 
        if (STREQ (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0))
275
 
          {
276
 
            if (m == 1)
277
 
              {
278
 
                unsigned char c = (unsigned char) p[0];
279
 
 
280
 
                if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea)
281
 
                    || (c >= 0xf0 && c <= 0xf9))
282
 
                  goto incomplete;
283
 
              }
284
 
            goto invalid;
285
 
          }
286
 
 
287
 
        /* An unknown multibyte encoding.  */
288
 
        goto incomplete;
 
129
        const char *encoding = locale_charset ();
 
130
 
 
131
        if (STREQ (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0))
 
132
          {
 
133
            /* Cf. unistr/u8-mblen.c.  */
 
134
            unsigned char c = (unsigned char) p[0];
 
135
 
 
136
            if (c >= 0xc2)
 
137
              {
 
138
                if (c < 0xe0)
 
139
                  {
 
140
                    if (m == 1)
 
141
                      goto incomplete;
 
142
                  }
 
143
                else if (c < 0xf0)
 
144
                  {
 
145
                    if (m == 1)
 
146
                      goto incomplete;
 
147
                    if (m == 2)
 
148
                      {
 
149
                        unsigned char c2 = (unsigned char) p[1];
 
150
 
 
151
                        if ((c2 ^ 0x80) < 0x40
 
152
                            && (c >= 0xe1 || c2 >= 0xa0)
 
153
                            && (c != 0xed || c2 < 0xa0))
 
154
                          goto incomplete;
 
155
                      }
 
156
                  }
 
157
                else if (c <= 0xf4)
 
158
                  {
 
159
                    if (m == 1)
 
160
                      goto incomplete;
 
161
                    else /* m == 2 || m == 3 */
 
162
                      {
 
163
                        unsigned char c2 = (unsigned char) p[1];
 
164
 
 
165
                        if ((c2 ^ 0x80) < 0x40
 
166
                            && (c >= 0xf1 || c2 >= 0x90)
 
167
                            && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
 
168
                          {
 
169
                            if (m == 2)
 
170
                              goto incomplete;
 
171
                            else /* m == 3 */
 
172
                              {
 
173
                                unsigned char c3 = (unsigned char) p[2];
 
174
 
 
175
                                if ((c3 ^ 0x80) < 0x40)
 
176
                                  goto incomplete;
 
177
                              }
 
178
                          }
 
179
                      }
 
180
                  }
 
181
              }
 
182
            goto invalid;
 
183
          }
 
184
 
 
185
        /* As a reference for this code, you can use the GNU libiconv
 
186
           implementation.  Look for uses of the RET_TOOFEW macro.  */
 
187
 
 
188
        if (STREQ (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0))
 
189
          {
 
190
            if (m == 1)
 
191
              {
 
192
                unsigned char c = (unsigned char) p[0];
 
193
 
 
194
                if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f)
 
195
                  goto incomplete;
 
196
              }
 
197
            if (m == 2)
 
198
              {
 
199
                unsigned char c = (unsigned char) p[0];
 
200
 
 
201
                if (c == 0x8f)
 
202
                  {
 
203
                    unsigned char c2 = (unsigned char) p[1];
 
204
 
 
205
                    if (c2 >= 0xa1 && c2 < 0xff)
 
206
                      goto incomplete;
 
207
                  }
 
208
              }
 
209
            goto invalid;
 
210
          }
 
211
        if (STREQ (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0)
 
212
            || STREQ (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0)
 
213
            || STREQ (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0))
 
214
          {
 
215
            if (m == 1)
 
216
              {
 
217
                unsigned char c = (unsigned char) p[0];
 
218
 
 
219
                if (c >= 0xa1 && c < 0xff)
 
220
                  goto incomplete;
 
221
              }
 
222
            goto invalid;
 
223
          }
 
224
        if (STREQ (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0))
 
225
          {
 
226
            if (m == 1)
 
227
              {
 
228
                unsigned char c = (unsigned char) p[0];
 
229
 
 
230
                if ((c >= 0xa1 && c < 0xff) || c == 0x8e)
 
231
                  goto incomplete;
 
232
              }
 
233
            else /* m == 2 || m == 3 */
 
234
              {
 
235
                unsigned char c = (unsigned char) p[0];
 
236
 
 
237
                if (c == 0x8e)
 
238
                  goto incomplete;
 
239
              }
 
240
            goto invalid;
 
241
          }
 
242
        if (STREQ (encoding, "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0))
 
243
          {
 
244
            if (m == 1)
 
245
              {
 
246
                unsigned char c = (unsigned char) p[0];
 
247
 
 
248
                if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe))
 
249
                  goto incomplete;
 
250
              }
 
251
            else /* m == 2 || m == 3 */
 
252
              {
 
253
                unsigned char c = (unsigned char) p[0];
 
254
 
 
255
                if (c >= 0x90 && c <= 0xe3)
 
256
                  {
 
257
                    unsigned char c2 = (unsigned char) p[1];
 
258
 
 
259
                    if (c2 >= 0x30 && c2 <= 0x39)
 
260
                      {
 
261
                        if (m == 2)
 
262
                          goto incomplete;
 
263
                        else /* m == 3 */
 
264
                          {
 
265
                            unsigned char c3 = (unsigned char) p[2];
 
266
 
 
267
                            if (c3 >= 0x81 && c3 <= 0xfe)
 
268
                              goto incomplete;
 
269
                          }
 
270
                      }
 
271
                  }
 
272
              }
 
273
            goto invalid;
 
274
          }
 
275
        if (STREQ (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0))
 
276
          {
 
277
            if (m == 1)
 
278
              {
 
279
                unsigned char c = (unsigned char) p[0];
 
280
 
 
281
                if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea)
 
282
                    || (c >= 0xf0 && c <= 0xf9))
 
283
                  goto incomplete;
 
284
              }
 
285
            goto invalid;
 
286
          }
 
287
 
 
288
        /* An unknown multibyte encoding.  */
 
289
        goto incomplete;
289
290
      }
290
291
 
291
292
     incomplete:
292
293
      {
293
 
        size_t k = nstate;
294
 
        /* Here 0 <= k < m < 4.  */
295
 
        pstate[++k] = s[0];
296
 
        if (k < m)
297
 
          {
298
 
            pstate[++k] = s[1];
299
 
            if (k < m)
300
 
              pstate[++k] = s[2];
301
 
          }
302
 
        if (k != m)
303
 
          abort ();
 
294
        size_t k = nstate;
 
295
        /* Here 0 <= k < m < 4.  */
 
296
        pstate[++k] = s[0];
 
297
        if (k < m)
 
298
          {
 
299
            pstate[++k] = s[1];
 
300
            if (k < m)
 
301
              pstate[++k] = s[2];
 
302
          }
 
303
        if (k != m)
 
304
          abort ();
304
305
      }
305
306
      pstate[0] = m;
306
307
      return (size_t)(-2);
321
322
size_t
322
323
rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
323
324
{
324
 
# if MBRTOWC_NULL_ARG_BUG || MBRTOWC_RETVAL_BUG
 
325
# if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG
325
326
  if (s == NULL)
326
327
    {
327
328
      pwc = NULL;
334
335
  {
335
336
    static mbstate_t internal_state;
336
337
 
337
 
    /* Override mbrtowc's internal state.  We can not call mbsinit() on the
 
338
    /* Override mbrtowc's internal state.  We cannot call mbsinit() on the
338
339
       hidden internal state, but we can call it on our variable.  */
339
340
    if (ps == NULL)
340
341
      ps = &internal_state;
341
342
 
342
343
    if (!mbsinit (ps))
343
344
      {
344
 
        /* Parse the rest of the multibyte character byte for byte.  */
345
 
        size_t count = 0;
346
 
        for (; n > 0; s++, n--)
347
 
          {
348
 
            wchar_t wc;
349
 
            size_t ret = mbrtowc (&wc, s, 1, ps);
 
345
        /* Parse the rest of the multibyte character byte for byte.  */
 
346
        size_t count = 0;
 
347
        for (; n > 0; s++, n--)
 
348
          {
 
349
            wchar_t wc;
 
350
            size_t ret = mbrtowc (&wc, s, 1, ps);
350
351
 
351
 
            if (ret == (size_t)(-1))
352
 
              return (size_t)(-1);
353
 
            count++;
354
 
            if (ret != (size_t)(-2))
355
 
              {
356
 
                /* The multibyte character has been completed.  */
357
 
                if (pwc != NULL)
358
 
                  *pwc = wc;
359
 
                return (wc == 0 ? 0 : count);
360
 
              }
361
 
          }
362
 
        return (size_t)(-2);
 
352
            if (ret == (size_t)(-1))
 
353
              return (size_t)(-1);
 
354
            count++;
 
355
            if (ret != (size_t)(-2))
 
356
              {
 
357
                /* The multibyte character has been completed.  */
 
358
                if (pwc != NULL)
 
359
                  *pwc = wc;
 
360
                return (wc == 0 ? 0 : count);
 
361
              }
 
362
          }
 
363
        return (size_t)(-2);
363
364
      }
364
365
  }
365
366
# endif
371
372
 
372
373
    if (ret != (size_t)(-1) && ret != (size_t)(-2))
373
374
      {
374
 
        if (pwc != NULL)
375
 
          *pwc = wc;
376
 
        if (wc == 0)
377
 
          ret = 0;
 
375
        if (pwc != NULL)
 
376
          *pwc = wc;
 
377
        if (wc == 0)
 
378
          ret = 0;
378
379
      }
379
380
    return ret;
380
381
  }
381
382
# else
382
 
  return mbrtowc (pwc, s, n, ps);
 
383
  {
 
384
#   if MBRTOWC_NULL_ARG1_BUG
 
385
    wchar_t dummy;
 
386
 
 
387
    if (pwc == NULL)
 
388
      pwc = &dummy;
 
389
#   endif
 
390
 
 
391
    return mbrtowc (pwc, s, n, ps);
 
392
  }
383
393
# endif
384
394
}
385
395