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