(root)/
glibc-2.38/
stdio-common/
tst-scanf-binary-main.c
       1  /* Test scanf functions with C2X binary integers.
       2     Copyright (C) 2022-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <inttypes.h>
      20  #include <stdarg.h>
      21  #include <stdio.h>
      22  #include <wchar.h>
      23  
      24  #include <libc-diag.h>
      25  #include <support/check.h>
      26  #include <support/xstdio.h>
      27  
      28  #define CONCAT_(X, Y, Z) X ## Y ## Z
      29  #define CONCAT(X, Y, Z) CONCAT_ (X, Y, Z)
      30  #define FNX(FN1, FN2) CONCAT (FN1, FNW, FN2)
      31  #ifndef STDX
      32  # define STDX ""
      33  #endif
      34  
      35  #define INFILE OBJPFX "/tst-" STDX "scanf-binary-" STD "-in"
      36  
      37  static int
      38  wrap_vfscanf (FILE *fp, const CHAR *format, ...)
      39  {
      40    va_list ap;
      41    va_start (ap, format);
      42    int ret = FNX (vf, scanf) (fp, format, ap);
      43    va_end (ap);
      44    return ret;
      45  }
      46  
      47  static int
      48  wrap_vscanf (const CHAR *format, ...)
      49  {
      50    va_list ap;
      51    va_start (ap, format);
      52    int ret = FNX (v, scanf) (format, ap);
      53    va_end (ap);
      54    return ret;
      55  }
      56  
      57  static int
      58  wrap_vsscanf (const CHAR *s, const CHAR *format, ...)
      59  {
      60    va_list ap;
      61    va_start (ap, format);
      62    int ret = FNX (vs, scanf) (s, format, ap);
      63    va_end (ap);
      64    return ret;
      65  }
      66  
      67  static void
      68  one_check (const CHAR *s, int expected, char expected_c)
      69  {
      70    int ret;
      71    FILE *fp;
      72    int ret_i;
      73    long int ret_l;
      74    long long int ret_ll;
      75    char ret_c;
      76    fp = xfopen (INFILE, "w");
      77    ret = FNX (fput, s) (s, fp);
      78    TEST_VERIFY_EXIT (0 <= ret);
      79    xfclose (fp);
      80  
      81    if (!TEST_C2X)
      82      {
      83        expected = 0;
      84        expected_c = s[0] == L_('-') ? s[2] : s[1];
      85      }
      86  
      87    ret = FNX (s, scanf) (s, L_("%i %c"), &ret_i, &ret_c);
      88    TEST_COMPARE (ret, 2);
      89    TEST_COMPARE (ret_i, expected);
      90    TEST_COMPARE (ret_c, expected_c);
      91    fp = xfopen (INFILE, "r");
      92    ret = FNX (f, scanf) (fp, L_("%i %c"), &ret_i, &ret_c);
      93    TEST_COMPARE (ret, 2);
      94    TEST_COMPARE (ret_i, expected);
      95    TEST_COMPARE (ret_c, expected_c);
      96    xfclose (fp);
      97    fp = xfreopen (INFILE, "r", stdin);
      98    ret = FNX (, scanf) (L_("%i %c"), &ret_i, &ret_c);
      99    TEST_COMPARE (ret, 2);
     100    TEST_COMPARE (ret_i, expected);
     101    TEST_COMPARE (ret_c, expected_c);
     102    ret = wrap_vsscanf (s, L_("%i %c"), &ret_i, &ret_c);
     103    TEST_COMPARE (ret, 2);
     104    TEST_COMPARE (ret_i, expected);
     105    TEST_COMPARE (ret_c, expected_c);
     106    fp = xfopen (INFILE, "r");
     107    ret = wrap_vfscanf (fp, L_("%i %c"), &ret_i, &ret_c);
     108    TEST_COMPARE (ret, 2);
     109    TEST_COMPARE (ret_i, expected);
     110    TEST_COMPARE (ret_c, expected_c);
     111    xfclose (fp);
     112    fp = xfreopen (INFILE, "r", stdin);
     113    ret = wrap_vscanf (L_("%i %c"), &ret_i, &ret_c);
     114    TEST_COMPARE (ret, 2);
     115    TEST_COMPARE (ret_i, expected);
     116    TEST_COMPARE (ret_c, expected_c);
     117  
     118    ret = FNX (s, scanf) (s, L_("%li %c"), &ret_l, &ret_c);
     119    TEST_COMPARE (ret, 2);
     120    TEST_COMPARE (ret_l, expected);
     121    TEST_COMPARE (ret_c, expected_c);
     122    fp = xfopen (INFILE, "r");
     123    ret = FNX (f, scanf) (fp, L_("%li %c"), &ret_l, &ret_c);
     124    TEST_COMPARE (ret, 2);
     125    TEST_COMPARE (ret_l, expected);
     126    TEST_COMPARE (ret_c, expected_c);
     127    xfclose (fp);
     128    fp = xfreopen (INFILE, "r", stdin);
     129    ret = FNX (, scanf) (L_("%li %c"), &ret_l, &ret_c);
     130    TEST_COMPARE (ret, 2);
     131    TEST_COMPARE (ret_l, expected);
     132    TEST_COMPARE (ret_c, expected_c);
     133    ret = wrap_vsscanf (s, L_("%li %c"), &ret_l, &ret_c);
     134    TEST_COMPARE (ret, 2);
     135    TEST_COMPARE (ret_l, expected);
     136    TEST_COMPARE (ret_c, expected_c);
     137    fp = xfopen (INFILE, "r");
     138    ret = wrap_vfscanf (fp, L_("%li %c"), &ret_l, &ret_c);
     139    TEST_COMPARE (ret, 2);
     140    TEST_COMPARE (ret_l, expected);
     141    TEST_COMPARE (ret_c, expected_c);
     142    xfclose (fp);
     143    fp = xfreopen (INFILE, "r", stdin);
     144    ret = wrap_vscanf (L_("%li %c"), &ret_l, &ret_c);
     145    TEST_COMPARE (ret, 2);
     146    TEST_COMPARE (ret_l, expected);
     147    TEST_COMPARE (ret_c, expected_c);
     148  
     149    ret = FNX (s, scanf) (s, L_("%lli %c"), &ret_ll, &ret_c);
     150    TEST_COMPARE (ret, 2);
     151    TEST_COMPARE (ret_ll, expected);
     152    TEST_COMPARE (ret_c, expected_c);
     153    fp = xfopen (INFILE, "r");
     154    ret = FNX (f, scanf) (fp, L_("%lli %c"), &ret_ll, &ret_c);
     155    TEST_COMPARE (ret, 2);
     156    TEST_COMPARE (ret_ll, expected);
     157    TEST_COMPARE (ret_c, expected_c);
     158    xfclose (fp);
     159    fp = xfreopen (INFILE, "r", stdin);
     160    ret = FNX (, scanf) (L_("%lli %c"), &ret_ll, &ret_c);
     161    TEST_COMPARE (ret, 2);
     162    TEST_COMPARE (ret_ll, expected);
     163    TEST_COMPARE (ret_c, expected_c);
     164    ret = wrap_vsscanf (s, L_("%lli %c"), &ret_ll, &ret_c);
     165    TEST_COMPARE (ret, 2);
     166    TEST_COMPARE (ret_ll, expected);
     167    TEST_COMPARE (ret_c, expected_c);
     168    fp = xfopen (INFILE, "r");
     169    ret = wrap_vfscanf (fp, L_("%lli %c"), &ret_ll, &ret_c);
     170    TEST_COMPARE (ret, 2);
     171    TEST_COMPARE (ret_ll, expected);
     172    TEST_COMPARE (ret_c, expected_c);
     173    xfclose (fp);
     174    fp = xfreopen (INFILE, "r", stdin);
     175    ret = wrap_vscanf (L_("%lli %c"), &ret_ll, &ret_c);
     176    TEST_COMPARE (ret, 2);
     177    TEST_COMPARE (ret_ll, expected);
     178    TEST_COMPARE (ret_c, expected_c);
     179  }
     180  
     181  /* GCC does not know the %b format before GCC 12.  */
     182  DIAG_PUSH_NEEDS_COMMENT;
     183  #if !__GNUC_PREREQ (12, 0)
     184  DIAG_IGNORE_NEEDS_COMMENT (11, "-Wformat");
     185  DIAG_IGNORE_NEEDS_COMMENT (11, "-Wformat-extra-args");
     186  #endif
     187  
     188  static void
     189  one_check_b (const CHAR *s, int expected, char expected_c)
     190  {
     191    int ret;
     192    FILE *fp;
     193    unsigned int ret_i;
     194    unsigned long int ret_l;
     195    unsigned long long int ret_ll;
     196    char ret_c;
     197    fp = xfopen (INFILE, "w");
     198    ret = FNX (fput, s) (s, fp);
     199    TEST_VERIFY_EXIT (0 <= ret);
     200    xfclose (fp);
     201  
     202    ret = FNX (s, scanf) (s, L_("%b %c"), &ret_i, &ret_c);
     203    TEST_COMPARE (ret, 2);
     204    TEST_COMPARE (ret_i, (unsigned int) expected);
     205    TEST_COMPARE (ret_c, expected_c);
     206    fp = xfopen (INFILE, "r");
     207    ret = FNX (f, scanf) (fp, L_("%b %c"), &ret_i, &ret_c);
     208    TEST_COMPARE (ret, 2);
     209    TEST_COMPARE (ret_i, (unsigned int) expected);
     210    TEST_COMPARE (ret_c, expected_c);
     211    xfclose (fp);
     212    fp = xfreopen (INFILE, "r", stdin);
     213    ret = FNX (, scanf) (L_("%b %c"), &ret_i, &ret_c);
     214    TEST_COMPARE (ret, 2);
     215    TEST_COMPARE (ret_i, (unsigned int) expected);
     216    TEST_COMPARE (ret_c, expected_c);
     217    ret = wrap_vsscanf (s, L_("%b %c"), &ret_i, &ret_c);
     218    TEST_COMPARE (ret, 2);
     219    TEST_COMPARE (ret_i, (unsigned int) expected);
     220    TEST_COMPARE (ret_c, expected_c);
     221    fp = xfopen (INFILE, "r");
     222    ret = wrap_vfscanf (fp, L_("%b %c"), &ret_i, &ret_c);
     223    TEST_COMPARE (ret, 2);
     224    TEST_COMPARE (ret_i, (unsigned int) expected);
     225    TEST_COMPARE (ret_c, expected_c);
     226    xfclose (fp);
     227    fp = xfreopen (INFILE, "r", stdin);
     228    ret = wrap_vscanf (L_("%b %c"), &ret_i, &ret_c);
     229    TEST_COMPARE (ret, 2);
     230    TEST_COMPARE (ret_i, (unsigned int) expected);
     231    TEST_COMPARE (ret_c, expected_c);
     232  
     233    ret = FNX (s, scanf) (s, L_("%lb %c"), &ret_l, &ret_c);
     234    TEST_COMPARE (ret, 2);
     235    TEST_COMPARE (ret_l, (unsigned long int) expected);
     236    TEST_COMPARE (ret_c, expected_c);
     237    fp = xfopen (INFILE, "r");
     238    ret = FNX (f, scanf) (fp, L_("%lb %c"), &ret_l, &ret_c);
     239    TEST_COMPARE (ret, 2);
     240    TEST_COMPARE (ret_l, (unsigned long int) expected);
     241    TEST_COMPARE (ret_c, expected_c);
     242    xfclose (fp);
     243    fp = xfreopen (INFILE, "r", stdin);
     244    ret = FNX (, scanf) (L_("%lb %c"), &ret_l, &ret_c);
     245    TEST_COMPARE (ret, 2);
     246    TEST_COMPARE (ret_l, (unsigned long int) expected);
     247    TEST_COMPARE (ret_c, expected_c);
     248    ret = wrap_vsscanf (s, L_("%lb %c"), &ret_l, &ret_c);
     249    TEST_COMPARE (ret, 2);
     250    TEST_COMPARE (ret_l, (unsigned long int) expected);
     251    TEST_COMPARE (ret_c, expected_c);
     252    fp = xfopen (INFILE, "r");
     253    ret = wrap_vfscanf (fp, L_("%lb %c"), &ret_l, &ret_c);
     254    TEST_COMPARE (ret, 2);
     255    TEST_COMPARE (ret_l, (unsigned long int) expected);
     256    TEST_COMPARE (ret_c, expected_c);
     257    xfclose (fp);
     258    fp = xfreopen (INFILE, "r", stdin);
     259    ret = wrap_vscanf (L_("%lb %c"), &ret_l, &ret_c);
     260    TEST_COMPARE (ret, 2);
     261    TEST_COMPARE (ret_l, (unsigned long int) expected);
     262    TEST_COMPARE (ret_c, expected_c);
     263  
     264    ret = FNX (s, scanf) (s, L_("%llb %c"), &ret_ll, &ret_c);
     265    TEST_COMPARE (ret, 2);
     266    TEST_COMPARE (ret_ll, (unsigned long long int) expected);
     267    TEST_COMPARE (ret_c, expected_c);
     268    fp = xfopen (INFILE, "r");
     269    ret = FNX (f, scanf) (fp, L_("%llb %c"), &ret_ll, &ret_c);
     270    TEST_COMPARE (ret, 2);
     271    TEST_COMPARE (ret_ll, (unsigned long long int) expected);
     272    TEST_COMPARE (ret_c, expected_c);
     273    xfclose (fp);
     274    fp = xfreopen (INFILE, "r", stdin);
     275    ret = FNX (, scanf) (L_("%llb %c"), &ret_ll, &ret_c);
     276    TEST_COMPARE (ret, 2);
     277    TEST_COMPARE (ret_ll, (unsigned long long int) expected);
     278    TEST_COMPARE (ret_c, expected_c);
     279    ret = wrap_vsscanf (s, L_("%llb %c"), &ret_ll, &ret_c);
     280    TEST_COMPARE (ret, 2);
     281    TEST_COMPARE (ret_ll, (unsigned long long int) expected);
     282    TEST_COMPARE (ret_c, expected_c);
     283    fp = xfopen (INFILE, "r");
     284    ret = wrap_vfscanf (fp, L_("%llb %c"), &ret_ll, &ret_c);
     285    TEST_COMPARE (ret, 2);
     286    TEST_COMPARE (ret_ll, (unsigned long long int) expected);
     287    TEST_COMPARE (ret_c, expected_c);
     288    xfclose (fp);
     289    fp = xfreopen (INFILE, "r", stdin);
     290    ret = wrap_vscanf (L_("%llb %c"), &ret_ll, &ret_c);
     291    TEST_COMPARE (ret, 2);
     292    TEST_COMPARE (ret_ll, (unsigned long long int) expected);
     293    TEST_COMPARE (ret_c, expected_c);
     294  }
     295  
     296  #define CHECK_SCNB(TYPE, MACRO, S, EXPECTED, EXPECTED_C)		\
     297    do									\
     298      {									\
     299        int ret;								\
     300        FILE *fp;								\
     301        TYPE ret_t;							\
     302        char ret_c;							\
     303        fp = xfopen (INFILE, "w");					\
     304        ret = FNX (fput, s) (S, fp);					\
     305        TEST_VERIFY_EXIT (0 <= ret);					\
     306        xfclose (fp);							\
     307        ret = FNX (s, scanf) (S, L_("%") MACRO " %c", &ret_t, &ret_c);	\
     308        TEST_COMPARE (ret, 2);						\
     309        TEST_COMPARE (ret_t, EXPECTED);					\
     310        TEST_COMPARE (ret_c, EXPECTED_C);					\
     311        fp = xfopen (INFILE, "r");					\
     312        ret = FNX (f, scanf) (fp, L_("%") MACRO " %c", &ret_t, &ret_c);	\
     313        TEST_COMPARE (ret, 2);						\
     314        TEST_COMPARE (ret_t, EXPECTED);					\
     315        TEST_COMPARE (ret_c, EXPECTED_C);					\
     316        xfclose (fp);							\
     317        fp = xfreopen (INFILE, "r", stdin);				\
     318        ret = FNX (, scanf) (L_("%") MACRO " %c", &ret_t, &ret_c);	\
     319        TEST_COMPARE (ret, 2);						\
     320        TEST_COMPARE (ret_t, EXPECTED);					\
     321        TEST_COMPARE (ret_c, EXPECTED_C);					\
     322        ret = wrap_vsscanf (S, L_("%") MACRO " %c", &ret_t, &ret_c);	\
     323        TEST_COMPARE (ret, 2);						\
     324        TEST_COMPARE (ret_t, EXPECTED);					\
     325        TEST_COMPARE (ret_c, EXPECTED_C);					\
     326        fp = xfopen (INFILE, "r");					\
     327        ret = wrap_vfscanf (fp, L_("%") MACRO " %c", &ret_t, &ret_c);	\
     328        TEST_COMPARE (ret, 2);						\
     329        TEST_COMPARE (ret_t, EXPECTED);					\
     330        TEST_COMPARE (ret_c, EXPECTED_C);					\
     331        xfclose (fp);							\
     332        fp = xfreopen (INFILE, "r", stdin);				\
     333        ret = wrap_vscanf (L_("%") MACRO " %c", &ret_t, &ret_c);		\
     334        TEST_COMPARE (ret, 2);						\
     335        TEST_COMPARE (ret_t, EXPECTED);					\
     336        TEST_COMPARE (ret_c, EXPECTED_C);					\
     337      }									\
     338    while (0)
     339  
     340  static void
     341  one_check_scnb (const CHAR *s, int expected, char expected_c)
     342  {
     343  #if TEST_C2X || defined _GNU_SOURCE
     344    CHECK_SCNB (uint8_t, SCNb8, s, (uint8_t) expected, expected_c);
     345    CHECK_SCNB (uint16_t, SCNb16, s, (uint16_t) expected, expected_c);
     346    CHECK_SCNB (uint32_t, SCNb32, s, (uint32_t) expected, expected_c);
     347    CHECK_SCNB (uint64_t, SCNb64, s, (uint64_t) expected, expected_c);
     348    CHECK_SCNB (uint_least8_t, SCNbLEAST8, s, (uint_least8_t) expected,
     349  	      expected_c);
     350    CHECK_SCNB (uint_least16_t, SCNbLEAST16, s, (uint_least16_t) expected,
     351  	      expected_c);
     352    CHECK_SCNB (uint_least32_t, SCNbLEAST32, s, (uint_least32_t) expected,
     353  	      expected_c);
     354    CHECK_SCNB (uint_least64_t, SCNbLEAST64, s, (uint_least64_t) expected,
     355  	      expected_c);
     356    CHECK_SCNB (uint_fast8_t, SCNbFAST8, s, (uint_fast8_t) expected, expected_c);
     357    CHECK_SCNB (uint_fast16_t, SCNbFAST16, s, (uint_fast16_t) expected,
     358  	      expected_c);
     359    CHECK_SCNB (uint_fast32_t, SCNbFAST32, s, (uint_fast32_t) expected,
     360  	      expected_c);
     361    CHECK_SCNB (uint_fast64_t, SCNbFAST64, s, (uint_fast64_t) expected,
     362  	      expected_c);
     363    CHECK_SCNB (uintmax_t, SCNbMAX, s, (uintmax_t) expected, expected_c);
     364    CHECK_SCNB (uintptr_t, SCNbPTR, s, (uintptr_t) expected, expected_c);
     365  #endif
     366  }
     367  
     368  DIAG_POP_NEEDS_COMMENT;
     369  
     370  static int
     371  do_test (void)
     372  {
     373    one_check (L_("0b101 x"), 5, 'x');
     374    one_check (L_("0B101 x"), 5, 'x');
     375    one_check (L_("-0b11111 y"), -31, 'y');
     376    one_check (L_("-0B11111 y"), -31, 'y');
     377    one_check_b (L_("0b101 x"), 5, 'x');
     378    one_check_b (L_("0B101 x"), 5, 'x');
     379    one_check_b (L_("-0b11111 y"), -31, 'y');
     380    one_check_b (L_("-0B11111 y"), -31, 'y');
     381    one_check_b (L_("101 x"), 5, 'x');
     382    one_check_b (L_("-11111 y"), -31, 'y');
     383    one_check_scnb (L_("0b101 x"), 5, 'x');
     384    one_check_scnb (L_("0B101 x"), 5, 'x');
     385    one_check_scnb (L_("-0b11111 y"), -31, 'y');
     386    one_check_scnb (L_("-0B11111 y"), -31, 'y');
     387    one_check_scnb (L_("101 x"), 5, 'x');
     388    one_check_scnb (L_("-11111 y"), -31, 'y');
     389    return 0;
     390  }
     391  
     392  #include <support/test-driver.c>