(root)/
gettext-0.22.4/
gettext-tools/
gnulib-tests/
test-mbrtoc32-w32.c
       1  /* Test of conversion of multibyte character to 32-bit wide character.
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #include <config.h>
      18  
      19  #include <uchar.h>
      20  
      21  #include <errno.h>
      22  #include <locale.h>
      23  #include <stdio.h>
      24  #include <stdlib.h>
      25  #include <string.h>
      26  #include <wchar.h>
      27  
      28  #include "localcharset.h"
      29  #include "macros.h"
      30  
      31  #if defined _WIN32 && !defined __CYGWIN__
      32  
      33  static int
      34  test_one_locale (const char *name, int codepage)
      35  {
      36    mbstate_t state;
      37    char32_t wc;
      38    size_t ret;
      39  
      40  # if 1
      41    /* Portable code to set the locale.  */
      42    {
      43      char name_with_codepage[1024];
      44  
      45      sprintf (name_with_codepage, "%s.%d", name, codepage);
      46  
      47      /* Set the locale.  */
      48      if (setlocale (LC_ALL, name_with_codepage) == NULL)
      49        return 77;
      50    }
      51  # else
      52    /* Hacky way to set a locale.codepage combination that setlocale() refuses
      53       to set.  */
      54    {
      55      /* Codepage of the current locale, set with setlocale().
      56         Not necessarily the same as GetACP().  */
      57      extern __declspec(dllimport) unsigned int __lc_codepage;
      58  
      59      /* Set the locale.  */
      60      if (setlocale (LC_ALL, name) == NULL)
      61        return 77;
      62  
      63      /* Clobber the codepage and MB_CUR_MAX, both set by setlocale().  */
      64      __lc_codepage = codepage;
      65      switch (codepage)
      66        {
      67        case 1252:
      68        case 1256:
      69          MB_CUR_MAX = 1;
      70          break;
      71        case 932:
      72        case 950:
      73        case 936:
      74          MB_CUR_MAX = 2;
      75          break;
      76        case 54936:
      77        case 65001:
      78          MB_CUR_MAX = 4;
      79          break;
      80        }
      81  
      82      /* Test whether the codepage is really available.  */
      83      memset (&state, '\0', sizeof (mbstate_t));
      84      if (mbrtoc32 (&wc, " ", 1, &state) == (size_t)(-1))
      85        return 77;
      86    }
      87  # endif
      88  
      89    /* Test zero-length input.  */
      90    {
      91      memset (&state, '\0', sizeof (mbstate_t));
      92      wc = (char32_t) 0xBADFACE;
      93      ret = mbrtoc32 (&wc, "x", 0, &state);
      94      ASSERT (ret == (size_t)(-2));
      95      ASSERT (mbsinit (&state));
      96    }
      97  
      98    /* Test NUL byte input.  */
      99    {
     100      memset (&state, '\0', sizeof (mbstate_t));
     101      wc = (char32_t) 0xBADFACE;
     102      ret = mbrtoc32 (&wc, "", 1, &state);
     103      ASSERT (ret == 0);
     104      ASSERT (wc == 0);
     105      ASSERT (mbsinit (&state));
     106      ret = mbrtoc32 (NULL, "", 1, &state);
     107      ASSERT (ret == 0);
     108      ASSERT (mbsinit (&state));
     109    }
     110  
     111    /* Test single-byte input.  */
     112    {
     113      int c;
     114      char buf[1];
     115  
     116      memset (&state, '\0', sizeof (mbstate_t));
     117      for (c = 0; c < 0x100; c++)
     118        switch (c)
     119          {
     120          case '\t': case '\v': case '\f':
     121          case ' ': case '!': case '"': case '#': case '%':
     122          case '&': case '\'': case '(': case ')': case '*':
     123          case '+': case ',': case '-': case '.': case '/':
     124          case '0': case '1': case '2': case '3': case '4':
     125          case '5': case '6': case '7': case '8': case '9':
     126          case ':': case ';': case '<': case '=': case '>':
     127          case '?':
     128          case 'A': case 'B': case 'C': case 'D': case 'E':
     129          case 'F': case 'G': case 'H': case 'I': case 'J':
     130          case 'K': case 'L': case 'M': case 'N': case 'O':
     131          case 'P': case 'Q': case 'R': case 'S': case 'T':
     132          case 'U': case 'V': case 'W': case 'X': case 'Y':
     133          case 'Z':
     134          case '[': case '\\': case ']': case '^': case '_':
     135          case 'a': case 'b': case 'c': case 'd': case 'e':
     136          case 'f': case 'g': case 'h': case 'i': case 'j':
     137          case 'k': case 'l': case 'm': case 'n': case 'o':
     138          case 'p': case 'q': case 'r': case 's': case 't':
     139          case 'u': case 'v': case 'w': case 'x': case 'y':
     140          case 'z': case '{': case '|': case '}': case '~':
     141            /* c is in the ISO C "basic character set".  */
     142            buf[0] = c;
     143            wc = (char32_t) 0xBADFACE;
     144            ret = mbrtoc32 (&wc, buf, 1, &state);
     145            ASSERT (ret == 1);
     146            ASSERT (wc == c);
     147            ASSERT (mbsinit (&state));
     148            ret = mbrtoc32 (NULL, buf, 1, &state);
     149            ASSERT (ret == 1);
     150            ASSERT (mbsinit (&state));
     151            break;
     152          }
     153    }
     154  
     155    /* Test special calling convention, passing a NULL pointer.  */
     156    {
     157      memset (&state, '\0', sizeof (mbstate_t));
     158      wc = (char32_t) 0xBADFACE;
     159      ret = mbrtoc32 (&wc, NULL, 5, &state);
     160      ASSERT (ret == 0);
     161      ASSERT (wc == (char32_t) 0xBADFACE);
     162      ASSERT (mbsinit (&state));
     163    }
     164  
     165    switch (codepage)
     166      {
     167      case 1252:
     168        /* Locale encoding is CP1252, an extension of ISO-8859-1.  */
     169        {
     170          char input[] = "B\374\337er"; /* "Büßer" */
     171          memset (&state, '\0', sizeof (mbstate_t));
     172  
     173          wc = (char32_t) 0xBADFACE;
     174          ret = mbrtoc32 (&wc, input, 1, &state);
     175          ASSERT (ret == 1);
     176          ASSERT (wc == 'B');
     177          ASSERT (mbsinit (&state));
     178          input[0] = '\0';
     179  
     180          wc = (char32_t) 0xBADFACE;
     181          ret = mbrtoc32 (&wc, input + 1, 1, &state);
     182          ASSERT (ret == 1);
     183          ASSERT (c32tob (wc) == (unsigned char) '\374');
     184          ASSERT (wc == 0x00FC); /* expect Unicode encoding */
     185          ASSERT (mbsinit (&state));
     186          input[1] = '\0';
     187  
     188          /* Test support of NULL first argument.  */
     189          ret = mbrtoc32 (NULL, input + 2, 3, &state);
     190          ASSERT (ret == 1);
     191          ASSERT (mbsinit (&state));
     192  
     193          wc = (char32_t) 0xBADFACE;
     194          ret = mbrtoc32 (&wc, input + 2, 3, &state);
     195          ASSERT (ret == 1);
     196          ASSERT (c32tob (wc) == (unsigned char) '\337');
     197          ASSERT (wc == 0x00DF); /* expect Unicode encoding */
     198          ASSERT (mbsinit (&state));
     199          input[2] = '\0';
     200  
     201          wc = (char32_t) 0xBADFACE;
     202          ret = mbrtoc32 (&wc, input + 3, 2, &state);
     203          ASSERT (ret == 1);
     204          ASSERT (wc == 'e');
     205          ASSERT (mbsinit (&state));
     206          input[3] = '\0';
     207  
     208          wc = (char32_t) 0xBADFACE;
     209          ret = mbrtoc32 (&wc, input + 4, 1, &state);
     210          ASSERT (ret == 1);
     211          ASSERT (wc == 'r');
     212          ASSERT (mbsinit (&state));
     213        }
     214        return 0;
     215  
     216      case 1256:
     217        /* Locale encoding is CP1256, not the same as ISO-8859-6.  */
     218        {
     219          char input[] = "x\302\341\346y"; /* "xآلوy" */
     220          memset (&state, '\0', sizeof (mbstate_t));
     221  
     222          wc = (char32_t) 0xBADFACE;
     223          ret = mbrtoc32 (&wc, input, 1, &state);
     224          ASSERT (ret == 1);
     225          ASSERT (wc == 'x');
     226          ASSERT (mbsinit (&state));
     227          input[0] = '\0';
     228  
     229          wc = (char32_t) 0xBADFACE;
     230          ret = mbrtoc32 (&wc, input + 1, 1, &state);
     231          ASSERT (ret == 1);
     232          ASSERT (c32tob (wc) == (unsigned char) '\302');
     233          ASSERT (wc == 0x0622); /* expect Unicode encoding */
     234          ASSERT (mbsinit (&state));
     235          input[1] = '\0';
     236  
     237          /* Test support of NULL first argument.  */
     238          ret = mbrtoc32 (NULL, input + 2, 3, &state);
     239          ASSERT (ret == 1);
     240          ASSERT (mbsinit (&state));
     241  
     242          wc = (char32_t) 0xBADFACE;
     243          ret = mbrtoc32 (&wc, input + 2, 3, &state);
     244          ASSERT (ret == 1);
     245          ASSERT (c32tob (wc) == (unsigned char) '\341');
     246          ASSERT (wc == 0x0644); /* expect Unicode encoding */
     247          ASSERT (mbsinit (&state));
     248          input[2] = '\0';
     249  
     250          wc = (char32_t) 0xBADFACE;
     251          ret = mbrtoc32 (&wc, input + 3, 2, &state);
     252          ASSERT (ret == 1);
     253          ASSERT (c32tob (wc) == (unsigned char) '\346');
     254          ASSERT (wc == 0x0648); /* expect Unicode encoding */
     255          ASSERT (mbsinit (&state));
     256          input[3] = '\0';
     257  
     258          wc = (char32_t) 0xBADFACE;
     259          ret = mbrtoc32 (&wc, input + 4, 1, &state);
     260          ASSERT (ret == 1);
     261          ASSERT (wc == 'y');
     262          ASSERT (mbsinit (&state));
     263        }
     264        return 0;
     265  
     266      case 65001:
     267        /* Locale encoding is CP65001 = UTF-8.  */
     268        if (strcmp (locale_charset (), "UTF-8") != 0)
     269          return 77;
     270        {
     271          char input[] = "s\303\274\303\237\360\237\230\213!"; /* "süß😋!" */
     272          memset (&state, '\0', sizeof (mbstate_t));
     273  
     274          wc = (char32_t) 0xBADFACE;
     275          ret = mbrtoc32 (&wc, input, 1, &state);
     276          ASSERT (ret == 1);
     277          ASSERT (wc == 's');
     278          ASSERT (mbsinit (&state));
     279          input[0] = '\0';
     280  
     281          wc = (char32_t) 0xBADFACE;
     282          ret = mbrtoc32 (&wc, input + 1, 1, &state);
     283          ASSERT (ret == (size_t)(-2));
     284          ASSERT (wc == (char32_t) 0xBADFACE);
     285          ASSERT (!mbsinit (&state));
     286          input[1] = '\0';
     287  
     288          wc = (char32_t) 0xBADFACE;
     289          ret = mbrtoc32 (&wc, input + 2, 7, &state);
     290          ASSERT (ret == 1);
     291          ASSERT (c32tob (wc) == EOF);
     292          ASSERT (wc == 0x00FC); /* expect Unicode encoding */
     293          ASSERT (mbsinit (&state));
     294          input[2] = '\0';
     295  
     296          /* Test support of NULL first argument.  */
     297          ret = mbrtoc32 (NULL, input + 3, 6, &state);
     298          ASSERT (ret == 2);
     299          ASSERT (mbsinit (&state));
     300  
     301          wc = (char32_t) 0xBADFACE;
     302          ret = mbrtoc32 (&wc, input + 3, 6, &state);
     303          ASSERT (ret == 2);
     304          ASSERT (c32tob (wc) == EOF);
     305          ASSERT (wc == 0x00DF); /* expect Unicode encoding */
     306          ASSERT (mbsinit (&state));
     307          input[3] = '\0';
     308          input[4] = '\0';
     309  
     310          /* Test support of NULL first argument.  */
     311          ret = mbrtoc32 (NULL, input + 5, 4, &state);
     312          ASSERT (ret == 4);
     313          ASSERT (mbsinit (&state));
     314  
     315          wc = (char32_t) 0xBADFACE;
     316          ret = mbrtoc32 (&wc, input + 5, 4, &state);
     317          ASSERT (ret == 4);
     318          ASSERT (c32tob (wc) == EOF);
     319          ASSERT (wc == 0x1F60B); /* expect Unicode encoding */
     320          ASSERT (mbsinit (&state));
     321          input[5] = '\0';
     322          input[6] = '\0';
     323          input[7] = '\0';
     324          input[8] = '\0';
     325  
     326          wc = (char32_t) 0xBADFACE;
     327          ret = mbrtoc32 (&wc, input + 9, 1, &state);
     328          ASSERT (ret == 1);
     329          ASSERT (wc == '!');
     330          ASSERT (mbsinit (&state));
     331  
     332          /* Test some invalid input.  */
     333          memset (&state, '\0', sizeof (mbstate_t));
     334          wc = (char32_t) 0xBADFACE;
     335          ret = mbrtoc32 (&wc, "\377", 1, &state); /* 0xFF */
     336          ASSERT (ret == (size_t)-1);
     337          ASSERT (errno == EILSEQ);
     338  
     339          memset (&state, '\0', sizeof (mbstate_t));
     340          wc = (char32_t) 0xBADFACE;
     341          ret = mbrtoc32 (&wc, "\303\300", 2, &state); /* 0xC3 0xC0 */
     342          ASSERT (ret == (size_t)-1);
     343          ASSERT (errno == EILSEQ);
     344  
     345          memset (&state, '\0', sizeof (mbstate_t));
     346          wc = (char32_t) 0xBADFACE;
     347          ret = mbrtoc32 (&wc, "\343\300", 2, &state); /* 0xE3 0xC0 */
     348          ASSERT (ret == (size_t)-1);
     349          ASSERT (errno == EILSEQ);
     350  
     351          memset (&state, '\0', sizeof (mbstate_t));
     352          wc = (char32_t) 0xBADFACE;
     353          ret = mbrtoc32 (&wc, "\343\300\200", 3, &state); /* 0xE3 0xC0 0x80 */
     354          ASSERT (ret == (size_t)-1);
     355          ASSERT (errno == EILSEQ);
     356  
     357          memset (&state, '\0', sizeof (mbstate_t));
     358          wc = (char32_t) 0xBADFACE;
     359          ret = mbrtoc32 (&wc, "\343\200\300", 3, &state); /* 0xE3 0x80 0xC0 */
     360          ASSERT (ret == (size_t)-1);
     361          ASSERT (errno == EILSEQ);
     362  
     363          memset (&state, '\0', sizeof (mbstate_t));
     364          wc = (char32_t) 0xBADFACE;
     365          ret = mbrtoc32 (&wc, "\363\300", 2, &state); /* 0xF3 0xC0 */
     366          ASSERT (ret == (size_t)-1);
     367          ASSERT (errno == EILSEQ);
     368  
     369          memset (&state, '\0', sizeof (mbstate_t));
     370          wc = (char32_t) 0xBADFACE;
     371          ret = mbrtoc32 (&wc, "\363\300\200\200", 4, &state); /* 0xF3 0xC0 0x80 0x80 */
     372          ASSERT (ret == (size_t)-1);
     373          ASSERT (errno == EILSEQ);
     374  
     375          memset (&state, '\0', sizeof (mbstate_t));
     376          wc = (char32_t) 0xBADFACE;
     377          ret = mbrtoc32 (&wc, "\363\200\300", 3, &state); /* 0xF3 0x80 0xC0 */
     378          ASSERT (ret == (size_t)-1);
     379          ASSERT (errno == EILSEQ);
     380  
     381          memset (&state, '\0', sizeof (mbstate_t));
     382          wc = (char32_t) 0xBADFACE;
     383          ret = mbrtoc32 (&wc, "\363\200\300\200", 4, &state); /* 0xF3 0x80 0xC0 0x80 */
     384          ASSERT (ret == (size_t)-1);
     385          ASSERT (errno == EILSEQ);
     386  
     387          memset (&state, '\0', sizeof (mbstate_t));
     388          wc = (char32_t) 0xBADFACE;
     389          ret = mbrtoc32 (&wc, "\363\200\200\300", 4, &state); /* 0xF3 0x80 0x80 0xC0 */
     390          ASSERT (ret == (size_t)-1);
     391          ASSERT (errno == EILSEQ);
     392        }
     393        return 0;
     394  
     395      case 932:
     396        /* Locale encoding is CP932, similar to Shift_JIS.  */
     397        {
     398          char input[] = "<\223\372\226\173\214\352>"; /* "<日本語>" */
     399          memset (&state, '\0', sizeof (mbstate_t));
     400  
     401          wc = (char32_t) 0xBADFACE;
     402          ret = mbrtoc32 (&wc, input, 1, &state);
     403          ASSERT (ret == 1);
     404          ASSERT (wc == '<');
     405          ASSERT (mbsinit (&state));
     406          input[0] = '\0';
     407  
     408          wc = (char32_t) 0xBADFACE;
     409          ret = mbrtoc32 (&wc, input + 1, 2, &state);
     410          ASSERT (ret == 2);
     411          ASSERT (c32tob (wc) == EOF);
     412          ASSERT (wc == 0x65E5); /* expect Unicode encoding */
     413          ASSERT (mbsinit (&state));
     414          input[1] = '\0';
     415          input[2] = '\0';
     416  
     417          wc = (char32_t) 0xBADFACE;
     418          ret = mbrtoc32 (&wc, input + 3, 1, &state);
     419          ASSERT (ret == (size_t)(-2));
     420          ASSERT (wc == (char32_t) 0xBADFACE);
     421          ASSERT (!mbsinit (&state));
     422          input[3] = '\0';
     423  
     424          wc = (char32_t) 0xBADFACE;
     425          ret = mbrtoc32 (&wc, input + 4, 4, &state);
     426          ASSERT (ret == 1);
     427          ASSERT (c32tob (wc) == EOF);
     428          ASSERT (wc == 0x672C); /* expect Unicode encoding */
     429          ASSERT (mbsinit (&state));
     430          input[4] = '\0';
     431  
     432          /* Test support of NULL first argument.  */
     433          ret = mbrtoc32 (NULL, input + 5, 3, &state);
     434          ASSERT (ret == 2);
     435          ASSERT (mbsinit (&state));
     436  
     437          wc = (char32_t) 0xBADFACE;
     438          ret = mbrtoc32 (&wc, input + 5, 3, &state);
     439          ASSERT (ret == 2);
     440          ASSERT (c32tob (wc) == EOF);
     441          ASSERT (wc == 0x8A9E); /* expect Unicode encoding */
     442          ASSERT (mbsinit (&state));
     443          input[5] = '\0';
     444          input[6] = '\0';
     445  
     446          wc = (char32_t) 0xBADFACE;
     447          ret = mbrtoc32 (&wc, input + 7, 1, &state);
     448          ASSERT (ret == 1);
     449          ASSERT (wc == '>');
     450          ASSERT (mbsinit (&state));
     451  
     452          /* Test some invalid input.  */
     453          memset (&state, '\0', sizeof (mbstate_t));
     454          wc = (char32_t) 0xBADFACE;
     455          ret = mbrtoc32 (&wc, "\377", 1, &state); /* 0xFF */
     456          ASSERT ((ret == (size_t)-1 && errno == EILSEQ) || ret == (size_t)-2);
     457  
     458          memset (&state, '\0', sizeof (mbstate_t));
     459          wc = (char32_t) 0xBADFACE;
     460          ret = mbrtoc32 (&wc, "\225\377", 2, &state); /* 0x95 0xFF */
     461          ASSERT ((ret == (size_t)-1 && errno == EILSEQ) || (ret == 2 && wc == 0x30FB));
     462        }
     463        return 0;
     464  
     465      case 950:
     466        /* Locale encoding is CP950, similar to Big5.  */
     467        {
     468          char input[] = "<\244\351\245\273\273\171>"; /* "<日本語>" */
     469          memset (&state, '\0', sizeof (mbstate_t));
     470  
     471          wc = (char32_t) 0xBADFACE;
     472          ret = mbrtoc32 (&wc, input, 1, &state);
     473          ASSERT (ret == 1);
     474          ASSERT (wc == '<');
     475          ASSERT (mbsinit (&state));
     476          input[0] = '\0';
     477  
     478          wc = (char32_t) 0xBADFACE;
     479          ret = mbrtoc32 (&wc, input + 1, 2, &state);
     480          ASSERT (ret == 2);
     481          ASSERT (c32tob (wc) == EOF);
     482          ASSERT (wc == 0x65E5); /* expect Unicode encoding */
     483          ASSERT (mbsinit (&state));
     484          input[1] = '\0';
     485          input[2] = '\0';
     486  
     487          wc = (char32_t) 0xBADFACE;
     488          ret = mbrtoc32 (&wc, input + 3, 1, &state);
     489          ASSERT (ret == (size_t)(-2));
     490          ASSERT (wc == (char32_t) 0xBADFACE);
     491          ASSERT (!mbsinit (&state));
     492          input[3] = '\0';
     493  
     494          wc = (char32_t) 0xBADFACE;
     495          ret = mbrtoc32 (&wc, input + 4, 4, &state);
     496          ASSERT (ret == 1);
     497          ASSERT (c32tob (wc) == EOF);
     498          ASSERT (wc == 0x672C); /* expect Unicode encoding */
     499          ASSERT (mbsinit (&state));
     500          input[4] = '\0';
     501  
     502          /* Test support of NULL first argument.  */
     503          ret = mbrtoc32 (NULL, input + 5, 3, &state);
     504          ASSERT (ret == 2);
     505          ASSERT (mbsinit (&state));
     506  
     507          wc = (char32_t) 0xBADFACE;
     508          ret = mbrtoc32 (&wc, input + 5, 3, &state);
     509          ASSERT (ret == 2);
     510          ASSERT (c32tob (wc) == EOF);
     511          ASSERT (wc == 0x8A9E); /* expect Unicode encoding */
     512          ASSERT (mbsinit (&state));
     513          input[5] = '\0';
     514          input[6] = '\0';
     515  
     516          wc = (char32_t) 0xBADFACE;
     517          ret = mbrtoc32 (&wc, input + 7, 1, &state);
     518          ASSERT (ret == 1);
     519          ASSERT (wc == '>');
     520          ASSERT (mbsinit (&state));
     521  
     522          /* Test some invalid input.  */
     523          memset (&state, '\0', sizeof (mbstate_t));
     524          wc = (char32_t) 0xBADFACE;
     525          ret = mbrtoc32 (&wc, "\377", 1, &state); /* 0xFF */
     526          ASSERT ((ret == (size_t)-1 && errno == EILSEQ) || ret == (size_t)-2);
     527  
     528          memset (&state, '\0', sizeof (mbstate_t));
     529          wc = (char32_t) 0xBADFACE;
     530          ret = mbrtoc32 (&wc, "\225\377", 2, &state); /* 0x95 0xFF */
     531          ASSERT ((ret == (size_t)-1 && errno == EILSEQ) || (ret == 2 && wc == '?'));
     532        }
     533        return 0;
     534  
     535      case 936:
     536        /* Locale encoding is CP936 = GBK, an extension of GB2312.  */
     537        {
     538          char input[] = "<\310\325\261\276\325\132>"; /* "<日本語>" */
     539          memset (&state, '\0', sizeof (mbstate_t));
     540  
     541          wc = (char32_t) 0xBADFACE;
     542          ret = mbrtoc32 (&wc, input, 1, &state);
     543          ASSERT (ret == 1);
     544          ASSERT (wc == '<');
     545          ASSERT (mbsinit (&state));
     546          input[0] = '\0';
     547  
     548          wc = (char32_t) 0xBADFACE;
     549          ret = mbrtoc32 (&wc, input + 1, 2, &state);
     550          ASSERT (ret == 2);
     551          ASSERT (c32tob (wc) == EOF);
     552          ASSERT (wc == 0x65E5); /* expect Unicode encoding */
     553          ASSERT (mbsinit (&state));
     554          input[1] = '\0';
     555          input[2] = '\0';
     556  
     557          wc = (char32_t) 0xBADFACE;
     558          ret = mbrtoc32 (&wc, input + 3, 1, &state);
     559          ASSERT (ret == (size_t)(-2));
     560          ASSERT (wc == (char32_t) 0xBADFACE);
     561          ASSERT (!mbsinit (&state));
     562          input[3] = '\0';
     563  
     564          wc = (char32_t) 0xBADFACE;
     565          ret = mbrtoc32 (&wc, input + 4, 4, &state);
     566          ASSERT (ret == 1);
     567          ASSERT (c32tob (wc) == EOF);
     568          ASSERT (wc == 0x672C); /* expect Unicode encoding */
     569          ASSERT (mbsinit (&state));
     570          input[4] = '\0';
     571  
     572          /* Test support of NULL first argument.  */
     573          ret = mbrtoc32 (NULL, input + 5, 3, &state);
     574          ASSERT (ret == 2);
     575          ASSERT (mbsinit (&state));
     576  
     577          wc = (char32_t) 0xBADFACE;
     578          ret = mbrtoc32 (&wc, input + 5, 3, &state);
     579          ASSERT (ret == 2);
     580          ASSERT (c32tob (wc) == EOF);
     581          ASSERT (wc == 0x8A9E); /* expect Unicode encoding */
     582          ASSERT (mbsinit (&state));
     583          input[5] = '\0';
     584          input[6] = '\0';
     585  
     586          wc = (char32_t) 0xBADFACE;
     587          ret = mbrtoc32 (&wc, input + 7, 1, &state);
     588          ASSERT (ret == 1);
     589          ASSERT (wc == '>');
     590          ASSERT (mbsinit (&state));
     591  
     592          /* Test some invalid input.  */
     593          memset (&state, '\0', sizeof (mbstate_t));
     594          wc = (char32_t) 0xBADFACE;
     595          ret = mbrtoc32 (&wc, "\377", 1, &state); /* 0xFF */
     596          ASSERT ((ret == (size_t)-1 && errno == EILSEQ) || ret == (size_t)-2);
     597  
     598          memset (&state, '\0', sizeof (mbstate_t));
     599          wc = (char32_t) 0xBADFACE;
     600          ret = mbrtoc32 (&wc, "\225\377", 2, &state); /* 0x95 0xFF */
     601          ASSERT ((ret == (size_t)-1 && errno == EILSEQ) || (ret == 2 && wc == '?'));
     602        }
     603        return 0;
     604  
     605      case 54936:
     606        /* Locale encoding is CP54936 = GB18030.  */
     607        if (strcmp (locale_charset (), "GB18030") != 0)
     608          return 77;
     609        {
     610          char input[] = "s\250\271\201\060\211\070\224\071\375\067!"; /* "süß😋!" */
     611          memset (&state, '\0', sizeof (mbstate_t));
     612  
     613          wc = (char32_t) 0xBADFACE;
     614          ret = mbrtoc32 (&wc, input, 1, &state);
     615          ASSERT (ret == 1);
     616          ASSERT (wc == 's');
     617          ASSERT (mbsinit (&state));
     618          input[0] = '\0';
     619  
     620          wc = (char32_t) 0xBADFACE;
     621          ret = mbrtoc32 (&wc, input + 1, 1, &state);
     622          ASSERT (ret == (size_t)(-2));
     623          ASSERT (wc == (char32_t) 0xBADFACE);
     624          ASSERT (!mbsinit (&state));
     625          input[1] = '\0';
     626  
     627          wc = (char32_t) 0xBADFACE;
     628          ret = mbrtoc32 (&wc, input + 2, 9, &state);
     629          ASSERT (ret == 1);
     630          ASSERT (c32tob (wc) == EOF);
     631          ASSERT (wc == 0x00FC); /* expect Unicode encoding */
     632          ASSERT (mbsinit (&state));
     633          input[2] = '\0';
     634  
     635          /* Test support of NULL first argument.  */
     636          ret = mbrtoc32 (NULL, input + 3, 8, &state);
     637          ASSERT (ret == 4);
     638          ASSERT (mbsinit (&state));
     639  
     640          wc = (char32_t) 0xBADFACE;
     641          ret = mbrtoc32 (&wc, input + 3, 8, &state);
     642          ASSERT (ret == 4);
     643          ASSERT (c32tob (wc) == EOF);
     644          ASSERT (wc == 0x00DF); /* expect Unicode encoding */
     645          ASSERT (mbsinit (&state));
     646          input[3] = '\0';
     647          input[4] = '\0';
     648          input[5] = '\0';
     649          input[6] = '\0';
     650  
     651          /* Test support of NULL first argument.  */
     652          ret = mbrtoc32 (NULL, input + 7, 4, &state);
     653          ASSERT (ret == 4);
     654          ASSERT (mbsinit (&state));
     655  
     656          wc = (char32_t) 0xBADFACE;
     657          ret = mbrtoc32 (&wc, input + 7, 4, &state);
     658          ASSERT (ret == 4);
     659          ASSERT (c32tob (wc) == EOF);
     660          ASSERT (wc == 0x1F60B); /* expect Unicode encoding */
     661          ASSERT (mbsinit (&state));
     662          input[7] = '\0';
     663          input[8] = '\0';
     664          input[9] = '\0';
     665          input[10] = '\0';
     666  
     667          wc = (char32_t) 0xBADFACE;
     668          ret = mbrtoc32 (&wc, input + 11, 1, &state);
     669          ASSERT (ret == 1);
     670          ASSERT (wc == '!');
     671          ASSERT (mbsinit (&state));
     672  
     673          /* Test some invalid input.  */
     674          memset (&state, '\0', sizeof (mbstate_t));
     675          wc = (char32_t) 0xBADFACE;
     676          ret = mbrtoc32 (&wc, "\377", 1, &state); /* 0xFF */
     677          ASSERT (ret == (size_t)-1);
     678          ASSERT (errno == EILSEQ);
     679  
     680          memset (&state, '\0', sizeof (mbstate_t));
     681          wc = (char32_t) 0xBADFACE;
     682          ret = mbrtoc32 (&wc, "\225\377", 2, &state); /* 0x95 0xFF */
     683          ASSERT (ret == (size_t)-1);
     684          ASSERT (errno == EILSEQ);
     685  
     686          memset (&state, '\0', sizeof (mbstate_t));
     687          wc = (char32_t) 0xBADFACE;
     688          ret = mbrtoc32 (&wc, "\201\045", 2, &state); /* 0x81 0x25 */
     689          ASSERT (ret == (size_t)-1);
     690          ASSERT (errno == EILSEQ);
     691  
     692          memset (&state, '\0', sizeof (mbstate_t));
     693          wc = (char32_t) 0xBADFACE;
     694          ret = mbrtoc32 (&wc, "\201\060\377", 3, &state); /* 0x81 0x30 0xFF */
     695          ASSERT (ret == (size_t)-1);
     696          ASSERT (errno == EILSEQ);
     697  
     698          memset (&state, '\0', sizeof (mbstate_t));
     699          wc = (char32_t) 0xBADFACE;
     700          ret = mbrtoc32 (&wc, "\201\060\377\064", 4, &state); /* 0x81 0x30 0xFF 0x34 */
     701          ASSERT (ret == (size_t)-1);
     702          ASSERT (errno == EILSEQ);
     703  
     704          memset (&state, '\0', sizeof (mbstate_t));
     705          wc = (char32_t) 0xBADFACE;
     706          ret = mbrtoc32 (&wc, "\201\060\211\072", 4, &state); /* 0x81 0x30 0x89 0x3A */
     707          ASSERT (ret == (size_t)-1);
     708          ASSERT (errno == EILSEQ);
     709        }
     710        return 0;
     711  
     712      default:
     713        return 1;
     714      }
     715  }
     716  
     717  int
     718  main (int argc, char *argv[])
     719  {
     720    int codepage = atoi (argv[argc - 1]);
     721    int result;
     722    int i;
     723  
     724    result = 77;
     725    for (i = 1; i < argc - 1; i++)
     726      {
     727        int ret = test_one_locale (argv[i], codepage);
     728  
     729        if (ret != 77)
     730          result = ret;
     731      }
     732  
     733    if (result == 77)
     734      {
     735        fprintf (stderr, "Skipping test: found no locale with codepage %d\n",
     736                 codepage);
     737      }
     738    return result;
     739  }
     740  
     741  #else
     742  
     743  int
     744  main (int argc, char *argv[])
     745  {
     746    fputs ("Skipping test: not a native Windows system\n", stderr);
     747    return 77;
     748  }
     749  
     750  #endif