(root)/
mpfr-4.2.1/
tests/
tprintf.c
       1  /* tprintf.c -- test file for mpfr_printf and mpfr_vprintf
       2  
       3  Copyright 2008-2023 Free Software Foundation, Inc.
       4  Contributed by the AriC and Caramba projects, INRIA.
       5  
       6  This file is part of the GNU MPFR Library.
       7  
       8  The GNU MPFR Library is free software; you can redistribute it and/or modify
       9  it under the terms of the GNU Lesser General Public License as published by
      10  the Free Software Foundation; either version 3 of the License, or (at your
      11  option) any later version.
      12  
      13  The GNU MPFR Library is distributed in the hope that it will be useful, but
      14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      15  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
      16  License for more details.
      17  
      18  You should have received a copy of the GNU Lesser General Public License
      19  along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
      20  https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
      21  51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
      22  
      23  /* FIXME: The output is not tested (thus coverage data are meaningless);
      24     only the return value is tested (output string length).
      25     Knowing the implementation, we may need only some minimal checks:
      26     all the formatted output functions are based on mpfr_vasnprintf_aux
      27     and full checks are done via tsprintf. */
      28  
      29  /* Needed due to the tests on HAVE_STDARG and MPFR_USE_MINI_GMP */
      30  #ifdef HAVE_CONFIG_H
      31  # include "config.h"
      32  #endif
      33  
      34  #if defined(HAVE_STDARG) && !defined(MPFR_USE_MINI_GMP)
      35  #include <stdarg.h>
      36  
      37  #include <stddef.h>
      38  #include <errno.h>
      39  
      40  #ifdef HAVE_LOCALE_H
      41  #include <locale.h>
      42  #endif
      43  
      44  #define MPFR_NEED_INTMAX_H
      45  #include "mpfr-test.h"
      46  #define STDOUT_FILENO 1
      47  
      48  #define QUOTE(X) NAME(X)
      49  #define NAME(X) #X
      50  
      51  /* unlike other tests, we print out errors to stderr because stdout might be
      52     redirected */
      53  #define check_length(num_test, var, value, var_spec)                    \
      54    if ((var) != (value))                                                 \
      55      {                                                                   \
      56        fprintf (stderr, "Error in test #%d: mpfr_printf printed %"       \
      57                 QUOTE(var_spec)" characters instead of %d\n",            \
      58                 (num_test), (var), (value));                             \
      59        exit (1);                                                         \
      60      }
      61  
      62  #define check_length_with_cmp(num_test, var, value, cmp, var_spec)      \
      63    if (cmp != 0)                                                         \
      64      {                                                                   \
      65        mpfr_fprintf (stderr, "Error in test #%d: mpfr_printf printed %"  \
      66                      QUOTE(var_spec)" characters instead of %d\n",       \
      67                      (num_test), (var), (value));                        \
      68        exit (1);                                                         \
      69      }
      70  
      71  #if MPFR_LCONV_DPTS
      72  #define DPLEN ((int) strlen (localeconv()->decimal_point))
      73  #else
      74  #define DPLEN 1
      75  #endif
      76  
      77  /* limit for random precision in random() */
      78  const int prec_max_printf = 5000;
      79  /* boolean: is stdout redirected to a file ? */
      80  int stdout_redirect;
      81  
      82  static void
      83  check (const char *fmt, mpfr_ptr x)
      84  {
      85    if (mpfr_printf (fmt, x) == -1)
      86      {
      87        fprintf (stderr, "Error 1 in mpfr_printf(\"%s\", ...)\n", fmt);
      88  
      89        exit (1);
      90      }
      91    putchar ('\n');
      92  }
      93  
      94  static void
      95  check_vprintf (const char *fmt, ...)
      96  {
      97    va_list ap;
      98  
      99    va_start (ap, fmt);
     100    if (mpfr_vprintf (fmt, ap) == -1)
     101      {
     102        fprintf (stderr, "Error 2 in mpfr_vprintf(\"%s\", ...)\n", fmt);
     103  
     104        va_end (ap);
     105        exit (1);
     106      }
     107    putchar ('\n');
     108    va_end (ap);
     109  }
     110  
     111  static unsigned int
     112  check_vprintf_failure (const char *fmt, ...)
     113  {
     114    va_list ap;
     115    int r, e;
     116  
     117    va_start (ap, fmt);
     118    errno = 0;
     119    r = mpfr_vprintf (fmt, ap);
     120    e = errno;
     121    va_end (ap);
     122  
     123    if (r != -1
     124  #ifdef EOVERFLOW
     125        || e != EOVERFLOW
     126  #endif
     127        )
     128      {
     129        putchar ('\n');
     130        fprintf (stderr, "Error 3 in mpfr_vprintf(\"%s\", ...)\n"
     131                 "Got r = %d, errno = %d\n", fmt, r, e);
     132        return 1;
     133      }
     134  
     135    putchar ('\n');
     136    return 0;
     137  }
     138  
     139  /* The goal of this test is to check cases where more INT_MAX characters
     140     are output, in which case, it should be a failure, because like C's
     141     *printf functions, the return type is int and the returned value must
     142     be either the number of characters printed or a negative value. */
     143  static void
     144  check_long_string (void)
     145  {
     146    /* this test is VERY expensive both in time (~1 min on core2 @ 2.40GHz) and
     147       in memory (~2.5 GB) */
     148    mpfr_t x;
     149    long large_prec = 2147483647;
     150    size_t min_memory_limit, old_memory_limit;
     151  
     152    old_memory_limit = tests_memory_limit;
     153  
     154    /* With a 32-bit (4GB) address space, a realloc failure has been noticed
     155       with a 2G precision (though allocating up to 4GB is possible):
     156         MPFR: Can't reallocate memory (old_size=4096 new_size=2147487744)
     157       The implementation might be improved to use less memory and avoid
     158       this problem. In the mean time, let's choose a smaller precision,
     159       but this will generally have the effect to disable the test. */
     160    if (sizeof (void *) == 4)
     161      large_prec /= 2;
     162  
     163    /* We assume that the precision won't be increased internally. */
     164    if (large_prec > MPFR_PREC_MAX)
     165      large_prec = MPFR_PREC_MAX;
     166  
     167    /* Increase tests_memory_limit if need be in order to avoid an
     168       obvious failure due to insufficient memory. Note that such an
     169       increase is necessary, but is not guaranteed to be sufficient
     170       in all cases (e.g. with logging activated). */
     171    min_memory_limit = large_prec / MPFR_BYTES_PER_MP_LIMB;
     172    if (min_memory_limit > (size_t) -1 / 32)
     173      min_memory_limit = (size_t) -1;
     174    else
     175      min_memory_limit *= 32;
     176    if (tests_memory_limit > 0 && tests_memory_limit < min_memory_limit)
     177      tests_memory_limit = min_memory_limit;
     178  
     179    mpfr_init2 (x, large_prec);
     180  
     181    mpfr_set_ui (x, 1, MPFR_RNDN);
     182    mpfr_nextabove (x);
     183  
     184    if (large_prec >= INT_MAX - 512)
     185      {
     186        unsigned int err = 0;
     187  
     188  #define LS1 "%Rb %512d"
     189  #define LS2 "%RA %RA %Ra %Ra %512d"
     190  
     191        err |= check_vprintf_failure (LS1, x, 1);
     192        err |= check_vprintf_failure (LS2, x, x, x, x, 1);
     193  
     194        if (sizeof (long) * CHAR_BIT > 40)
     195          {
     196            long n1, n2;
     197  
     198            n1 = large_prec + 517;
     199            n2 = -17;
     200            err |= check_vprintf_failure (LS1 "%ln", x, 1, &n2);
     201            if (n1 != n2)
     202              {
     203                fprintf (stderr, "Error in check_long_string(\"%s\", ...)\n"
     204                         "Expected n = %ld\n"
     205                         "Got      n = %ld\n",
     206                         LS1 "%ln", n1, n2);
     207                err = 1;
     208              }
     209            n1 = ((large_prec - 2) / 4) * 4 + 548;
     210            n2 = -17;
     211            err |= check_vprintf_failure (LS2 "%ln", x, x, x, x, 1, &n2);
     212            if (n1 != n2)
     213              {
     214                fprintf (stderr, "Error in check_long_string(\"%s\", ...)\n"
     215                         "Expected n = %ld\n"
     216                         "Got      n = %ld\n",
     217                         LS2 "%ln", n1, n2);
     218                err = 1;
     219              }
     220          }
     221  
     222        if (err)
     223          exit (1);
     224      }
     225  
     226    mpfr_clear (x);
     227    tests_memory_limit = old_memory_limit;
     228  }
     229  
     230  static void
     231  check_special (void)
     232  {
     233    mpfr_t x;
     234  
     235    mpfr_init (x);
     236  
     237    mpfr_set_inf (x, 1);
     238    check ("%Ra", x);
     239    check ("%Rb", x);
     240    check ("%Re", x);
     241    check ("%Rf", x);
     242    check ("%Rg", x);
     243    check_vprintf ("%Ra", x);
     244    check_vprintf ("%Rb", x);
     245    check_vprintf ("%Re", x);
     246    check_vprintf ("%Rf", x);
     247    check_vprintf ("%Rg", x);
     248  
     249    mpfr_set_inf (x, -1);
     250    check ("%Ra", x);
     251    check ("%Rb", x);
     252    check ("%Re", x);
     253    check ("%Rf", x);
     254    check ("%Rg", x);
     255    check_vprintf ("%Ra", x);
     256    check_vprintf ("%Rb", x);
     257    check_vprintf ("%Re", x);
     258    check_vprintf ("%Rf", x);
     259    check_vprintf ("%Rg", x);
     260  
     261    mpfr_set_nan (x);
     262    check ("%Ra", x);
     263    check ("%Rb", x);
     264    check ("%Re", x);
     265    check ("%Rf", x);
     266    check ("%Rg", x);
     267    check_vprintf ("%Ra", x);
     268    check_vprintf ("%Rb", x);
     269    check_vprintf ("%Re", x);
     270    check_vprintf ("%Rf", x);
     271    check_vprintf ("%Rg", x);
     272  
     273    mpfr_clear (x);
     274  }
     275  
     276  static void
     277  check_mixed (void)
     278  {
     279    int ch = 'a';
     280  #ifndef NPRINTF_HH
     281    signed char sch = -1;
     282    unsigned char uch = 1;
     283  #endif
     284    short sh = -1;
     285    unsigned short ush = 1;
     286    int i = -1;
     287    int j = 1;
     288    unsigned int ui = 1;
     289    long lo = -1;
     290    unsigned long ulo = 1;
     291    float f = -1.25;
     292    double d = -1.25;
     293  #if defined(PRINTF_T) || defined(PRINTF_L)
     294    long double ld = -1.25;
     295  #endif
     296  
     297  #ifdef PRINTF_T
     298    ptrdiff_t p = 1, saved_p;
     299  #endif
     300    size_t sz = 1;
     301  
     302    mpz_t mpz;
     303    mpq_t mpq;
     304    mpf_t mpf;
     305    mpfr_rnd_t rnd = MPFR_RNDN;
     306  
     307    mpfr_t mpfr;
     308    mpfr_prec_t prec;
     309  
     310    mpz_init (mpz);
     311    mpz_set_ui (mpz, ulo);
     312    mpq_init (mpq);
     313    mpq_set_si (mpq, lo, ulo);
     314    mpf_init (mpf);
     315    mpf_set_q (mpf, mpq);
     316    mpfr_init (mpfr);
     317    mpfr_set_f (mpfr, mpf, MPFR_RNDN);
     318    prec = mpfr_get_prec (mpfr);
     319  
     320    check_vprintf ("a. %Ra, b. %u, c. %lx%n", mpfr, ui, ulo, &j);
     321    check_length (1, j, 22, d);
     322    check_vprintf ("a. %c, b. %Rb, c. %u, d. %li%ln", i, mpfr, i, lo, &ulo);
     323    check_length (2, ulo, 36, lu);
     324    check_vprintf ("a. %hi, b. %*f, c. %Re%hn", ush, 3, f, mpfr, &ush);
     325    check_length (3, ush, 45 + DPLEN, hu);
     326    check_vprintf ("a. %hi, b. %f, c. %#.2Rf%n", sh, d, mpfr, &i);
     327    check_length (4, i, 28 + DPLEN, d);
     328    check_vprintf ("a. %R*A, b. %Fe, c. %i%zn", rnd, mpfr, mpf, sz, &sz);
     329    check_length (5, (unsigned long) sz, 33 + DPLEN, lu); /* no format specifier '%zu' in C90 */
     330    check_vprintf ("a. %Pu, b. %c, c. %RUG, d. %Zi%Zn", prec, ch, mpfr, mpz, &mpz);
     331    check_length_with_cmp (6, mpz, 24, mpz_cmp_ui (mpz, 24), Zi);
     332    check_vprintf ("%% a. %#.0RNg, b. %Qx%Rn c. %p",
     333                   mpfr, mpq, &mpfr, (void *) &i);
     334    check_length_with_cmp (7, mpfr, 15, mpfr_cmp_ui (mpfr, 15), Rg);
     335  
     336  #ifdef PRINTF_T
     337    saved_p = p;
     338    check_vprintf ("%% a. %RNg, b. %Qx, c. %td%tn", mpfr, mpq, p, &p);
     339    if (p != 20)
     340      {
     341        mpfr_fprintf (stderr,
     342                      "Error in test #8: got '%% a. %RNg, b. %Qx, c. %td'\n",
     343                      mpfr, mpq, saved_p);
     344  #if defined(__MINGW32__) || defined(__MINGW64__)
     345        fprintf (stderr,
     346                 "Your MinGW may be too old, in which case compiling GMP\n"
     347                 "with -D__USE_MINGW_ANSI_STDIO might be required.\n");
     348  #endif
     349      }
     350    check_length (8, (long) p, 20, ld); /* no format specifier '%td' in C90 */
     351  #endif
     352  
     353  #ifdef PRINTF_L
     354    check_vprintf ("a. %RA, b. %Lf, c. %QX%zn", mpfr, ld, mpq, &sz);
     355    check_length (9, (unsigned long) sz, 29 + DPLEN, lu); /* no format specifier '%zu' in C90 */
     356  #endif
     357  
     358  #ifndef NPRINTF_HH
     359    check_vprintf ("a. %hhi, b. %Ra, c. %hhu%hhn", sch, mpfr, uch, &uch);
     360    check_length (10, (unsigned int) uch, 22, u); /* no format specifier '%hhu' in C90 */
     361  #endif
     362  
     363  #if defined(HAVE_LONG_LONG) && !defined(NPRINTF_LL)
     364    {
     365      long long llo = -1;
     366      unsigned long long ullo = 1;
     367  
     368      check_vprintf ("a. %Re, b. %llx%Qn", mpfr, ullo, &mpq);
     369      check_length_with_cmp (11, mpq, 31, mpq_cmp_ui (mpq, 31, 1), Qu);
     370      check_vprintf ("a. %lli, b. %Rf%lln", llo, mpfr, &ullo);
     371      check_length (12, ullo, 19, llu);
     372    }
     373  #endif
     374  
     375  #if defined(_MPFR_H_HAVE_INTMAX_T) && !defined(NPRINTF_J)
     376    {
     377      intmax_t im = -1;
     378      uintmax_t uim = 1;
     379  
     380      check_vprintf ("a. %*RA, b. %ji%Fn", 10, mpfr, im, &mpf);
     381      check_length_with_cmp (31, mpf, 20, mpf_cmp_ui (mpf, 20), Fg);
     382      check_vprintf ("a. %.*Re, b. %jx%jn", 10, mpfr, uim, &im);
     383      check_length (32, (long) im, 25, li); /* no format specifier "%ji" in C90 */
     384    }
     385  #endif
     386  
     387    mpfr_clear (mpfr);
     388    mpf_clear (mpf);
     389    mpq_clear (mpq);
     390    mpz_clear (mpz);
     391  }
     392  
     393  static void
     394  check_random (int nb_tests)
     395  {
     396    int i;
     397    mpfr_t x;
     398    mpfr_rnd_t rnd;
     399    char flag[] =
     400      {
     401        '-',
     402        '+',
     403        ' ',
     404        '#',
     405        '0', /* no ambiguity: first zeros are flag zero*/
     406        '\''
     407      };
     408    char specifier[] =
     409      {
     410        'a',
     411        'b',
     412        'e',
     413        'f',
     414        'g'
     415      };
     416    mpfr_exp_t old_emin, old_emax;
     417  
     418    old_emin = mpfr_get_emin ();
     419    old_emax = mpfr_get_emax ();
     420  
     421    mpfr_init (x);
     422  
     423    for (i = 0; i < nb_tests; ++i)
     424      {
     425        int ret;
     426        int j, jmax;
     427        int spec, prec;
     428  #define FMT_SIZE 13
     429        char fmt[FMT_SIZE]; /* at most something like "%-+ #0'.*R*f" */
     430        char *ptr = fmt;
     431  
     432        tests_default_random (x, 256, MPFR_EMIN_MIN, MPFR_EMAX_MAX, 0);
     433        rnd = (mpfr_rnd_t) RND_RAND ();
     434  
     435        spec = (int) (randlimb () % 5);
     436        jmax = (spec == 3 || spec == 4) ? 6 : 5; /* ' flag only with %f or %g */
     437        /* advantage small precision */
     438        prec = RAND_BOOL () ? 10 : prec_max_printf;
     439        prec = (int) (randlimb () % prec);
     440        if (spec == 3
     441            && (mpfr_get_exp (x) > prec_max_printf
     442                || mpfr_get_exp (x) < -prec_max_printf))
     443          /*  change style 'f' to style 'e' when number x is very large or very
     444              small*/
     445          --spec;
     446  
     447        *ptr++ = '%';
     448        for (j = 0; j < jmax; j++)
     449          {
     450            if (randlimb () % 3 == 0)
     451              *ptr++ = flag[j];
     452          }
     453        *ptr++ = '.';
     454        *ptr++ = '*';
     455        *ptr++ = 'R';
     456        *ptr++ = '*';
     457        *ptr++ = specifier[spec];
     458        *ptr = '\0';
     459        MPFR_ASSERTD (ptr - fmt < FMT_SIZE);
     460  
     461        mpfr_printf ("mpfr_printf(\"%s\", %d, %s, %Re)\n", fmt, prec,
     462                     mpfr_print_rnd_mode (rnd), x);
     463        ret = mpfr_printf (fmt, prec, rnd, x);
     464        if (ret == -1)
     465          {
     466            if (spec == 3
     467                && (MPFR_GET_EXP (x) > INT_MAX || MPFR_GET_EXP (x) < -INT_MAX))
     468              /* normal failure: x is too large to be output with full precision */
     469              {
     470                mpfr_printf ("too large !");
     471              }
     472            else
     473              {
     474                printf ("Error in mpfr_printf(\"%s\", %d, %s, ...)",
     475                        fmt, prec, mpfr_print_rnd_mode (rnd));
     476  
     477                if (stdout_redirect)
     478                  {
     479                    if ((fflush (stdout) == EOF) || (fclose (stdout) == EOF))
     480                      {
     481                        perror ("check_random");
     482                        exit (1);
     483                      }
     484                  }
     485                exit (1);
     486              }
     487          }
     488        putchar ('\n');
     489      }
     490  
     491    set_emin (old_emin);
     492    set_emax (old_emax);
     493  
     494    mpfr_clear (x);
     495  }
     496  
     497  #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
     498  
     499  static void
     500  test_locale (void)
     501  {
     502    const char * const tab_locale[] = {
     503      "en_US",
     504      "en_US.iso88591",
     505      "en_US.iso885915",
     506      "en_US.utf8"
     507    };
     508    int i;
     509    mpfr_t x;
     510    int count;
     511    char v[] = "99999999999999999999999.5";
     512  
     513    for (i = 0; i < numberof(tab_locale); i++)
     514      {
     515        char *s;
     516  
     517        s = setlocale (LC_ALL, tab_locale[i]);
     518  
     519        if (s != NULL && MPFR_THOUSANDS_SEPARATOR == ',')
     520          break;
     521      }
     522  
     523    if (i == numberof(tab_locale))
     524      {
     525        if (getenv ("MPFR_CHECK_LOCALES") == NULL)
     526          return;
     527  
     528        fprintf (stderr, "Cannot find a locale with ',' thousands separator.\n"
     529                 "Please install one of the en_US based locales.\n");
     530        exit (1);
     531      }
     532  
     533    mpfr_init2 (x, 113);
     534    mpfr_set_ui (x, 10000, MPFR_RNDN);
     535  
     536    count = mpfr_printf ("(1) 10000=%'Rg \n", x);
     537    check_length (10000, count, 18, d);
     538    count = mpfr_printf ("(2) 10000=%'Rf \n", x);
     539    check_length (10001, count, 25, d);
     540  
     541    mpfr_set_ui (x, 1000, MPFR_RNDN);
     542    count = mpfr_printf ("(3) 1000=%'Rf \n", x);
     543    check_length (10002, count, 23, d);
     544  
     545    for (i = 1; i <= sizeof (v) - 3; i++)
     546      {
     547        mpfr_set_str (x, v + sizeof (v) - 3 - i, 10, MPFR_RNDN);
     548        count = mpfr_printf ("(4) 10^i=%'.0Rf \n", x);
     549        check_length (10002 + i, count, 12 + i + i/3, d);
     550      }
     551  
     552  #define N0 20
     553  
     554    for (i = 1; i <= N0; i++)
     555      {
     556        char s[N0+4];
     557        int j, rnd;
     558  
     559        s[0] = '1';
     560        for (j = 1; j <= i; j++)
     561          s[j] = '0';
     562        s[i+1] = '\0';
     563  
     564        mpfr_set_str (x, s, 10, MPFR_RNDN);
     565  
     566        RND_LOOP (rnd)
     567          {
     568            count = mpfr_printf ("(5) 10^i=%'.0R*f \n", (mpfr_rnd_t) rnd, x);
     569            check_length (11000 + 10 * i + rnd, count, 12 + i + i/3, d);
     570          }
     571  
     572        strcat (s + (i + 1), ".5");
     573        count = mpfr_printf ("(5) 10^i=%'.0Rf \n", x);
     574        check_length (11000 + 10 * i + 9, count, 12 + i + i/3, d);
     575      }
     576  
     577    mpfr_set_str (x, "1000", 10, MPFR_RNDN);
     578    count = mpfr_printf ("%'012.3Rg\n", x);
     579    check_length (12000, count, 13, d);
     580    count = mpfr_printf ("%'012.4Rg\n", x);
     581    check_length (12001, count, 13, d);
     582    count = mpfr_printf ("%'013.4Rg\n", x);
     583    check_length (12002, count, 14, d);
     584  
     585    mpfr_clear (x);
     586  }
     587  
     588  #else
     589  
     590  static void
     591  test_locale (void)
     592  {
     593    if (getenv ("MPFR_CHECK_LOCALES") != NULL)
     594      {
     595        fprintf (stderr, "Cannot test locales.\n");
     596        exit (1);
     597      }
     598  }
     599  
     600  #endif
     601  
     602  int
     603  main (int argc, char *argv[])
     604  {
     605    int N;
     606  
     607    tests_start_mpfr ();
     608  
     609    /* with no argument: prints to /dev/null,
     610       tprintf N: prints N tests to stdout */
     611    if (argc == 1)
     612      {
     613        N = 1000;
     614        stdout_redirect = 1;
     615        if (freopen ("/dev/null", "w", stdout) == NULL)
     616          {
     617            /* We failed to open this device, try with a dummy file */
     618            if (freopen ("tprintf_out.txt", "w", stdout) == NULL)
     619              {
     620                /* Output the error message to stderr since it is not
     621                   a message about a wrong result in MPFR. Anyway the
     622                   standard output may have changed. */
     623                fprintf (stderr, "Can't open /dev/null or a temporary file\n");
     624                exit (1);
     625              }
     626          }
     627      }
     628    else
     629      {
     630        stdout_redirect = 0;
     631        N = atoi (argv[1]);
     632      }
     633  
     634    check_special ();
     635    check_mixed ();
     636  
     637    /* expensive tests */
     638    if (getenv ("MPFR_CHECK_LARGEMEM") != NULL)
     639      check_long_string();
     640  
     641    check_random (N);
     642  
     643    test_locale ();
     644  
     645    if (stdout_redirect)
     646      {
     647        if ((fflush (stdout) == EOF) || (fclose (stdout) == EOF))
     648          perror ("main");
     649      }
     650    tests_end_mpfr ();
     651    return 0;
     652  }
     653  
     654  #else  /* HAVE_STDARG */
     655  
     656  int
     657  main (void)
     658  {
     659    /* We have nothing to test. */
     660    return 77;
     661  }
     662  
     663  #endif  /* HAVE_STDARG */