1  /* Copyright (C) 2000-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library 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 GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <ctype.h>
      19  #include <langinfo.h>
      20  #include <locale.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <string.h>
      24  #include <unistd.h>
      25  #include <wchar.h>
      26  #include <wctype.h>
      27  #include <sys/types.h>
      28  
      29  
      30  #define ZERO  "\xe2\x82\x80"
      31  #define ONE   "\xe2\x82\x81"
      32  #define TWO   "\xe2\x82\x82"
      33  #define THREE "\xe2\x82\x83"
      34  #define FOUR  "\xe2\x82\x84"
      35  #define FIVE  "\xe2\x82\x85"
      36  #define SIX   "\xe2\x82\x86"
      37  #define SEVEN "\xe2\x82\x87"
      38  #define EIGHT "\xe2\x82\x88"
      39  #define NINE  "\xe2\x82\x89"
      40  
      41  static struct printf_int_test
      42  {
      43    int n;
      44    const char *format;
      45    const char *expected;
      46  } printf_int_tests[] =
      47  {
      48    {       0, "%I'10d", "       " ZERO },
      49    {       1, "%I'10d", "       " ONE },
      50    {       2, "%I'10d", "       " TWO },
      51    {       3, "%I'10d", "       " THREE },
      52    {       4, "%I'10d", "       " FOUR },
      53    {       5, "%I'10d", "       " FIVE },
      54    {       6, "%I'10d", "       " SIX },
      55    {       7, "%I'10d", "       " SEVEN },
      56    {       8, "%I'10d", "       " EIGHT },
      57    {       9, "%I'10d", "       " NINE },
      58    {      11, "%I'10d", "    " ONE ONE },
      59    {      12, "%I'10d", "    " ONE TWO },
      60    {     123, "%I10d",  " " ONE TWO THREE },
      61    {     123, "%I'10d", " " ONE TWO THREE },
      62    {    1234, "%I10d",  ONE TWO THREE FOUR },
      63    {    1234, "%I'10d", ONE "," TWO THREE FOUR },
      64    {   12345, "%I'10d", ONE TWO "," THREE FOUR FIVE },
      65    {  123456, "%I'10d", ONE TWO THREE "," FOUR FIVE SIX },
      66    { 1234567, "%I'10d", ONE "," TWO THREE FOUR "," FIVE SIX SEVEN }
      67  };
      68  #define nprintf_int_tests \
      69    (sizeof (printf_int_tests) / sizeof (printf_int_tests[0]))
      70  
      71  #define WZERO  L"\x2080"
      72  #define WONE   L"\x2081"
      73  #define WTWO   L"\x2082"
      74  #define WTHREE L"\x2083"
      75  #define WFOUR  L"\x2084"
      76  #define WFIVE  L"\x2085"
      77  #define WSIX   L"\x2086"
      78  #define WSEVEN L"\x2087"
      79  #define WEIGHT L"\x2088"
      80  #define WNINE  L"\x2089"
      81  
      82  static struct wprintf_int_test
      83  {
      84    int n;
      85    const wchar_t *format;
      86    const wchar_t *expected;
      87  } wprintf_int_tests[] =
      88  {
      89    {       0, L"%I'10d", L"         " WZERO },
      90    {       1, L"%I'10d", L"         " WONE },
      91    {       2, L"%I'10d", L"         " WTWO },
      92    {       3, L"%I'10d", L"         " WTHREE },
      93    {       4, L"%I'10d", L"         " WFOUR },
      94    {       5, L"%I'10d", L"         " WFIVE },
      95    {       6, L"%I'10d", L"         " WSIX },
      96    {       7, L"%I'10d", L"         " WSEVEN },
      97    {       8, L"%I'10d", L"         " WEIGHT },
      98    {       9, L"%I'10d", L"         " WNINE },
      99    {      11, L"%I'10d", L"        " WONE WONE },
     100    {      12, L"%I'10d", L"        " WONE WTWO },
     101    {     123, L"%I10d",  L"       " WONE WTWO WTHREE },
     102    {     123, L"%I'10d", L"       " WONE WTWO WTHREE },
     103    {    1234, L"%I10d",  L"      " WONE WTWO WTHREE WFOUR },
     104    {    1234, L"%I'10d", L"     " WONE L"," WTWO WTHREE WFOUR },
     105    {   12345, L"%I'10d", L"    " WONE WTWO L"," WTHREE WFOUR WFIVE },
     106    {  123456, L"%I'10d", L"   " WONE WTWO WTHREE L"," WFOUR WFIVE WSIX },
     107    { 1234567, L"%I'10d", L" " WONE L"," WTWO WTHREE WFOUR L"," WFIVE WSIX WSEVEN }
     108  };
     109  #define nwprintf_int_tests \
     110    (sizeof (wprintf_int_tests) / sizeof (wprintf_int_tests[0]))
     111  
     112  
     113  static int
     114  do_test (void)
     115  {
     116    int cnt;
     117    int failures;
     118    int status;
     119  
     120    if (setlocale (LC_ALL, "test7") == NULL)
     121      {
     122        puts ("cannot set locale `test7'");
     123        exit (1);
     124      }
     125    printf ("CODESET = \"%s\"\n", nl_langinfo (CODESET));
     126  
     127    /* First: printf tests.  */
     128    failures = 0;
     129    for (cnt = 0; cnt < (int) nprintf_int_tests; ++cnt)
     130      {
     131        char buf[100];
     132        ssize_t n;
     133  
     134        n = snprintf (buf, sizeof buf, printf_int_tests[cnt].format,
     135  		    printf_int_tests[cnt].n);
     136  
     137        printf ("%3d: got \"%s\", expected \"%s\"",
     138  	      cnt, buf, printf_int_tests[cnt].expected);
     139  
     140        if (n != (ssize_t) strlen (printf_int_tests[cnt].expected)
     141  	  || strcmp (buf, printf_int_tests[cnt].expected) != 0)
     142  	{
     143  	  puts ("  -> FAILED");
     144  	  ++failures;
     145  	}
     146        else
     147  	puts ("  -> OK");
     148      }
     149  
     150    printf ("%d failures in printf tests\n", failures);
     151    status = failures != 0;
     152  
     153    /* wprintf tests.  */
     154    failures = 0;
     155    for (cnt = 0; cnt < (int) nwprintf_int_tests; ++cnt)
     156      {
     157        wchar_t buf[100];
     158        ssize_t n;
     159  
     160        n = swprintf (buf, sizeof buf / sizeof (buf[0]),
     161  		    wprintf_int_tests[cnt].format,
     162  		    wprintf_int_tests[cnt].n);
     163  
     164        printf ("%3d: got \"%ls\", expected \"%ls\"",
     165  	      cnt, buf, wprintf_int_tests[cnt].expected);
     166  
     167        if (n != (ssize_t) wcslen (wprintf_int_tests[cnt].expected)
     168  	  || wcscmp (buf, wprintf_int_tests[cnt].expected) != 0)
     169  	{
     170  	  puts ("  -> FAILED");
     171  	  ++failures;
     172  	}
     173        else
     174  	puts ("  -> OK");
     175      }
     176  
     177    printf ("%d failures in wprintf tests\n", failures);
     178    status = failures != 0;
     179  
     180    /* ctype tests.  This makes sure that the multibyte character digit
     181       representations are not handle in this table.  */
     182    failures = 0;
     183    for (cnt = 0; cnt < 256; ++cnt)
     184      if (cnt >= '0' && cnt <= '9')
     185        {
     186  	if (! isdigit (cnt))
     187  	  {
     188  	    printf ("isdigit ('%c') == 0\n", cnt);
     189  	    ++failures;
     190  	  }
     191        }
     192      else
     193        {
     194  	if (isdigit (cnt))
     195  	  {
     196  	    printf ("isdigit (%d) != 0\n", cnt);
     197  	    ++failures;
     198  	  }
     199        }
     200  
     201    printf ("%d failures in ctype tests\n", failures);
     202    status = failures != 0;
     203  
     204    /* wctype tests.  This makes sure the second set of digits is also
     205       recorded.  */
     206    failures = 0;
     207    for (cnt = 0; cnt < 256; ++cnt)
     208      if (cnt >= '0' && cnt <= '9')
     209        {
     210  	if (! iswdigit (cnt))
     211  	  {
     212  	    printf ("iswdigit (L'%c') == 0\n", cnt);
     213  	    ++failures;
     214  	  }
     215        }
     216      else
     217        {
     218  	if (iswdigit (cnt))
     219  	  {
     220  	    printf ("iswdigit (%d) != 0\n", cnt);
     221  	    ++failures;
     222  	  }
     223        }
     224  
     225    for (cnt = 0x2070; cnt < 0x2090; ++cnt)
     226      if (cnt >= 0x2080 && cnt <= 0x2089)
     227        {
     228  	if (! iswdigit (cnt))
     229  	  {
     230  	    printf ("iswdigit (U%04X) == 0\n", cnt);
     231  	    ++failures;
     232  	  }
     233        }
     234      else
     235        {
     236  	if (iswdigit (cnt))
     237  	  {
     238  	    printf ("iswdigit (U%04X) != 0\n", cnt);
     239  	    ++failures;
     240  	  }
     241        }
     242  
     243    printf ("%d failures in wctype tests\n", failures);
     244    status = failures != 0;
     245  
     246    return status;
     247  }
     248  
     249  #define TEST_FUNCTION do_test ()
     250  #include "../test-skeleton.c"