Advertisement
NaZaRa

vfprintf -- glib-2.13

Apr 2nd, 2013
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 75.76 KB | None | 0 0
  1. /* Copyright (C) 1991-2008, 2009, 2010   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, write to the Free
  16.    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  17.    02111-1307 USA.  */
  18.  
  19. #include <ctype.h>
  20. #include <limits.h>
  21. #include <printf.h>
  22. #include <stdarg.h>
  23. #include <stdint.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <errno.h>
  27. #include <wchar.h>
  28. #include <bits/libc-lock.h>
  29. #include <sys/param.h>
  30. #include "_itoa.h"
  31. #include <locale/localeinfo.h>
  32. #include <stdio.h>
  33.  
  34. /* This code is shared between the standard stdio implementation found
  35.    in GNU C library and the libio implementation originally found in
  36.    GNU libg++.
  37.  
  38.    Beside this it is also shared between the normal and wide character
  39.    implementation as defined in ISO/IEC 9899:1990/Amendment 1:1995.  */
  40.  
  41.  
  42. #include <libioP.h>
  43. #define FILE        _IO_FILE
  44. #undef va_list
  45. #define va_list _IO_va_list
  46. #undef BUFSIZ
  47. #define BUFSIZ      _IO_BUFSIZ
  48. #define ARGCHECK(S, Format) \
  49.   do                                          \
  50.     {                                         \
  51.       /* Check file argument for consistence.  */                 \
  52.       CHECK_FILE (S, -1);                             \
  53.       if (S->_flags & _IO_NO_WRITES)                          \
  54.     {                                     \
  55.       __set_errno (EBADF);                            \
  56.       return -1;                                  \
  57.     }                                     \
  58.       if (Format == NULL)                             \
  59.     {                                     \
  60.       MAYBE_SET_EINVAL;                           \
  61.       return -1;                                  \
  62.     }                                     \
  63.     } while (0)
  64. #define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED)
  65.  
  66. #define done_add(val) \
  67.   do {                                        \
  68.     unsigned int _val = val;                              \
  69.     assert ((unsigned int) done < (unsigned int) INT_MAX);            \
  70.     if (__builtin_expect ((unsigned int) INT_MAX - (unsigned int) done        \
  71.               < _val, 0))                         \
  72.       {                                       \
  73.     done = -1;                                \
  74.     goto all_done;                                \
  75.       }                                       \
  76.     done += _val;                                 \
  77.   } while (0)
  78.  
  79. #ifndef COMPILE_WPRINTF
  80. # define vfprintf   _IO_vfprintf_internal
  81. # define CHAR_T     char
  82. # define UCHAR_T    unsigned char
  83. # define INT_T      int
  84. # define L_(Str)    Str
  85. # define ISDIGIT(Ch)    ((unsigned int) ((Ch) - '0') < 10)
  86. # define STR_LEN(Str)   strlen (Str)
  87.  
  88. # define PUT(F, S, N)   _IO_sputn ((F), (S), (N))
  89. # define PAD(Padchar) \
  90.   if (width > 0)                                  \
  91.     done_add (INTUSE(_IO_padn) (s, (Padchar), width))
  92. # define PUTC(C, F) _IO_putc_unlocked (C, F)
  93. # define ORIENT     if (_IO_vtable_offset (s) == 0 && _IO_fwide (s, -1) != -1)\
  94.               return -1
  95. #else
  96. # define vfprintf   _IO_vfwprintf
  97. # define CHAR_T     wchar_t
  98. /* This is a hack!!!  There should be a type uwchar_t.  */
  99. # define UCHAR_T    unsigned int /* uwchar_t */
  100. # define INT_T      wint_t
  101. # define L_(Str)    L##Str
  102. # define ISDIGIT(Ch)    ((unsigned int) ((Ch) - L'0') < 10)
  103. # define STR_LEN(Str)   __wcslen (Str)
  104.  
  105. # include "_itowa.h"
  106.  
  107. # define PUT(F, S, N)   _IO_sputn ((F), (S), (N))
  108. # define PAD(Padchar) \
  109.   if (width > 0)                                  \
  110.     done_add (_IO_wpadn (s, (Padchar), width))
  111. # define PUTC(C, F) _IO_putwc_unlocked (C, F)
  112. # define ORIENT     if (_IO_fwide (s, 1) != 1) return -1
  113.  
  114. # undef _itoa
  115. # define _itoa(Val, Buf, Base, Case) _itowa (Val, Buf, Base, Case)
  116. # define _itoa_word(Val, Buf, Base, Case) _itowa_word (Val, Buf, Base, Case)
  117. # undef EOF
  118. # define EOF WEOF
  119. #endif
  120.  
  121. #include "_i18n_number.h"
  122.  
  123. /* Include the shared code for parsing the format string.  */
  124. #include "printf-parse.h"
  125.  
  126.  
  127. #define outchar(Ch)                               \
  128.   do                                          \
  129.     {                                         \
  130.       register const INT_T outc = (Ch);                       \
  131.       if (PUTC (outc, s) == EOF || done == INT_MAX)               \
  132.     {                                     \
  133.       done = -1;                                  \
  134.       goto all_done;                              \
  135.     }                                     \
  136.       ++done;                                     \
  137.     }                                         \
  138.   while (0)
  139.  
  140. #define outstring(String, Len)                            \
  141.   do                                          \
  142.     {                                         \
  143.       assert ((size_t) done <= (size_t) INT_MAX);                 \
  144.       if ((size_t) PUT (s, (String), (Len)) != (size_t) (Len)             \
  145.       || (size_t) INT_MAX - (size_t) done < (size_t) (Len))           \
  146.     {                                     \
  147.       done = -1;                                  \
  148.       goto all_done;                              \
  149.     }                                     \
  150.       done += (Len);                                  \
  151.     }                                         \
  152.   while (0)
  153.  
  154. /* For handling long_double and longlong we use the same flag.  If
  155.    `long' and `long long' are effectively the same type define it to
  156.    zero.  */
  157. #if LONG_MAX == LONG_LONG_MAX
  158. # define is_longlong 0
  159. #else
  160. # define is_longlong is_long_double
  161. #endif
  162.  
  163. /* If `long' and `int' is effectively the same type we don't have to
  164.    handle `long separately.  */
  165. #if INT_MAX == LONG_MAX
  166. # define is_long_num    0
  167. #else
  168. # define is_long_num    is_long
  169. #endif
  170.  
  171.  
  172. /* Global variables.  */
  173. static const CHAR_T null[] = L_("(null)");
  174.  
  175.  
  176. /* Helper function to provide temporary buffering for unbuffered streams.  */
  177. static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list)
  178.      __THROW __attribute__ ((noinline)) internal_function;
  179.  
  180. /* Handle unknown format specifier.  */
  181. static int printf_unknown (FILE *, const struct printf_info *,
  182.                const void *const *) __THROW;
  183.  
  184. /* Group digits of number string.  */
  185. #ifdef COMPILE_WPRINTF
  186. static CHAR_T *group_number (CHAR_T *, CHAR_T *, const char *, wchar_t)
  187.      __THROW internal_function;
  188. #else
  189. static CHAR_T *group_number (CHAR_T *, CHAR_T *, const char *, const char *)
  190.      __THROW internal_function;
  191. #endif
  192.  
  193.  
  194. /* The function itself.  */
  195. int
  196. vfprintf (FILE *s, const CHAR_T *format, va_list ap)
  197. {
  198.   /* The character used as thousands separator.  */
  199. #ifdef COMPILE_WPRINTF
  200.   wchar_t thousands_sep = L'\0';
  201. #else
  202.   const char *thousands_sep = NULL;
  203. #endif
  204.  
  205.   /* The string describing the size of groups of digits.  */
  206.   const char *grouping;
  207.  
  208.   /* Place to accumulate the result.  */
  209.   int done;
  210.  
  211.   /* Current character in format string.  */
  212.   const UCHAR_T *f;
  213.  
  214.   /* End of leading constant string.  */
  215.   const UCHAR_T *lead_str_end;
  216.  
  217.   /* Points to next format specifier.  */
  218.   const UCHAR_T *end_of_spec;
  219.  
  220.   /* Buffer intermediate results.  */
  221.   CHAR_T work_buffer[1000];
  222.   CHAR_T *workstart = NULL;
  223.   CHAR_T *workend;
  224.  
  225.   /* We have to save the original argument pointer.  */
  226.   va_list ap_save;
  227.  
  228.   /* Count number of specifiers we already processed.  */
  229.   int nspecs_done;
  230.  
  231.   /* For the %m format we may need the current `errno' value.  */
  232.   int save_errno = errno;
  233.  
  234.   /* 1 if format is in read-only memory, -1 if it is in writable memory,
  235.      0 if unknown.  */
  236.   int readonly_format = 0;
  237.  
  238.   /* This table maps a character into a number representing a
  239.      class.  In each step there is a destination label for each
  240.      class.  */
  241.   static const uint8_t jump_table[] =
  242.   {
  243.     /* ' ' */  1,            0,            0, /* '#' */  4,
  244.            0, /* '%' */ 14,            0, /* '\''*/  6,
  245.            0,            0, /* '*' */  7, /* '+' */  2,
  246.            0, /* '-' */  3, /* '.' */  9,            0,
  247.     /* '0' */  5, /* '1' */  8, /* '2' */  8, /* '3' */  8,
  248.     /* '4' */  8, /* '5' */  8, /* '6' */  8, /* '7' */  8,
  249.     /* '8' */  8, /* '9' */  8,            0,            0,
  250.            0,            0,            0,            0,
  251.            0, /* 'A' */ 26,            0, /* 'C' */ 25,
  252.            0, /* 'E' */ 19, /* F */   19, /* 'G' */ 19,
  253.            0, /* 'I' */ 29,            0,            0,
  254.     /* 'L' */ 12,            0,            0,            0,
  255.            0,            0,            0, /* 'S' */ 21,
  256.            0,            0,            0,            0,
  257.     /* 'X' */ 18,            0, /* 'Z' */ 13,            0,
  258.            0,            0,            0,            0,
  259.            0, /* 'a' */ 26,            0, /* 'c' */ 20,
  260.     /* 'd' */ 15, /* 'e' */ 19, /* 'f' */ 19, /* 'g' */ 19,
  261.     /* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 28,            0,
  262.     /* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17,
  263.     /* 'p' */ 22, /* 'q' */ 12,            0, /* 's' */ 21,
  264.     /* 't' */ 27, /* 'u' */ 16,            0,            0,
  265.     /* 'x' */ 18,            0, /* 'z' */ 13
  266.   };
  267.  
  268. #define NOT_IN_JUMP_RANGE(Ch) ((Ch) < L_(' ') || (Ch) > L_('z'))
  269. #define CHAR_CLASS(Ch) (jump_table[(INT_T) (Ch) - L_(' ')])
  270. #ifdef SHARED
  271.   /* 'int' is enough and it saves some space on 64 bit systems.  */
  272. # define JUMP_TABLE_TYPE const int
  273. # define JUMP(ChExpr, table)                              \
  274.       do                                      \
  275.     {                                     \
  276.       int offset;                                 \
  277.       void *__unbounded ptr;                          \
  278.       spec = (ChExpr);                            \
  279.       offset = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown)          \
  280.         : table[CHAR_CLASS (spec)];                       \
  281.       ptr = &&do_form_unknown + offset;                   \
  282.       goto *ptr;                                  \
  283.     }                                     \
  284.       while (0)
  285. #else
  286. # define JUMP_TABLE_TYPE const void *const
  287. # define JUMP(ChExpr, table)                              \
  288.       do                                      \
  289.     {                                     \
  290.       const void *__unbounded ptr;                        \
  291.       spec = (ChExpr);                            \
  292.       ptr = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown)             \
  293.         : table[CHAR_CLASS (spec)];                       \
  294.       goto *ptr;                                  \
  295.     }                                     \
  296.       while (0)
  297. #endif
  298.  
  299. #define STEP0_3_TABLE                                 \
  300.     /* Step 0: at the beginning.  */                          \
  301.     static JUMP_TABLE_TYPE step0_jumps[30] =                      \
  302.     {                                         \
  303.       REF (form_unknown),                             \
  304.       REF (flag_space),     /* for ' ' */                     \
  305.       REF (flag_plus),      /* for '+' */                     \
  306.       REF (flag_minus),     /* for '-' */                     \
  307.       REF (flag_hash),      /* for '<hash>' */                \
  308.       REF (flag_zero),      /* for '0' */                     \
  309.       REF (flag_quote),     /* for '\'' */                    \
  310.       REF (width_asterics), /* for '*' */                     \
  311.       REF (width),      /* for '1'...'9' */               \
  312.       REF (precision),      /* for '.' */                     \
  313.       REF (mod_half),       /* for 'h' */                     \
  314.       REF (mod_long),       /* for 'l' */                     \
  315.       REF (mod_longlong),   /* for 'L', 'q' */                \
  316.       REF (mod_size_t),     /* for 'z', 'Z' */                \
  317.       REF (form_percent),   /* for '%' */                     \
  318.       REF (form_integer),   /* for 'd', 'i' */                \
  319.       REF (form_unsigned),  /* for 'u' */                     \
  320.       REF (form_octal),     /* for 'o' */                     \
  321.       REF (form_hexa),      /* for 'X', 'x' */                \
  322.       REF (form_float),     /* for 'E', 'e', 'F', 'f', 'G', 'g' */        \
  323.       REF (form_character), /* for 'c' */                     \
  324.       REF (form_string),    /* for 's', 'S' */                \
  325.       REF (form_pointer),   /* for 'p' */                     \
  326.       REF (form_number),    /* for 'n' */                     \
  327.       REF (form_strerror),  /* for 'm' */                     \
  328.       REF (form_wcharacter),    /* for 'C' */                     \
  329.       REF (form_floathex),  /* for 'A', 'a' */                \
  330.       REF (mod_ptrdiff_t),      /* for 't' */                     \
  331.       REF (mod_intmax_t),       /* for 'j' */                     \
  332.       REF (flag_i18n),      /* for 'I' */                     \
  333.     };                                        \
  334.     /* Step 1: after processing width.  */                    \
  335.     static JUMP_TABLE_TYPE step1_jumps[30] =                      \
  336.     {                                         \
  337.       REF (form_unknown),                             \
  338.       REF (form_unknown),   /* for ' ' */                     \
  339.       REF (form_unknown),   /* for '+' */                     \
  340.       REF (form_unknown),   /* for '-' */                     \
  341.       REF (form_unknown),   /* for '<hash>' */                \
  342.       REF (form_unknown),   /* for '0' */                     \
  343.       REF (form_unknown),   /* for '\'' */                    \
  344.       REF (form_unknown),   /* for '*' */                     \
  345.       REF (form_unknown),   /* for '1'...'9' */               \
  346.       REF (precision),      /* for '.' */                     \
  347.       REF (mod_half),       /* for 'h' */                     \
  348.       REF (mod_long),       /* for 'l' */                     \
  349.       REF (mod_longlong),   /* for 'L', 'q' */                \
  350.       REF (mod_size_t),     /* for 'z', 'Z' */                \
  351.       REF (form_percent),   /* for '%' */                     \
  352.       REF (form_integer),   /* for 'd', 'i' */                \
  353.       REF (form_unsigned),  /* for 'u' */                     \
  354.       REF (form_octal),     /* for 'o' */                     \
  355.       REF (form_hexa),      /* for 'X', 'x' */                \
  356.       REF (form_float),     /* for 'E', 'e', 'F', 'f', 'G', 'g' */        \
  357.       REF (form_character), /* for 'c' */                     \
  358.       REF (form_string),    /* for 's', 'S' */                \
  359.       REF (form_pointer),   /* for 'p' */                     \
  360.       REF (form_number),    /* for 'n' */                     \
  361.       REF (form_strerror),  /* for 'm' */                     \
  362.       REF (form_wcharacter),    /* for 'C' */                     \
  363.       REF (form_floathex),  /* for 'A', 'a' */                \
  364.       REF (mod_ptrdiff_t),      /* for 't' */                     \
  365.       REF (mod_intmax_t),       /* for 'j' */                     \
  366.       REF (form_unknown)        /* for 'I' */                     \
  367.     };                                        \
  368.     /* Step 2: after processing precision.  */                    \
  369.     static JUMP_TABLE_TYPE step2_jumps[30] =                      \
  370.     {                                         \
  371.       REF (form_unknown),                             \
  372.       REF (form_unknown),   /* for ' ' */                     \
  373.       REF (form_unknown),   /* for '+' */                     \
  374.       REF (form_unknown),   /* for '-' */                     \
  375.       REF (form_unknown),   /* for '<hash>' */                \
  376.       REF (form_unknown),   /* for '0' */                     \
  377.       REF (form_unknown),   /* for '\'' */                    \
  378.       REF (form_unknown),   /* for '*' */                     \
  379.       REF (form_unknown),   /* for '1'...'9' */               \
  380.       REF (form_unknown),   /* for '.' */                     \
  381.       REF (mod_half),       /* for 'h' */                     \
  382.       REF (mod_long),       /* for 'l' */                     \
  383.       REF (mod_longlong),   /* for 'L', 'q' */                \
  384.       REF (mod_size_t),     /* for 'z', 'Z' */                \
  385.       REF (form_percent),   /* for '%' */                     \
  386.       REF (form_integer),   /* for 'd', 'i' */                \
  387.       REF (form_unsigned),  /* for 'u' */                     \
  388.       REF (form_octal),     /* for 'o' */                     \
  389.       REF (form_hexa),      /* for 'X', 'x' */                \
  390.       REF (form_float),     /* for 'E', 'e', 'F', 'f', 'G', 'g' */        \
  391.       REF (form_character), /* for 'c' */                     \
  392.       REF (form_string),    /* for 's', 'S' */                \
  393.       REF (form_pointer),   /* for 'p' */                     \
  394.       REF (form_number),    /* for 'n' */                     \
  395.       REF (form_strerror),  /* for 'm' */                     \
  396.       REF (form_wcharacter),    /* for 'C' */                     \
  397.       REF (form_floathex),  /* for 'A', 'a' */                \
  398.       REF (mod_ptrdiff_t),      /* for 't' */                     \
  399.       REF (mod_intmax_t),       /* for 'j' */                     \
  400.       REF (form_unknown)        /* for 'I' */                     \
  401.     };                                        \
  402.     /* Step 3a: after processing first 'h' modifier.  */              \
  403.     static JUMP_TABLE_TYPE step3a_jumps[30] =                     \
  404.     {                                         \
  405.       REF (form_unknown),                             \
  406.       REF (form_unknown),   /* for ' ' */                     \
  407.       REF (form_unknown),   /* for '+' */                     \
  408.       REF (form_unknown),   /* for '-' */                     \
  409.       REF (form_unknown),   /* for '<hash>' */                \
  410.       REF (form_unknown),   /* for '0' */                     \
  411.       REF (form_unknown),   /* for '\'' */                    \
  412.       REF (form_unknown),   /* for '*' */                     \
  413.       REF (form_unknown),   /* for '1'...'9' */               \
  414.       REF (form_unknown),   /* for '.' */                     \
  415.       REF (mod_halfhalf),   /* for 'h' */                     \
  416.       REF (form_unknown),   /* for 'l' */                     \
  417.       REF (form_unknown),   /* for 'L', 'q' */                \
  418.       REF (form_unknown),   /* for 'z', 'Z' */                \
  419.       REF (form_percent),   /* for '%' */                     \
  420.       REF (form_integer),   /* for 'd', 'i' */                \
  421.       REF (form_unsigned),  /* for 'u' */                     \
  422.       REF (form_octal),     /* for 'o' */                     \
  423.       REF (form_hexa),      /* for 'X', 'x' */                \
  424.       REF (form_unknown),   /* for 'E', 'e', 'F', 'f', 'G', 'g' */        \
  425.       REF (form_unknown),   /* for 'c' */                     \
  426.       REF (form_unknown),   /* for 's', 'S' */                \
  427.       REF (form_unknown),   /* for 'p' */                     \
  428.       REF (form_number),    /* for 'n' */                     \
  429.       REF (form_unknown),   /* for 'm' */                     \
  430.       REF (form_unknown),   /* for 'C' */                     \
  431.       REF (form_unknown),   /* for 'A', 'a' */                \
  432.       REF (form_unknown),       /* for 't' */                     \
  433.       REF (form_unknown),       /* for 'j' */                     \
  434.       REF (form_unknown)        /* for 'I' */                     \
  435.     };                                        \
  436.     /* Step 3b: after processing first 'l' modifier.  */              \
  437.     static JUMP_TABLE_TYPE step3b_jumps[30] =                     \
  438.     {                                         \
  439.       REF (form_unknown),                             \
  440.       REF (form_unknown),   /* for ' ' */                     \
  441.       REF (form_unknown),   /* for '+' */                     \
  442.       REF (form_unknown),   /* for '-' */                     \
  443.       REF (form_unknown),   /* for '<hash>' */                \
  444.       REF (form_unknown),   /* for '0' */                     \
  445.       REF (form_unknown),   /* for '\'' */                    \
  446.       REF (form_unknown),   /* for '*' */                     \
  447.       REF (form_unknown),   /* for '1'...'9' */               \
  448.       REF (form_unknown),   /* for '.' */                     \
  449.       REF (form_unknown),   /* for 'h' */                     \
  450.       REF (mod_longlong),   /* for 'l' */                     \
  451.       REF (form_unknown),   /* for 'L', 'q' */                \
  452.       REF (form_unknown),   /* for 'z', 'Z' */                \
  453.       REF (form_percent),   /* for '%' */                     \
  454.       REF (form_integer),   /* for 'd', 'i' */                \
  455.       REF (form_unsigned),  /* for 'u' */                     \
  456.       REF (form_octal),     /* for 'o' */                     \
  457.       REF (form_hexa),      /* for 'X', 'x' */                \
  458.       REF (form_float),     /* for 'E', 'e', 'F', 'f', 'G', 'g' */        \
  459.       REF (form_character), /* for 'c' */                     \
  460.       REF (form_string),    /* for 's', 'S' */                \
  461.       REF (form_pointer),   /* for 'p' */                     \
  462.       REF (form_number),    /* for 'n' */                     \
  463.       REF (form_strerror),  /* for 'm' */                     \
  464.       REF (form_wcharacter),    /* for 'C' */                     \
  465.       REF (form_floathex),  /* for 'A', 'a' */                \
  466.       REF (form_unknown),       /* for 't' */                     \
  467.       REF (form_unknown),       /* for 'j' */                     \
  468.       REF (form_unknown)        /* for 'I' */                     \
  469.     }
  470.  
  471. #define STEP4_TABLE                               \
  472.     /* Step 4: processing format specifier.  */                   \
  473.     static JUMP_TABLE_TYPE step4_jumps[30] =                      \
  474.     {                                         \
  475.       REF (form_unknown),                             \
  476.       REF (form_unknown),   /* for ' ' */                     \
  477.       REF (form_unknown),   /* for '+' */                     \
  478.       REF (form_unknown),   /* for '-' */                     \
  479.       REF (form_unknown),   /* for '<hash>' */                \
  480.       REF (form_unknown),   /* for '0' */                     \
  481.       REF (form_unknown),   /* for '\'' */                    \
  482.       REF (form_unknown),   /* for '*' */                     \
  483.       REF (form_unknown),   /* for '1'...'9' */               \
  484.       REF (form_unknown),   /* for '.' */                     \
  485.       REF (form_unknown),   /* for 'h' */                     \
  486.       REF (form_unknown),   /* for 'l' */                     \
  487.       REF (form_unknown),   /* for 'L', 'q' */                \
  488.       REF (form_unknown),   /* for 'z', 'Z' */                \
  489.       REF (form_percent),   /* for '%' */                     \
  490.       REF (form_integer),   /* for 'd', 'i' */                \
  491.       REF (form_unsigned),  /* for 'u' */                     \
  492.       REF (form_octal),     /* for 'o' */                     \
  493.       REF (form_hexa),      /* for 'X', 'x' */                \
  494.       REF (form_float),     /* for 'E', 'e', 'F', 'f', 'G', 'g' */        \
  495.       REF (form_character), /* for 'c' */                     \
  496.       REF (form_string),    /* for 's', 'S' */                \
  497.       REF (form_pointer),   /* for 'p' */                     \
  498.       REF (form_number),    /* for 'n' */                     \
  499.       REF (form_strerror),  /* for 'm' */                     \
  500.       REF (form_wcharacter),    /* for 'C' */                     \
  501.       REF (form_floathex),  /* for 'A', 'a' */                \
  502.       REF (form_unknown),       /* for 't' */                     \
  503.       REF (form_unknown),       /* for 'j' */                     \
  504.       REF (form_unknown)        /* for 'I' */                     \
  505.     }
  506.  
  507.  
  508. #define process_arg(fspec)                            \
  509.       /* Start real work.  We know about all flags and modifiers and          \
  510.      now process the wanted format specifier.  */                 \
  511.     LABEL (form_percent):                             \
  512.       /* Write a literal "%".  */                         \
  513.       outchar (L_('%'));                              \
  514.       break;                                      \
  515.                                           \
  516.     LABEL (form_integer):                             \
  517.       /* Signed decimal integer.  */                          \
  518.       base = 10;                                  \
  519.                                           \
  520.       if (is_longlong)                                \
  521.     {                                     \
  522.       long long int signed_number;                        \
  523.                                           \
  524.       if (fspec == NULL)                              \
  525.         signed_number = va_arg (ap, long long int);               \
  526.       else                                    \
  527.         signed_number = args_value[fspec->data_arg].pa_long_long_int;     \
  528.                                           \
  529.       is_negative = signed_number < 0;                    \
  530.       number.longlong = is_negative ? (- signed_number) : signed_number;  \
  531.                                           \
  532.       goto LABEL (longlong_number);                       \
  533.     }                                     \
  534.       else                                    \
  535.     {                                     \
  536.       long int signed_number;                         \
  537.                                           \
  538.       if (fspec == NULL)                              \
  539.         {                                     \
  540.           if (is_long_num)                            \
  541.         signed_number = va_arg (ap, long int);                \
  542.           else if (is_char)                           \
  543.         signed_number = (signed char) va_arg (ap, unsigned int);      \
  544.           else if (!is_short)                         \
  545.         signed_number = va_arg (ap, int);                 \
  546.           else                                \
  547.         signed_number = (short int) va_arg (ap, unsigned int);        \
  548.         }                                     \
  549.       else                                    \
  550.         if (is_long_num)                              \
  551.           signed_number = args_value[fspec->data_arg].pa_long_int;        \
  552.         else if (is_char)                             \
  553.           signed_number = (signed char)                   \
  554.         args_value[fspec->data_arg].pa_u_int;                 \
  555.         else if (!is_short)                           \
  556.           signed_number = args_value[fspec->data_arg].pa_int;         \
  557.         else                                  \
  558.           signed_number = (short int)                     \
  559.         args_value[fspec->data_arg].pa_u_int;                 \
  560.                                           \
  561.       is_negative = signed_number < 0;                    \
  562.       number.word = is_negative ? (- signed_number) : signed_number;      \
  563.                                           \
  564.       goto LABEL (number);                            \
  565.     }                                     \
  566.       /* NOTREACHED */                                \
  567.                                           \
  568.     LABEL (form_unsigned):                            \
  569.       /* Unsigned decimal integer.  */                        \
  570.       base = 10;                                  \
  571.       goto LABEL (unsigned_number);                       \
  572.       /* NOTREACHED */                                \
  573.                                           \
  574.     LABEL (form_octal):                               \
  575.       /* Unsigned octal integer.  */                          \
  576.       base = 8;                                   \
  577.       goto LABEL (unsigned_number);                       \
  578.       /* NOTREACHED */                                \
  579.                                           \
  580.     LABEL (form_hexa):                                \
  581.       /* Unsigned hexadecimal integer.  */                    \
  582.       base = 16;                                  \
  583.                                           \
  584.     LABEL (unsigned_number):      /* Unsigned number of base BASE.  */        \
  585.                                           \
  586.       /* ISO specifies the `+' and ` ' flags only for signed              \
  587.      conversions.  */                             \
  588.       is_negative = 0;                                \
  589.       showsign = 0;                               \
  590.       space = 0;                                  \
  591.                                           \
  592.       if (is_longlong)                                \
  593.     {                                     \
  594.       if (fspec == NULL)                              \
  595.         number.longlong = va_arg (ap, unsigned long long int);        \
  596.       else                                    \
  597.         number.longlong = args_value[fspec->data_arg].pa_u_long_long_int; \
  598.                                           \
  599.     LABEL (longlong_number):                          \
  600.       if (prec < 0)                               \
  601.         /* Supply a default precision if none was given.  */          \
  602.         prec = 1;                                 \
  603.       else                                    \
  604.         /* We have to take care for the '0' flag.  If a precision         \
  605.            is given it must be ignored.  */                   \
  606.         pad = L_(' ');                            \
  607.                                           \
  608.       /* If the precision is 0 and the number is 0 nothing has to         \
  609.          be written for the number, except for the 'o' format in          \
  610.          alternate form.  */                          \
  611.       if (prec == 0 && number.longlong == 0)                  \
  612.         {                                     \
  613.           string = workend;                           \
  614.           if (base == 8 && alt)                       \
  615.         *--string = L_('0');                          \
  616.         }                                     \
  617.       else                                    \
  618.         {                                     \
  619.           /* Put the number in WORK.  */                      \
  620.           string = _itoa (number.longlong, workend, base,             \
  621.                   spec == L_('X'));                   \
  622.           if (group && grouping)                          \
  623.         string = group_number (string, workend, grouping,         \
  624.                        thousands_sep);                \
  625.                                           \
  626.           if (use_outdigits && base == 10)                    \
  627.         string = _i18n_number_rewrite (string, workend, workend);     \
  628.         }                                     \
  629.       /* Simplify further test for num != 0.  */                  \
  630.       number.word = number.longlong != 0;                     \
  631.     }                                     \
  632.       else                                    \
  633.     {                                     \
  634.       if (fspec == NULL)                              \
  635.         {                                     \
  636.           if (is_long_num)                            \
  637.         number.word = va_arg (ap, unsigned long int);             \
  638.           else if (is_char)                           \
  639.         number.word = (unsigned char) va_arg (ap, unsigned int);      \
  640.           else if (!is_short)                         \
  641.         number.word = va_arg (ap, unsigned int);              \
  642.           else                                \
  643.         number.word = (unsigned short int) va_arg (ap, unsigned int); \
  644.         }                                     \
  645.       else                                    \
  646.         if (is_long_num)                              \
  647.           number.word = args_value[fspec->data_arg].pa_u_long_int;        \
  648.         else if (is_char)                             \
  649.           number.word = (unsigned char)                   \
  650.         args_value[fspec->data_arg].pa_u_int;                 \
  651.         else if (!is_short)                           \
  652.           number.word = args_value[fspec->data_arg].pa_u_int;         \
  653.         else                                  \
  654.           number.word = (unsigned short int)                  \
  655.         args_value[fspec->data_arg].pa_u_int;                 \
  656.                                           \
  657.     LABEL (number):                               \
  658.       if (prec < 0)                               \
  659.         /* Supply a default precision if none was given.  */          \
  660.         prec = 1;                                 \
  661.       else                                    \
  662.         /* We have to take care for the '0' flag.  If a precision         \
  663.            is given it must be ignored.  */                   \
  664.         pad = L_(' ');                            \
  665.                                           \
  666.       /* If the precision is 0 and the number is 0 nothing has to         \
  667.          be written for the number, except for the 'o' format in          \
  668.          alternate form.  */                          \
  669.       if (prec == 0 && number.word == 0)                      \
  670.         {                                     \
  671.           string = workend;                           \
  672.           if (base == 8 && alt)                       \
  673.         *--string = L_('0');                          \
  674.         }                                     \
  675.       else                                    \
  676.         {                                     \
  677.           /* Put the number in WORK.  */                      \
  678.           string = _itoa_word (number.word, workend, base,            \
  679.                    spec == L_('X'));                  \
  680.           if (group && grouping)                          \
  681.         string = group_number (string, workend, grouping,         \
  682.                        thousands_sep);                \
  683.                                           \
  684.           if (use_outdigits && base == 10)                    \
  685.         string = _i18n_number_rewrite (string, workend, workend);     \
  686.         }                                     \
  687.     }                                     \
  688.                                           \
  689.       if (prec <= workend - string && number.word != 0 && alt && base == 8)   \
  690.     /* Add octal marker.  */                          \
  691.     *--string = L_('0');                              \
  692.                                           \
  693.       prec = MAX (0, prec - (workend - string));                  \
  694.                                           \
  695.       if (!left)                                  \
  696.     {                                     \
  697.       width -= workend - string + prec;                   \
  698.                                           \
  699.       if (number.word != 0 && alt && base == 16)                  \
  700.         /* Account for 0X hex marker.  */                     \
  701.         width -= 2;                               \
  702.                                           \
  703.       if (is_negative || showsign || space)                   \
  704.         --width;                                  \
  705.                                           \
  706.       if (pad == L_(' '))                             \
  707.         {                                     \
  708.           PAD (L_(' '));                              \
  709.           width = 0;                              \
  710.         }                                     \
  711.                                           \
  712.       if (is_negative)                            \
  713.         outchar (L_('-'));                            \
  714.       else if (showsign)                              \
  715.         outchar (L_('+'));                            \
  716.       else if (space)                             \
  717.         outchar (L_(' '));                            \
  718.                                           \
  719.       if (number.word != 0 && alt && base == 16)                  \
  720.         {                                     \
  721.           outchar (L_('0'));                          \
  722.           outchar (spec);                             \
  723.         }                                     \
  724.                                           \
  725.       width += prec;                              \
  726.       PAD (L_('0'));                              \
  727.                                           \
  728.       outstring (string, workend - string);                   \
  729.                                           \
  730.       break;                                  \
  731.     }                                     \
  732.       else                                    \
  733.     {                                     \
  734.       if (is_negative)                            \
  735.         {                                     \
  736.           outchar (L_('-'));                          \
  737.           --width;                                \
  738.         }                                     \
  739.       else if (showsign)                              \
  740.         {                                     \
  741.           outchar (L_('+'));                          \
  742.           --width;                                \
  743.         }                                     \
  744.       else if (space)                             \
  745.         {                                     \
  746.           outchar (L_(' '));                          \
  747.           --width;                                \
  748.         }                                     \
  749.                                           \
  750.       if (number.word != 0 && alt && base == 16)                  \
  751.         {                                     \
  752.           outchar (L_('0'));                          \
  753.           outchar (spec);                             \
  754.           width -= 2;                             \
  755.         }                                     \
  756.                                           \
  757.       width -= workend - string + prec;                   \
  758.                                           \
  759.       if (prec > 0)                               \
  760.         {                                     \
  761.           int temp = width;                           \
  762.           width = prec;                           \
  763.           PAD (L_('0'));                              \
  764.           width = temp;                           \
  765.         }                                     \
  766.                                           \
  767.       outstring (string, workend - string);                   \
  768.                                           \
  769.       PAD (L_(' '));                              \
  770.       break;                                  \
  771.     }                                     \
  772.                                           \
  773.     LABEL (form_float):                               \
  774.       {                                       \
  775.     /* Floating-point number.  This is handled by printf_fp.c.  */        \
  776.     const void *ptr;                              \
  777.     int function_done;                            \
  778.                                           \
  779.     if (fspec == NULL)                            \
  780.       {                                   \
  781.         if (__ldbl_is_dbl)                            \
  782.           is_long_double = 0;                         \
  783.                                           \
  784.         struct printf_info info = { .prec = prec,                 \
  785.                     .width = width,               \
  786.                     .spec = spec,                 \
  787.                     .is_long_double = is_long_double,     \
  788.                     .is_short = is_short,             \
  789.                     .is_long = is_long,           \
  790.                     .alt = alt,               \
  791.                     .space = space,               \
  792.                     .left = left,                 \
  793.                     .showsign = showsign,             \
  794.                     .group = group,               \
  795.                     .pad = pad,               \
  796.                     .extra = 0,               \
  797.                     .i18n = use_outdigits,            \
  798.                     .wide = sizeof (CHAR_T) != 1 };       \
  799.                                           \
  800.         if (is_long_double)                           \
  801.           the_arg.pa_long_double = va_arg (ap, long double);          \
  802.         else                                  \
  803.           the_arg.pa_double = va_arg (ap, double);                \
  804.         ptr = (const void *) &the_arg;                    \
  805.                                           \
  806.         function_done = __printf_fp (s, &info, &ptr);             \
  807.       }                                   \
  808.     else                                      \
  809.       {                                   \
  810.         ptr = (const void *) &args_value[fspec->data_arg];            \
  811.         if (__ldbl_is_dbl)                            \
  812.           {                                   \
  813.         fspec->data_arg_type = PA_DOUBLE;                 \
  814.         fspec->info.is_long_double = 0;                   \
  815.           }                                   \
  816.                                           \
  817.         function_done = __printf_fp (s, &fspec->info, &ptr);          \
  818.       }                                   \
  819.                                           \
  820.     if (function_done < 0)                            \
  821.       {                                   \
  822.         /* Error in print handler.  */                    \
  823.         done = -1;                                \
  824.         goto all_done;                            \
  825.       }                                   \
  826.                                           \
  827.     done_add (function_done);                         \
  828.       }                                       \
  829.       break;                                      \
  830.                                           \
  831.     LABEL (form_floathex):                            \
  832.       {                                       \
  833.     /* Floating point number printed as hexadecimal number.  */       \
  834.     const void *ptr;                              \
  835.     int function_done;                            \
  836.                                           \
  837.     if (fspec == NULL)                            \
  838.       {                                   \
  839.         if (__ldbl_is_dbl)                            \
  840.           is_long_double = 0;                         \
  841.                                           \
  842.         struct printf_info info = { .prec = prec,                 \
  843.                     .width = width,               \
  844.                     .spec = spec,                 \
  845.                     .is_long_double = is_long_double,     \
  846.                     .is_short = is_short,             \
  847.                     .is_long = is_long,           \
  848.                     .alt = alt,               \
  849.                     .space = space,               \
  850.                     .left = left,                 \
  851.                     .showsign = showsign,             \
  852.                     .group = group,               \
  853.                     .pad = pad,               \
  854.                     .extra = 0,               \
  855.                     .wide = sizeof (CHAR_T) != 1 };       \
  856.                                           \
  857.         if (is_long_double)                           \
  858.           the_arg.pa_long_double = va_arg (ap, long double);          \
  859.         else                                  \
  860.           the_arg.pa_double = va_arg (ap, double);                \
  861.         ptr = (const void *) &the_arg;                    \
  862.                                           \
  863.         function_done = __printf_fphex (s, &info, &ptr);              \
  864.       }                                   \
  865.     else                                      \
  866.       {                                   \
  867.         ptr = (const void *) &args_value[fspec->data_arg];            \
  868.         if (__ldbl_is_dbl)                            \
  869.           fspec->info.is_long_double = 0;                     \
  870.                                           \
  871.         function_done = __printf_fphex (s, &fspec->info, &ptr);       \
  872.       }                                   \
  873.                                           \
  874.     if (function_done < 0)                            \
  875.       {                                   \
  876.         /* Error in print handler.  */                    \
  877.         done = -1;                                \
  878.         goto all_done;                            \
  879.       }                                   \
  880.                                           \
  881.     done_add (function_done);                         \
  882.       }                                       \
  883.       break;                                      \
  884.                                           \
  885.     LABEL (form_pointer):                             \
  886.       /* Generic pointer.  */                             \
  887.       {                                       \
  888.     const void *ptr;                              \
  889.     if (fspec == NULL)                            \
  890.       ptr = va_arg (ap, void *);                          \
  891.     else                                      \
  892.       ptr = args_value[fspec->data_arg].pa_pointer;               \
  893.     if (ptr != NULL)                              \
  894.       {                                   \
  895.         /* If the pointer is not NULL, write it as a %#x spec.  */        \
  896.         base = 16;                                \
  897.         number.word = (unsigned long int) ptr;                \
  898.         is_negative = 0;                              \
  899.         alt = 1;                                  \
  900.         group = 0;                                \
  901.         spec = L_('x');                           \
  902.         goto LABEL (number);                          \
  903.       }                                   \
  904.     else                                      \
  905.       {                                   \
  906.         /* Write "(nil)" for a nil pointer.  */               \
  907.         string = (CHAR_T *) L_("(nil)");                      \
  908.         /* Make sure the full string "(nil)" is printed.  */          \
  909.         if (prec < 5)                             \
  910.           prec = 5;                               \
  911.         is_long = 0;    /* This is no wide-char string.  */       \
  912.         goto LABEL (print_string);                        \
  913.       }                                   \
  914.       }                                       \
  915.       /* NOTREACHED */                                \
  916.                                           \
  917.     LABEL (form_number):                              \
  918.       if (s->_flags2 & _IO_FLAGS2_FORTIFY)                    \
  919.     {                                     \
  920.       if (! readonly_format)                          \
  921.         {                                     \
  922.           extern int __readonly_area (const void *, size_t)           \
  923.         attribute_hidden;                         \
  924.           readonly_format                             \
  925.         = __readonly_area (format, ((STR_LEN (format) + 1)        \
  926.                         * sizeof (CHAR_T)));          \
  927.         }                                     \
  928.       if (readonly_format < 0)                        \
  929.         __libc_fatal ("*** %n in writable segment detected ***\n");       \
  930.     }                                     \
  931.       /* Answer the count of characters written.  */                  \
  932.       if (fspec == NULL)                              \
  933.     {                                     \
  934.       if (is_longlong)                            \
  935.         *(long long int *) va_arg (ap, void *) = done;            \
  936.       else if (is_long_num)                           \
  937.         *(long int *) va_arg (ap, void *) = done;                 \
  938.       else if (is_char)                           \
  939.         *(char *) va_arg (ap, void *) = done;                 \
  940.       else if (!is_short)                             \
  941.         *(int *) va_arg (ap, void *) = done;                  \
  942.       else                                    \
  943.         *(short int *) va_arg (ap, void *) = done;                \
  944.     }                                     \
  945.       else                                    \
  946.     if (is_longlong)                              \
  947.       *(long long int *) args_value[fspec->data_arg].pa_pointer = done;   \
  948.     else if (is_long_num)                             \
  949.       *(long int *) args_value[fspec->data_arg].pa_pointer = done;        \
  950.     else if (is_char)                             \
  951.       *(char *) args_value[fspec->data_arg].pa_pointer = done;        \
  952.     else if (!is_short)                           \
  953.       *(int *) args_value[fspec->data_arg].pa_pointer = done;         \
  954.     else                                      \
  955.       *(short int *) args_value[fspec->data_arg].pa_pointer = done;       \
  956.       break;                                      \
  957.                                           \
  958.     LABEL (form_strerror):                            \
  959.       /* Print description of error ERRNO.  */                    \
  960.       string =                                    \
  961.     (CHAR_T *) __strerror_r (save_errno, (char *) work_buffer,        \
  962.                  sizeof work_buffer);                 \
  963.       is_long = 0;      /* This is no wide-char string.  */       \
  964.       goto LABEL (print_string)
  965.  
  966. #ifdef COMPILE_WPRINTF
  967. # define process_string_arg(fspec) \
  968.     LABEL (form_character):                           \
  969.       /* Character.  */                               \
  970.       if (is_long)                                \
  971.     goto LABEL (form_wcharacter);                         \
  972.       --width;  /* Account for the character itself.  */              \
  973.       if (!left)                                  \
  974.     PAD (L' ');                               \
  975.       if (fspec == NULL)                              \
  976.     outchar (__btowc ((unsigned char) va_arg (ap, int))); /* Promoted. */ \
  977.       else                                    \
  978.     outchar (__btowc ((unsigned char)                     \
  979.               args_value[fspec->data_arg].pa_int));           \
  980.       if (left)                                   \
  981.     PAD (L' ');                               \
  982.       break;                                      \
  983.                                           \
  984.     LABEL (form_wcharacter):                              \
  985.       {                                       \
  986.     /* Wide character.  */                            \
  987.     --width;                                  \
  988.     if (!left)                                \
  989.       PAD (L' ');                                 \
  990.     if (fspec == NULL)                            \
  991.       outchar (va_arg (ap, wchar_t));                     \
  992.     else                                      \
  993.       outchar (args_value[fspec->data_arg].pa_wchar);             \
  994.     if (left)                                 \
  995.       PAD (L' ');                                 \
  996.       }                                       \
  997.       break;                                      \
  998.                                           \
  999.     LABEL (form_string):                              \
  1000.       {                                       \
  1001.     size_t len;                               \
  1002.     int string_malloced;                              \
  1003.                                           \
  1004.     /* The string argument could in fact be `char *' or `wchar_t *'.      \
  1005.        But this should not make a difference here.  */            \
  1006.     if (fspec == NULL)                            \
  1007.       string = (CHAR_T *) va_arg (ap, const wchar_t *);           \
  1008.     else                                      \
  1009.       string = (CHAR_T *) args_value[fspec->data_arg].pa_wstring;         \
  1010.                                           \
  1011.     /* Entry point for printing other strings.  */                \
  1012.       LABEL (print_string):                           \
  1013.                                           \
  1014.     string_malloced = 0;                              \
  1015.     if (string == NULL)                           \
  1016.       {                                   \
  1017.         /* Write "(null)" if there's space.  */               \
  1018.         if (prec == -1                            \
  1019.         || prec >= (int) (sizeof (null) / sizeof (null[0])) - 1)      \
  1020.           {                                   \
  1021.         string = (CHAR_T *) null;                     \
  1022.         len = (sizeof (null) / sizeof (null[0])) - 1;             \
  1023.           }                                   \
  1024.         else                                  \
  1025.           {                                   \
  1026.         string = (CHAR_T *) L"";                      \
  1027.         len = 0;                              \
  1028.           }                                   \
  1029.       }                                   \
  1030.     else if (!is_long && spec != L_('S'))                     \
  1031.       {                                   \
  1032.         /* This is complicated.  We have to transform the multibyte       \
  1033.            string into a wide character string.  */               \
  1034.         const char *mbs = (const char *) string;                  \
  1035.         mbstate_t mbstate;                            \
  1036.                                           \
  1037.         len = prec != -1 ? __strnlen (mbs, (size_t) prec) : strlen (mbs); \
  1038.                                           \
  1039.         /* Allocate dynamically an array which definitely is long         \
  1040.            enough for the wide character version.  Each byte in the       \
  1041.            multi-byte string can produce at most one wide character.  */  \
  1042.         if (__libc_use_alloca (len * sizeof (wchar_t)))           \
  1043.           string = (CHAR_T *) alloca (len * sizeof (wchar_t));        \
  1044.         else if ((string = (CHAR_T *) malloc (len * sizeof (wchar_t)))    \
  1045.              == NULL)                             \
  1046.           {                                   \
  1047.         done = -1;                            \
  1048.         goto all_done;                            \
  1049.           }                                   \
  1050.         else                                  \
  1051.           string_malloced = 1;                        \
  1052.                                           \
  1053.         memset (&mbstate, '\0', sizeof (mbstate_t));              \
  1054.         len = __mbsrtowcs (string, &mbs, len, &mbstate);              \
  1055.         if (len == (size_t) -1)                       \
  1056.           {                                   \
  1057.         /* Illegal multibyte character.  */               \
  1058.         done = -1;                            \
  1059.         goto all_done;                            \
  1060.           }                                   \
  1061.       }                                   \
  1062.     else                                      \
  1063.       {                                   \
  1064.         if (prec != -1)                           \
  1065.           /* Search for the end of the string, but don't search past      \
  1066.          the length specified by the precision.  */           \
  1067.           len = __wcsnlen (string, prec);                     \
  1068.         else                                  \
  1069.           len = __wcslen (string);                        \
  1070.       }                                   \
  1071.                                           \
  1072.     if ((width -= len) < 0)                           \
  1073.       {                                   \
  1074.         outstring (string, len);                          \
  1075.         break;                                \
  1076.       }                                   \
  1077.                                           \
  1078.     if (!left)                                \
  1079.       PAD (L' ');                                 \
  1080.     outstring (string, len);                          \
  1081.     if (left)                                 \
  1082.       PAD (L' ');                                 \
  1083.     if (__builtin_expect (string_malloced, 0))                \
  1084.       free (string);                              \
  1085.       }                                       \
  1086.       break;
  1087. #else
  1088. # define process_string_arg(fspec) \
  1089.     LABEL (form_character):                           \
  1090.       /* Character.  */                               \
  1091.       if (is_long)                                \
  1092.     goto LABEL (form_wcharacter);                         \
  1093.       --width;  /* Account for the character itself.  */              \
  1094.       if (!left)                                  \
  1095.     PAD (' ');                                \
  1096.       if (fspec == NULL)                              \
  1097.     outchar ((unsigned char) va_arg (ap, int)); /* Promoted.  */          \
  1098.       else                                    \
  1099.     outchar ((unsigned char) args_value[fspec->data_arg].pa_int);         \
  1100.       if (left)                                   \
  1101.     PAD (' ');                                \
  1102.       break;                                      \
  1103.                                           \
  1104.     LABEL (form_wcharacter):                              \
  1105.       {                                       \
  1106.     /* Wide character.  */                            \
  1107.     char buf[MB_CUR_MAX];                             \
  1108.     mbstate_t mbstate;                            \
  1109.     size_t len;                               \
  1110.                                           \
  1111.     memset (&mbstate, '\0', sizeof (mbstate_t));                  \
  1112.     len = __wcrtomb (buf, (fspec == NULL ? va_arg (ap, wchar_t)       \
  1113.                    : args_value[fspec->data_arg].pa_wchar),       \
  1114.              &mbstate);                       \
  1115.     if (len == (size_t) -1)                           \
  1116.       {                                   \
  1117.         /* Something went wron gduring the conversion.  Bail out.  */     \
  1118.         done = -1;                                \
  1119.         goto all_done;                            \
  1120.       }                                   \
  1121.     width -= len;                                 \
  1122.     if (!left)                                \
  1123.       PAD (' ');                                  \
  1124.     outstring (buf, len);                             \
  1125.     if (left)                                 \
  1126.       PAD (' ');                                  \
  1127.       }                                       \
  1128.       break;                                      \
  1129.                                           \
  1130.     LABEL (form_string):                              \
  1131.       {                                       \
  1132.     size_t len;                               \
  1133.     int string_malloced;                              \
  1134.                                           \
  1135.     /* The string argument could in fact be `char *' or `wchar_t *'.      \
  1136.        But this should not make a difference here.  */            \
  1137.     if (fspec == NULL)                            \
  1138.       string = (char *) va_arg (ap, const char *);                \
  1139.     else                                      \
  1140.       string = (char *) args_value[fspec->data_arg].pa_string;        \
  1141.                                           \
  1142.     /* Entry point for printing other strings.  */                \
  1143.       LABEL (print_string):                           \
  1144.                                           \
  1145.     string_malloced = 0;                              \
  1146.     if (string == NULL)                           \
  1147.       {                                   \
  1148.         /* Write "(null)" if there's space.  */               \
  1149.         if (prec == -1 || prec >= (int) sizeof (null) - 1)            \
  1150.           {                                   \
  1151.         string = (char *) null;                       \
  1152.         len = sizeof (null) - 1;                      \
  1153.           }                                   \
  1154.         else                                  \
  1155.           {                                   \
  1156.         string = (char *) "";                         \
  1157.         len = 0;                              \
  1158.           }                                   \
  1159.       }                                   \
  1160.     else if (!is_long && spec != L_('S'))                     \
  1161.       {                                   \
  1162.         if (prec != -1)                           \
  1163.           {                                   \
  1164.         /* Search for the end of the string, but don't search past    \
  1165.            the length (in bytes) specified by the precision.  Also    \
  1166.            don't use incomplete characters.  */               \
  1167.         if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) == 1)   \
  1168.           len = __strnlen (string, prec);                 \
  1169.         else                                  \
  1170.           {                               \
  1171.             /* In case we have a multibyte character set the          \
  1172.                situation is more complicated.  We must not copy       \
  1173.                bytes at the end which form an incomplete character. */\
  1174.             size_t ignore_size = (unsigned) prec > 1024 ? 1024 : prec;\
  1175.             wchar_t ignore[ignore_size];                  \
  1176.             const char *str2 = string;                    \
  1177.             const char *strend = string + prec;               \
  1178.             if (strend < string)                      \
  1179.               strend = (const char *) UINTPTR_MAX;            \
  1180.                                           \
  1181.             mbstate_t ps;                         \
  1182.             memset (&ps, '\0', sizeof (ps));                  \
  1183.                                           \
  1184.             while (str2 != NULL && str2 < strend)             \
  1185.               if (__mbsnrtowcs (ignore, &str2, strend - str2,         \
  1186.                     ignore_size, &ps) == (size_t) -1)     \
  1187.             {                             \
  1188.               done = -1;                          \
  1189.               goto all_done;                      \
  1190.             }                             \
  1191.                                           \
  1192.             if (str2 == NULL)                         \
  1193.               len = strlen (string);                      \
  1194.             else                              \
  1195.               len = str2 - string - (ps.__count & 7);             \
  1196.           }                               \
  1197.           }                                   \
  1198.         else                                  \
  1199.           len = strlen (string);                          \
  1200.       }                                   \
  1201.     else                                      \
  1202.       {                                   \
  1203.         const wchar_t *s2 = (const wchar_t *) string;             \
  1204.         mbstate_t mbstate;                            \
  1205.                                           \
  1206.         memset (&mbstate, '\0', sizeof (mbstate_t));              \
  1207.                                           \
  1208.         if (prec >= 0)                            \
  1209.           {                                   \
  1210.         /* The string `s2' might not be NUL terminated.  */       \
  1211.         if (__libc_use_alloca (prec))                     \
  1212.           string = (char *) alloca (prec);                \
  1213.         else if ((string = (char *) malloc (prec)) == NULL)       \
  1214.           {                               \
  1215.             done = -1;                            \
  1216.             goto all_done;                        \
  1217.           }                               \
  1218.         else                                  \
  1219.           string_malloced = 1;                        \
  1220.         len = __wcsrtombs (string, &s2, prec, &mbstate);          \
  1221.           }                                   \
  1222.         else                                  \
  1223.           {                                   \
  1224.         len = __wcsrtombs (NULL, &s2, 0, &mbstate);           \
  1225.         if (len != (size_t) -1)                       \
  1226.           {                               \
  1227.             assert (__mbsinit (&mbstate));                \
  1228.             s2 = (const wchar_t *) string;                \
  1229.             if (__libc_use_alloca (len + 1))                  \
  1230.               string = (char *) alloca (len + 1);             \
  1231.             else if ((string = (char *) malloc (len + 1)) == NULL)    \
  1232.               {                               \
  1233.             done = -1;                        \
  1234.             goto all_done;                        \
  1235.               }                               \
  1236.             else                              \
  1237.               string_malloced = 1;                    \
  1238.             (void) __wcsrtombs (string, &s2, len + 1, &mbstate);      \
  1239.           }                               \
  1240.           }                                   \
  1241.                                           \
  1242.         if (len == (size_t) -1)                       \
  1243.           {                                   \
  1244.         /* Illegal wide-character string.  */                 \
  1245.         done = -1;                            \
  1246.         goto all_done;                            \
  1247.           }                                   \
  1248.       }                                   \
  1249.                                           \
  1250.     if ((width -= len) < 0)                           \
  1251.       {                                   \
  1252.         outstring (string, len);                          \
  1253.         break;                                \
  1254.       }                                   \
  1255.                                           \
  1256.     if (!left)                                \
  1257.       PAD (' ');                                  \
  1258.     outstring (string, len);                          \
  1259.     if (left)                                 \
  1260.       PAD (' ');                                  \
  1261.     if (__builtin_expect (string_malloced, 0))                \
  1262.       free (string);                              \
  1263.       }                                       \
  1264.       break;
  1265. #endif
  1266.  
  1267.   /* Orient the stream.  */
  1268. #ifdef ORIENT
  1269.   ORIENT;
  1270. #endif
  1271.  
  1272.   /* Sanity check of arguments.  */
  1273.   ARGCHECK (s, format);
  1274.  
  1275. #ifdef ORIENT
  1276.   /* Check for correct orientation.  */
  1277.   if (_IO_vtable_offset (s) == 0 &&
  1278.       _IO_fwide (s, sizeof (CHAR_T) == 1 ? -1 : 1)
  1279.       != (sizeof (CHAR_T) == 1 ? -1 : 1))
  1280.     /* The stream is already oriented otherwise.  */
  1281.     return EOF;
  1282. #endif
  1283.  
  1284.   if (UNBUFFERED_P (s))
  1285.     /* Use a helper function which will allocate a local temporary buffer
  1286.        for the stream and then call us again.  */
  1287.     return buffered_vfprintf (s, format, ap);
  1288.  
  1289.   /* Initialize local variables.  */
  1290.   done = 0;
  1291.   grouping = (const char *) -1;
  1292. #ifdef __va_copy
  1293.   /* This macro will be available soon in gcc's <stdarg.h>.  We need it
  1294.      since on some systems `va_list' is not an integral type.  */
  1295.   __va_copy (ap_save, ap);
  1296. #else
  1297.   ap_save = ap;
  1298. #endif
  1299.   nspecs_done = 0;
  1300.  
  1301. #ifdef COMPILE_WPRINTF
  1302.   /* Find the first format specifier.  */
  1303.   f = lead_str_end = __find_specwc ((const UCHAR_T *) format);
  1304. #else
  1305.   /* Find the first format specifier.  */
  1306.   f = lead_str_end = __find_specmb ((const UCHAR_T *) format);
  1307. #endif
  1308.  
  1309.   /* Lock stream.  */
  1310.   _IO_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, s);
  1311.   _IO_flockfile (s);
  1312.  
  1313.   /* Write the literal text before the first format.  */
  1314.   outstring ((const UCHAR_T *) format,
  1315.          lead_str_end - (const UCHAR_T *) format);
  1316.  
  1317.   /* If we only have to print a simple string, return now.  */
  1318.   if (*f == L_('\0'))
  1319.     goto all_done;
  1320.  
  1321.   /* Use the slow path in case any printf handler is registered.  */
  1322.   if (__builtin_expect (__printf_function_table != NULL
  1323.             || __printf_modifier_table != NULL
  1324.             || __printf_va_arg_table != NULL, 0))
  1325.     goto do_positional;
  1326.  
  1327.   /* Process whole format string.  */
  1328.   do
  1329.     {
  1330. #ifdef SHARED
  1331. # define REF(Name) &&do_##Name - &&do_form_unknown
  1332. #else
  1333. # define REF(Name) &&do_##Name
  1334. #endif
  1335. #define LABEL(Name) do_##Name
  1336.       STEP0_3_TABLE;
  1337.       STEP4_TABLE;
  1338.  
  1339.       union printf_arg *args_value; /* This is not used here but ... */
  1340.       int is_negative;  /* Flag for negative number.  */
  1341.       union
  1342.       {
  1343.     unsigned long long int longlong;
  1344.     unsigned long int word;
  1345.       } number;
  1346.       int base;
  1347.       union printf_arg the_arg;
  1348.       CHAR_T *string;   /* Pointer to argument string.  */
  1349.       int alt = 0;  /* Alternate format.  */
  1350.       int space = 0;    /* Use space prefix if no sign is needed.  */
  1351.       int left = 0; /* Left-justify output.  */
  1352.       int showsign = 0; /* Always begin with plus or minus sign.  */
  1353.       int group = 0;    /* Print numbers according grouping rules.  */
  1354.       int is_long_double = 0; /* Argument is long double/ long long int.  */
  1355.       int is_short = 0; /* Argument is short int.  */
  1356.       int is_long = 0;  /* Argument is long int.  */
  1357.       int is_char = 0;  /* Argument is promoted (unsigned) char.  */
  1358.       int width = 0;    /* Width of output; 0 means none specified.  */
  1359.       int prec = -1;    /* Precision of output; -1 means none specified.  */
  1360.       /* This flag is set by the 'I' modifier and selects the use of the
  1361.      `outdigits' as determined by the current locale.  */
  1362.       int use_outdigits = 0;
  1363.       UCHAR_T pad = L_(' ');/* Padding character.  */
  1364.       CHAR_T spec;
  1365.  
  1366.       workstart = NULL;
  1367.       workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)];
  1368.  
  1369.       /* Get current character in format string.  */
  1370.       JUMP (*++f, step0_jumps);
  1371.  
  1372.       /* ' ' flag.  */
  1373.     LABEL (flag_space):
  1374.       space = 1;
  1375.       JUMP (*++f, step0_jumps);
  1376.  
  1377.       /* '+' flag.  */
  1378.     LABEL (flag_plus):
  1379.       showsign = 1;
  1380.       JUMP (*++f, step0_jumps);
  1381.  
  1382.       /* The '-' flag.  */
  1383.     LABEL (flag_minus):
  1384.       left = 1;
  1385.       pad = L_(' ');
  1386.       JUMP (*++f, step0_jumps);
  1387.  
  1388.       /* The '#' flag.  */
  1389.     LABEL (flag_hash):
  1390.       alt = 1;
  1391.       JUMP (*++f, step0_jumps);
  1392.  
  1393.       /* The '0' flag.  */
  1394.     LABEL (flag_zero):
  1395.       if (!left)
  1396.     pad = L_('0');
  1397.       JUMP (*++f, step0_jumps);
  1398.  
  1399.       /* The '\'' flag.  */
  1400.     LABEL (flag_quote):
  1401.       group = 1;
  1402.  
  1403.       if (grouping == (const char *) -1)
  1404.     {
  1405. #ifdef COMPILE_WPRINTF
  1406.       thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
  1407.                         _NL_NUMERIC_THOUSANDS_SEP_WC);
  1408. #else
  1409.       thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
  1410. #endif
  1411.  
  1412.       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
  1413.       if (*grouping == '\0' || *grouping == CHAR_MAX
  1414. #ifdef COMPILE_WPRINTF
  1415.           || thousands_sep == L'\0'
  1416. #else
  1417.           || *thousands_sep == '\0'
  1418. #endif
  1419.           )
  1420.         grouping = NULL;
  1421.     }
  1422.       JUMP (*++f, step0_jumps);
  1423.  
  1424.     LABEL (flag_i18n):
  1425.       use_outdigits = 1;
  1426.       JUMP (*++f, step0_jumps);
  1427.  
  1428.       /* Get width from argument.  */
  1429.     LABEL (width_asterics):
  1430.       {
  1431.     const UCHAR_T *tmp; /* Temporary value.  */
  1432.  
  1433.     tmp = ++f;
  1434.     if (ISDIGIT (*tmp) && read_int (&tmp) && *tmp == L_('$'))
  1435.       /* The width comes from a positional parameter.  */
  1436.       goto do_positional;
  1437.  
  1438.     width = va_arg (ap, int);
  1439.  
  1440.     /* Negative width means left justified.  */
  1441.     if (width < 0)
  1442.       {
  1443.         width = -width;
  1444.         pad = L_(' ');
  1445.         left = 1;
  1446.       }
  1447.  
  1448.     if (__builtin_expect (width >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
  1449.       {
  1450.         __set_errno (ERANGE);
  1451.         done = -1;
  1452.         goto all_done;
  1453.       }
  1454.  
  1455.     if (width >= sizeof (work_buffer) / sizeof (work_buffer[0]) - 32)
  1456.       {
  1457.         /* We have to use a special buffer.  The "32" is just a safe
  1458.            bet for all the output which is not counted in the width.  */
  1459.         size_t needed = ((size_t) width + 32) * sizeof (CHAR_T);
  1460.         if (__libc_use_alloca (needed))
  1461.           workend = (CHAR_T *) alloca (needed) + width + 32;
  1462.         else
  1463.           {
  1464.         workstart = (CHAR_T *) malloc (needed);
  1465.         if (workstart == NULL)
  1466.           {
  1467.             done = -1;
  1468.             goto all_done;
  1469.           }
  1470.         workend = workstart + width + 32;
  1471.           }
  1472.       }
  1473.       }
  1474.       JUMP (*f, step1_jumps);
  1475.  
  1476.       /* Given width in format string.  */
  1477.     LABEL (width):
  1478.       width = read_int (&f);
  1479.  
  1480.       if (__builtin_expect (width >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
  1481.     {
  1482.       __set_errno (ERANGE);
  1483.       done = -1;
  1484.       goto all_done;
  1485.     }
  1486.  
  1487.       if (width >= sizeof (work_buffer) / sizeof (work_buffer[0]) - 32)
  1488.     {
  1489.       /* We have to use a special buffer.  The "32" is just a safe
  1490.          bet for all the output which is not counted in the width.  */
  1491.       size_t needed = ((size_t) width + 32) * sizeof (CHAR_T);
  1492.       if (__libc_use_alloca (needed))
  1493.         workend = (CHAR_T *) alloca (needed) + width + 32;
  1494.       else
  1495.         {
  1496.           workstart = (CHAR_T *) malloc (needed);
  1497.           if (workstart == NULL)
  1498.         {
  1499.           done = -1;
  1500.           goto all_done;
  1501.         }
  1502.           workend = workstart + width + 32;
  1503.         }
  1504.     }
  1505.       if (*f == L_('$'))
  1506.     /* Oh, oh.  The argument comes from a positional parameter.  */
  1507.     goto do_positional;
  1508.       JUMP (*f, step1_jumps);
  1509.  
  1510.     LABEL (precision):
  1511.       ++f;
  1512.       if (*f == L_('*'))
  1513.     {
  1514.       const UCHAR_T *tmp;   /* Temporary value.  */
  1515.  
  1516.       tmp = ++f;
  1517.       if (ISDIGIT (*tmp) && read_int (&tmp) > 0 && *tmp == L_('$'))
  1518.         /* The precision comes from a positional parameter.  */
  1519.         goto do_positional;
  1520.  
  1521.       prec = va_arg (ap, int);
  1522.  
  1523.       /* If the precision is negative the precision is omitted.  */
  1524.       if (prec < 0)
  1525.         prec = -1;
  1526.     }
  1527.       else if (ISDIGIT (*f))
  1528.     prec = read_int (&f);
  1529.       else
  1530.     prec = 0;
  1531.       if (prec > width
  1532.       && prec > sizeof (work_buffer) / sizeof (work_buffer[0]) - 32)
  1533.     {
  1534.       if (__builtin_expect (prec >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
  1535.         {
  1536.           __set_errno (ERANGE);
  1537.           done = -1;
  1538.           goto all_done;
  1539.         }
  1540.       size_t needed = ((size_t) prec + 32) * sizeof (CHAR_T);
  1541.  
  1542.       if (__libc_use_alloca (needed))
  1543.         workend = (CHAR_T *) alloca (needed) + prec + 32;
  1544.       else
  1545.         {
  1546.           workstart = (CHAR_T *) malloc (needed);
  1547.           if (workstart == NULL)
  1548.         {
  1549.           done = -1;
  1550.           goto all_done;
  1551.         }
  1552.           workend = workstart + prec + 32;
  1553.         }
  1554.     }
  1555.       JUMP (*f, step2_jumps);
  1556.  
  1557.       /* Process 'h' modifier.  There might another 'h' following.  */
  1558.     LABEL (mod_half):
  1559.       is_short = 1;
  1560.       JUMP (*++f, step3a_jumps);
  1561.  
  1562.       /* Process 'hh' modifier.  */
  1563.     LABEL (mod_halfhalf):
  1564.       is_short = 0;
  1565.       is_char = 1;
  1566.       JUMP (*++f, step4_jumps);
  1567.  
  1568.       /* Process 'l' modifier.  There might another 'l' following.  */
  1569.     LABEL (mod_long):
  1570.       is_long = 1;
  1571.       JUMP (*++f, step3b_jumps);
  1572.  
  1573.       /* Process 'L', 'q', or 'll' modifier.  No other modifier is
  1574.      allowed to follow.  */
  1575.     LABEL (mod_longlong):
  1576.       is_long_double = 1;
  1577.       is_long = 1;
  1578.       JUMP (*++f, step4_jumps);
  1579.  
  1580.     LABEL (mod_size_t):
  1581.       is_long_double = sizeof (size_t) > sizeof (unsigned long int);
  1582.       is_long = sizeof (size_t) > sizeof (unsigned int);
  1583.       JUMP (*++f, step4_jumps);
  1584.  
  1585.     LABEL (mod_ptrdiff_t):
  1586.       is_long_double = sizeof (ptrdiff_t) > sizeof (unsigned long int);
  1587.       is_long = sizeof (ptrdiff_t) > sizeof (unsigned int);
  1588.       JUMP (*++f, step4_jumps);
  1589.  
  1590.     LABEL (mod_intmax_t):
  1591.       is_long_double = sizeof (intmax_t) > sizeof (unsigned long int);
  1592.       is_long = sizeof (intmax_t) > sizeof (unsigned int);
  1593.       JUMP (*++f, step4_jumps);
  1594.  
  1595.       /* Process current format.  */
  1596.       while (1)
  1597.     {
  1598.       process_arg (((struct printf_spec *) NULL));
  1599.       process_string_arg (((struct printf_spec *) NULL));
  1600.  
  1601.     LABEL (form_unknown):
  1602.       if (spec == L_('\0'))
  1603.         {
  1604.           /* The format string ended before the specifier is complete.  */
  1605.           done = -1;
  1606.           goto all_done;
  1607.         }
  1608.  
  1609.       /* If we are in the fast loop force entering the complicated
  1610.          one.  */
  1611.       goto do_positional;
  1612.     }
  1613.  
  1614.       /* The format is correctly handled.  */
  1615.       ++nspecs_done;
  1616.  
  1617.       if (__builtin_expect (workstart != NULL, 0))
  1618.     free (workstart);
  1619.       workstart = NULL;
  1620.  
  1621.       /* Look for next format specifier.  */
  1622. #ifdef COMPILE_WPRINTF
  1623.       f = __find_specwc ((end_of_spec = ++f));
  1624. #else
  1625.       f = __find_specmb ((end_of_spec = ++f));
  1626. #endif
  1627.  
  1628.       /* Write the following constant string.  */
  1629.       outstring (end_of_spec, f - end_of_spec);
  1630.     }
  1631.   while (*f != L_('\0'));
  1632.  
  1633.   /* Unlock stream and return.  */
  1634.   goto all_done;
  1635.  
  1636.   /* Here starts the more complex loop to handle positional parameters.  */
  1637. do_positional:
  1638.   {
  1639.     /* Array with information about the needed arguments.  This has to
  1640.        be dynamically extensible.  */
  1641.     size_t nspecs = 0;
  1642.     size_t nspecs_max = 32; /* A more or less arbitrary start value.  */
  1643.     struct printf_spec *specs
  1644.       = alloca (nspecs_max * sizeof (struct printf_spec));
  1645.  
  1646.     /* The number of arguments the format string requests.  This will
  1647.        determine the size of the array needed to store the argument
  1648.        attributes.  */
  1649.     size_t nargs = 0;
  1650.     int *args_type;
  1651.     union printf_arg *args_value = NULL;
  1652.     int *args_size;
  1653.  
  1654.     /* Positional parameters refer to arguments directly.  This could
  1655.        also determine the maximum number of arguments.  Track the
  1656.        maximum number.  */
  1657.     size_t max_ref_arg = 0;
  1658.  
  1659.     /* Just a counter.  */
  1660.     size_t cnt;
  1661.  
  1662.     free (workstart);
  1663.     workstart = NULL;
  1664.  
  1665.     if (grouping == (const char *) -1)
  1666.       {
  1667. #ifdef COMPILE_WPRINTF
  1668.     thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
  1669.                       _NL_NUMERIC_THOUSANDS_SEP_WC);
  1670. #else
  1671.     thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
  1672. #endif
  1673.  
  1674.     grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
  1675.     if (*grouping == '\0' || *grouping == CHAR_MAX)
  1676.       grouping = NULL;
  1677.       }
  1678.  
  1679.     for (f = lead_str_end; *f != L_('\0'); f = specs[nspecs++].next_fmt)
  1680.       {
  1681.     if (nspecs >= nspecs_max)
  1682.       {
  1683.         /* Extend the array of format specifiers.  */
  1684.         struct printf_spec *old = specs;
  1685.         specs = extend_alloca (specs, nspecs_max, 2 * nspecs_max);
  1686.  
  1687.         /* Copy the old array's elements to the new space.  */
  1688.         memmove (specs, old, nspecs * sizeof (struct printf_spec));
  1689.       }
  1690.  
  1691.     /* Parse the format specifier.  */
  1692. #ifdef COMPILE_WPRINTF
  1693.     nargs += __parse_one_specwc (f, nargs, &specs[nspecs], &max_ref_arg);
  1694. #else
  1695.     nargs += __parse_one_specmb (f, nargs, &specs[nspecs], &max_ref_arg);
  1696. #endif
  1697.       }
  1698.  
  1699.     /* Determine the number of arguments the format string consumes.  */
  1700.     nargs = MAX (nargs, max_ref_arg);
  1701.  
  1702.     /* Allocate memory for the argument descriptions.  */
  1703.     args_type = alloca (nargs * sizeof (int));
  1704.     memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
  1705.         nargs * sizeof (int));
  1706.     args_value = alloca (nargs * sizeof (union printf_arg));
  1707.     args_size = alloca (nargs * sizeof (int));
  1708.  
  1709.     /* XXX Could do sanity check here: If any element in ARGS_TYPE is
  1710.        still zero after this loop, format is invalid.  For now we
  1711.        simply use 0 as the value.  */
  1712.  
  1713.     /* Fill in the types of all the arguments.  */
  1714.     for (cnt = 0; cnt < nspecs; ++cnt)
  1715.       {
  1716.     /* If the width is determined by an argument this is an int.  */
  1717.     if (specs[cnt].width_arg != -1)
  1718.       args_type[specs[cnt].width_arg] = PA_INT;
  1719.  
  1720.     /* If the precision is determined by an argument this is an int.  */
  1721.     if (specs[cnt].prec_arg != -1)
  1722.       args_type[specs[cnt].prec_arg] = PA_INT;
  1723.  
  1724.     switch (specs[cnt].ndata_args)
  1725.       {
  1726.       case 0:       /* No arguments.  */
  1727.         break;
  1728.       case 1:       /* One argument; we already have the
  1729.                    type and size.  */
  1730.         args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type;
  1731.         args_size[specs[cnt].data_arg] = specs[cnt].size;
  1732.         break;
  1733.       default:
  1734.         /* We have more than one argument for this format spec.
  1735.            We must call the arginfo function again to determine
  1736.            all the types.  */
  1737.         (void) (*__printf_arginfo_table[specs[cnt].info.spec])
  1738.           (&specs[cnt].info,
  1739.            specs[cnt].ndata_args, &args_type[specs[cnt].data_arg],
  1740.            &args_size[specs[cnt].data_arg]);
  1741.         break;
  1742.       }
  1743.       }
  1744.  
  1745.     /* Now we know all the types and the order.  Fill in the argument
  1746.        values.  */
  1747.     for (cnt = 0; cnt < nargs; ++cnt)
  1748.       switch (args_type[cnt])
  1749.     {
  1750. #define T(tag, mem, type)                             \
  1751.     case tag:                                 \
  1752.       args_value[cnt].mem = va_arg (ap_save, type);               \
  1753.       break
  1754.  
  1755.     T (PA_WCHAR, pa_wchar, wint_t);
  1756.     case PA_CHAR:               /* Promoted.  */
  1757.     case PA_INT|PA_FLAG_SHORT:      /* Promoted.  */
  1758. #if LONG_MAX == INT_MAX
  1759.     case PA_INT|PA_FLAG_LONG:
  1760. #endif
  1761.     T (PA_INT, pa_int, int);
  1762. #if LONG_MAX == LONG_LONG_MAX
  1763.     case PA_INT|PA_FLAG_LONG:
  1764. #endif
  1765.     T (PA_INT|PA_FLAG_LONG_LONG, pa_long_long_int, long long int);
  1766. #if LONG_MAX != INT_MAX && LONG_MAX != LONG_LONG_MAX
  1767. # error "he?"
  1768. #endif
  1769.     case PA_FLOAT:              /* Promoted.  */
  1770.     T (PA_DOUBLE, pa_double, double);
  1771.     case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
  1772.       if (__ldbl_is_dbl)
  1773.         {
  1774.           args_value[cnt].pa_double = va_arg (ap_save, double);
  1775.           args_type[cnt] &= ~PA_FLAG_LONG_DOUBLE;
  1776.         }
  1777.       else
  1778.         args_value[cnt].pa_long_double = va_arg (ap_save, long double);
  1779.       break;
  1780.     case PA_STRING:             /* All pointers are the same */
  1781.     case PA_WSTRING:            /* All pointers are the same */
  1782.     T (PA_POINTER, pa_pointer, void *);
  1783. #undef T
  1784.     default:
  1785.       if ((args_type[cnt] & PA_FLAG_PTR) != 0)
  1786.         args_value[cnt].pa_pointer = va_arg (ap_save, void *);
  1787.       else if (__builtin_expect (__printf_va_arg_table != NULL, 0)
  1788.            && __printf_va_arg_table[args_type[cnt] - PA_LAST] != NULL)
  1789.         {
  1790.           args_value[cnt].pa_user = alloca (args_size[cnt]);
  1791.           (*__printf_va_arg_table[args_type[cnt] - PA_LAST])
  1792.         (args_value[cnt].pa_user, &ap_save);
  1793.         }
  1794.       else
  1795.         args_value[cnt].pa_long_double = 0.0;
  1796.       break;
  1797.     case -1:
  1798.       /* Error case.  Not all parameters appear in N$ format
  1799.          strings.  We have no way to determine their type.  */
  1800.       assert (s->_flags2 & _IO_FLAGS2_FORTIFY);
  1801.       __libc_fatal ("*** invalid %N$ use detected ***\n");
  1802.     }
  1803.  
  1804.     /* Now walk through all format specifiers and process them.  */
  1805.     for (; (size_t) nspecs_done < nspecs; ++nspecs_done)
  1806.       {
  1807. #undef REF
  1808. #ifdef SHARED
  1809. # define REF(Name) &&do2_##Name - &&do_form_unknown
  1810. #else
  1811. # define REF(Name) &&do2_##Name
  1812. #endif
  1813. #undef LABEL
  1814. #define LABEL(Name) do2_##Name
  1815.     STEP4_TABLE;
  1816.  
  1817.     int is_negative;
  1818.     union
  1819.     {
  1820.       unsigned long long int longlong;
  1821.       unsigned long int word;
  1822.     } number;
  1823.     int base;
  1824.     union printf_arg the_arg;
  1825.     CHAR_T *string;     /* Pointer to argument string.  */
  1826.  
  1827.     /* Fill variables from values in struct.  */
  1828.     int alt = specs[nspecs_done].info.alt;
  1829.     int space = specs[nspecs_done].info.space;
  1830.     int left = specs[nspecs_done].info.left;
  1831.     int showsign = specs[nspecs_done].info.showsign;
  1832.     int group = specs[nspecs_done].info.group;
  1833.     int is_long_double = specs[nspecs_done].info.is_long_double;
  1834.     int is_short = specs[nspecs_done].info.is_short;
  1835.     int is_char = specs[nspecs_done].info.is_char;
  1836.     int is_long = specs[nspecs_done].info.is_long;
  1837.     int width = specs[nspecs_done].info.width;
  1838.     int prec = specs[nspecs_done].info.prec;
  1839.     int use_outdigits = specs[nspecs_done].info.i18n;
  1840.     char pad = specs[nspecs_done].info.pad;
  1841.     CHAR_T spec = specs[nspecs_done].info.spec;
  1842.  
  1843.     workstart = NULL;
  1844.     workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)];
  1845.  
  1846.     /* Fill in last information.  */
  1847.     if (specs[nspecs_done].width_arg != -1)
  1848.       {
  1849.         /* Extract the field width from an argument.  */
  1850.         specs[nspecs_done].info.width =
  1851.           args_value[specs[nspecs_done].width_arg].pa_int;
  1852.  
  1853.         if (specs[nspecs_done].info.width < 0)
  1854.           /* If the width value is negative left justification is
  1855.          selected and the value is taken as being positive.  */
  1856.           {
  1857.         specs[nspecs_done].info.width *= -1;
  1858.         left = specs[nspecs_done].info.left = 1;
  1859.           }
  1860.         width = specs[nspecs_done].info.width;
  1861.       }
  1862.  
  1863.     if (specs[nspecs_done].prec_arg != -1)
  1864.       {
  1865.         /* Extract the precision from an argument.  */
  1866.         specs[nspecs_done].info.prec =
  1867.           args_value[specs[nspecs_done].prec_arg].pa_int;
  1868.  
  1869.         if (specs[nspecs_done].info.prec < 0)
  1870.           /* If the precision is negative the precision is
  1871.          omitted.  */
  1872.           specs[nspecs_done].info.prec = -1;
  1873.  
  1874.         prec = specs[nspecs_done].info.prec;
  1875.       }
  1876.  
  1877.     /* Maybe the buffer is too small.  */
  1878.     if (MAX (prec, width) + 32 > (int) (sizeof (work_buffer)
  1879.                         / sizeof (CHAR_T)))
  1880.       {
  1881.         if (__libc_use_alloca ((MAX (prec, width) + 32)
  1882.                    * sizeof (CHAR_T)))
  1883.           workend = ((CHAR_T *) alloca ((MAX (prec, width) + 32)
  1884.                         * sizeof (CHAR_T))
  1885.              + (MAX (prec, width) + 32));
  1886.         else
  1887.           {
  1888.         workstart = (CHAR_T *) malloc ((MAX (prec, width) + 32)
  1889.                            * sizeof (CHAR_T));
  1890.         workend = workstart + (MAX (prec, width) + 32);
  1891.           }
  1892.       }
  1893.  
  1894.     /* Process format specifiers.  */
  1895.     while (1)
  1896.       {
  1897.         extern printf_function **__printf_function_table;
  1898.         int function_done;
  1899.  
  1900.         if (spec <= UCHAR_MAX
  1901.         && __printf_function_table != NULL
  1902.         && __printf_function_table[(size_t) spec] != NULL)
  1903.           {
  1904.         const void **ptr = alloca (specs[nspecs_done].ndata_args
  1905.                        * sizeof (const void *));
  1906.  
  1907.         /* Fill in an array of pointers to the argument values.  */
  1908.         for (unsigned int i = 0; i < specs[nspecs_done].ndata_args;
  1909.              ++i)
  1910.           ptr[i] = &args_value[specs[nspecs_done].data_arg + i];
  1911.  
  1912.         /* Call the function.  */
  1913.         function_done = __printf_function_table[(size_t) spec]
  1914.           (s, &specs[nspecs_done].info, ptr);
  1915.  
  1916.         if (function_done != -2)
  1917.           {
  1918.             /* If an error occurred we don't have information
  1919.                about # of chars.  */
  1920.             if (function_done < 0)
  1921.               {
  1922.             done = -1;
  1923.             goto all_done;
  1924.               }
  1925.  
  1926.             done_add (function_done);
  1927.             break;
  1928.           }
  1929.           }
  1930.  
  1931.         JUMP (spec, step4_jumps);
  1932.  
  1933.         process_arg ((&specs[nspecs_done]));
  1934.         process_string_arg ((&specs[nspecs_done]));
  1935.  
  1936.       LABEL (form_unknown):
  1937.         {
  1938.           unsigned int i;
  1939.           const void **ptr;
  1940.  
  1941.           ptr = alloca (specs[nspecs_done].ndata_args
  1942.                 * sizeof (const void *));
  1943.  
  1944.           /* Fill in an array of pointers to the argument values.  */
  1945.           for (i = 0; i < specs[nspecs_done].ndata_args; ++i)
  1946.         ptr[i] = &args_value[specs[nspecs_done].data_arg + i];
  1947.  
  1948.           /* Call the function.  */
  1949.           function_done = printf_unknown (s, &specs[nspecs_done].info,
  1950.                           ptr);
  1951.  
  1952.           /* If an error occurred we don't have information about #
  1953.          of chars.  */
  1954.           if (function_done < 0)
  1955.         {
  1956.           done = -1;
  1957.           goto all_done;
  1958.         }
  1959.  
  1960.           done_add (function_done);
  1961.         }
  1962.         break;
  1963.       }
  1964.  
  1965.     free (workstart);
  1966.     workstart = NULL;
  1967.  
  1968.     /* Write the following constant string.  */
  1969.     outstring (specs[nspecs_done].end_of_fmt,
  1970.            specs[nspecs_done].next_fmt
  1971.            - specs[nspecs_done].end_of_fmt);
  1972.       }
  1973.   }
  1974.  
  1975. all_done:
  1976.   if (__builtin_expect (workstart != NULL, 0))
  1977.     free (workstart);
  1978.   /* Unlock the stream.  */
  1979.   _IO_funlockfile (s);
  1980.   _IO_cleanup_region_end (0);
  1981.  
  1982.   return done;
  1983. }
  1984. /* Handle an unknown format specifier.  This prints out a canonicalized
  1985.    representation of the format spec itself.  */
  1986. static int
  1987. printf_unknown (FILE *s, const struct printf_info *info,
  1988.         const void *const *args)
  1989.  
  1990. {
  1991.   int done = 0;
  1992.   CHAR_T work_buffer[MAX (sizeof (info->width), sizeof (info->prec)) * 3];
  1993.   CHAR_T *const workend
  1994.     = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)];
  1995.   register CHAR_T *w;
  1996.  
  1997.   outchar (L_('%'));
  1998.  
  1999.   if (info->alt)
  2000.     outchar (L_('#'));
  2001.   if (info->group)
  2002.     outchar (L_('\''));
  2003.   if (info->showsign)
  2004.     outchar (L_('+'));
  2005.   else if (info->space)
  2006.     outchar (L_(' '));
  2007.   if (info->left)
  2008.     outchar (L_('-'));
  2009.   if (info->pad == L_('0'))
  2010.     outchar (L_('0'));
  2011.   if (info->i18n)
  2012.     outchar (L_('I'));
  2013.  
  2014.   if (info->width != 0)
  2015.     {
  2016.       w = _itoa_word (info->width, workend, 10, 0);
  2017.       while (w < workend)
  2018.     outchar (*w++);
  2019.     }
  2020.  
  2021.   if (info->prec != -1)
  2022.     {
  2023.       outchar (L_('.'));
  2024.       w = _itoa_word (info->prec, workend, 10, 0);
  2025.       while (w < workend)
  2026.     outchar (*w++);
  2027.     }
  2028.  
  2029.   if (info->spec != L_('\0'))
  2030.     outchar (info->spec);
  2031.  
  2032.  all_done:
  2033.   return done;
  2034. }
  2035. /* Group the digits according to the grouping rules of the current locale.
  2036.    The interpretation of GROUPING is as in `struct lconv' from <locale.h>.  */
  2037. static CHAR_T *
  2038. internal_function
  2039. group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping,
  2040. #ifdef COMPILE_WPRINTF
  2041.           wchar_t thousands_sep
  2042. #else
  2043.           const char *thousands_sep
  2044. #endif
  2045.           )
  2046. {
  2047.   int len;
  2048.   CHAR_T *src, *s;
  2049. #ifndef COMPILE_WPRINTF
  2050.   int tlen = strlen (thousands_sep);
  2051. #endif
  2052.  
  2053.   /* We treat all negative values like CHAR_MAX.  */
  2054.  
  2055.   if (*grouping == CHAR_MAX || *grouping <= 0)
  2056.     /* No grouping should be done.  */
  2057.     return w;
  2058.  
  2059.   len = *grouping++;
  2060.  
  2061.   /* Copy existing string so that nothing gets overwritten.  */
  2062.   src = (CHAR_T *) alloca ((rear_ptr - w) * sizeof (CHAR_T));
  2063.   s = (CHAR_T *) __mempcpy (src, w,
  2064.                 (rear_ptr - w) * sizeof (CHAR_T));
  2065.   w = rear_ptr;
  2066.  
  2067.   /* Process all characters in the string.  */
  2068.   while (s > src)
  2069.     {
  2070.       *--w = *--s;
  2071.  
  2072.       if (--len == 0 && s > src)
  2073.     {
  2074.       /* A new group begins.  */
  2075. #ifdef COMPILE_WPRINTF
  2076.       *--w = thousands_sep;
  2077. #else
  2078.       int cnt = tlen;
  2079.       do
  2080.         *--w = thousands_sep[--cnt];
  2081.       while (cnt > 0);
  2082. #endif
  2083.  
  2084.       if (*grouping == CHAR_MAX
  2085. #if CHAR_MIN < 0
  2086.            || *grouping < 0
  2087. #endif
  2088.            )
  2089.         {
  2090.           /* No further grouping to be done.
  2091.          Copy the rest of the number.  */
  2092.           do
  2093.         *--w = *--s;
  2094.           while (s > src);
  2095.           break;
  2096.         }
  2097.       else if (*grouping != '\0')
  2098.         /* The previous grouping repeats ad infinitum.  */
  2099.         len = *grouping++;
  2100.       else
  2101.         len = grouping[-1];
  2102.     }
  2103.     }
  2104.   return w;
  2105. }
  2106. /* Helper "class" for `fprintf to unbuffered': creates a temporary buffer.  */
  2107. struct helper_file
  2108.   {
  2109.     struct _IO_FILE_plus _f;
  2110. #ifdef COMPILE_WPRINTF
  2111.     struct _IO_wide_data _wide_data;
  2112. #endif
  2113.     _IO_FILE *_put_stream;
  2114. #ifdef _IO_MTSAFE_IO
  2115.     _IO_lock_t lock;
  2116. #endif
  2117.   };
  2118.  
  2119. static int
  2120. _IO_helper_overflow (_IO_FILE *s, int c)
  2121. {
  2122.   _IO_FILE *target = ((struct helper_file*) s)->_put_stream;
  2123. #ifdef COMPILE_WPRINTF
  2124.   int used = s->_wide_data->_IO_write_ptr - s->_wide_data->_IO_write_base;
  2125.   if (used)
  2126.     {
  2127.       _IO_size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base,
  2128.                       used);
  2129.       if (written == 0 || written == WEOF)
  2130.     return WEOF;
  2131.       __wmemmove (s->_wide_data->_IO_write_base,
  2132.           s->_wide_data->_IO_write_base + written,
  2133.           used - written);
  2134.       s->_wide_data->_IO_write_ptr -= written;
  2135.     }
  2136. #else
  2137.   int used = s->_IO_write_ptr - s->_IO_write_base;
  2138.   if (used)
  2139.     {
  2140.       _IO_size_t written = _IO_sputn (target, s->_IO_write_base, used);
  2141.       if (written == 0 || written == EOF)
  2142.     return EOF;
  2143.       memmove (s->_IO_write_base, s->_IO_write_base + written,
  2144.            used - written);
  2145.       s->_IO_write_ptr -= written;
  2146.     }
  2147. #endif
  2148.   return PUTC (c, s);
  2149. }
  2150.  
  2151. #ifdef COMPILE_WPRINTF
  2152. static const struct _IO_jump_t _IO_helper_jumps =
  2153. {
  2154.   JUMP_INIT_DUMMY,
  2155.   JUMP_INIT (finish, INTUSE(_IO_wdefault_finish)),
  2156.   JUMP_INIT (overflow, _IO_helper_overflow),
  2157.   JUMP_INIT (underflow, _IO_default_underflow),
  2158.   JUMP_INIT (uflow, INTUSE(_IO_default_uflow)),
  2159.   JUMP_INIT (pbackfail, (_IO_pbackfail_t) INTUSE(_IO_wdefault_pbackfail)),
  2160.   JUMP_INIT (xsputn, INTUSE(_IO_wdefault_xsputn)),
  2161.   JUMP_INIT (xsgetn, INTUSE(_IO_wdefault_xsgetn)),
  2162.   JUMP_INIT (seekoff, _IO_default_seekoff),
  2163.   JUMP_INIT (seekpos, _IO_default_seekpos),
  2164.   JUMP_INIT (setbuf, _IO_default_setbuf),
  2165.   JUMP_INIT (sync, _IO_default_sync),
  2166.   JUMP_INIT (doallocate, INTUSE(_IO_wdefault_doallocate)),
  2167.   JUMP_INIT (read, _IO_default_read),
  2168.   JUMP_INIT (write, _IO_default_write),
  2169.   JUMP_INIT (seek, _IO_default_seek),
  2170.   JUMP_INIT (close, _IO_default_close),
  2171.   JUMP_INIT (stat, _IO_default_stat)
  2172. };
  2173. #else
  2174. static const struct _IO_jump_t _IO_helper_jumps =
  2175. {
  2176.   JUMP_INIT_DUMMY,
  2177.   JUMP_INIT (finish, INTUSE(_IO_default_finish)),
  2178.   JUMP_INIT (overflow, _IO_helper_overflow),
  2179.   JUMP_INIT (underflow, _IO_default_underflow),
  2180.   JUMP_INIT (uflow, INTUSE(_IO_default_uflow)),
  2181.   JUMP_INIT (pbackfail, INTUSE(_IO_default_pbackfail)),
  2182.   JUMP_INIT (xsputn, INTUSE(_IO_default_xsputn)),
  2183.   JUMP_INIT (xsgetn, INTUSE(_IO_default_xsgetn)),
  2184.   JUMP_INIT (seekoff, _IO_default_seekoff),
  2185.   JUMP_INIT (seekpos, _IO_default_seekpos),
  2186.   JUMP_INIT (setbuf, _IO_default_setbuf),
  2187.   JUMP_INIT (sync, _IO_default_sync),
  2188.   JUMP_INIT (doallocate, INTUSE(_IO_default_doallocate)),
  2189.   JUMP_INIT (read, _IO_default_read),
  2190.   JUMP_INIT (write, _IO_default_write),
  2191.   JUMP_INIT (seek, _IO_default_seek),
  2192.   JUMP_INIT (close, _IO_default_close),
  2193.   JUMP_INIT (stat, _IO_default_stat)
  2194. };
  2195. #endif
  2196.  
  2197. static int
  2198. internal_function
  2199. buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format,
  2200.            _IO_va_list args)
  2201. {
  2202.   CHAR_T buf[_IO_BUFSIZ];
  2203.   struct helper_file helper;
  2204.   register _IO_FILE *hp = (_IO_FILE *) &helper._f;
  2205.   int result, to_flush;
  2206.  
  2207.   /* Orient the stream.  */
  2208. #ifdef ORIENT
  2209.   ORIENT;
  2210. #endif
  2211.  
  2212.   /* Initialize helper.  */
  2213.   helper._put_stream = s;
  2214. #ifdef COMPILE_WPRINTF
  2215.   hp->_wide_data = &helper._wide_data;
  2216.   _IO_wsetp (hp, buf, buf + sizeof buf / sizeof (CHAR_T));
  2217.   hp->_mode = 1;
  2218. #else
  2219.   _IO_setp (hp, buf, buf + sizeof buf);
  2220.   hp->_mode = -1;
  2221. #endif
  2222.   hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS|_IO_USER_LOCK;
  2223. #if _IO_JUMPS_OFFSET
  2224.   hp->_vtable_offset = 0;
  2225. #endif
  2226. #ifdef _IO_MTSAFE_IO
  2227.   hp->_lock = NULL;
  2228. #endif
  2229.   hp->_flags2 = s->_flags2;
  2230.   _IO_JUMPS (&helper._f) = (struct _IO_jump_t *) &_IO_helper_jumps;
  2231.  
  2232.   /* Now print to helper instead.  */
  2233. #ifndef COMPILE_WPRINTF
  2234.   result = INTUSE(_IO_vfprintf) (hp, format, args);
  2235. #else
  2236.   result = vfprintf (hp, format, args);
  2237. #endif
  2238.  
  2239.   /* Lock stream.  */
  2240.   __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, s);
  2241.   _IO_flockfile (s);
  2242.  
  2243.   /* Now flush anything from the helper to the S. */
  2244. #ifdef COMPILE_WPRINTF
  2245.   if ((to_flush = (hp->_wide_data->_IO_write_ptr
  2246.            - hp->_wide_data->_IO_write_base)) > 0)
  2247.     {
  2248.       if ((int) _IO_sputn (s, hp->_wide_data->_IO_write_base, to_flush)
  2249.       != to_flush)
  2250.     result = -1;
  2251.     }
  2252. #else
  2253.   if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0)
  2254.     {
  2255.       if ((int) _IO_sputn (s, hp->_IO_write_base, to_flush) != to_flush)
  2256.     result = -1;
  2257.     }
  2258. #endif
  2259.  
  2260.   /* Unlock the stream.  */
  2261.   _IO_funlockfile (s);
  2262.   __libc_cleanup_region_end (0);
  2263.  
  2264.   return result;
  2265. }
  2266.  
  2267. #undef vfprintf
  2268. #ifdef COMPILE_WPRINTF
  2269. strong_alias (_IO_vfwprintf, __vfwprintf);
  2270. ldbl_weak_alias (_IO_vfwprintf, vfwprintf);
  2271. #else
  2272. ldbl_strong_alias (_IO_vfprintf_internal, vfprintf);
  2273. ldbl_hidden_def (_IO_vfprintf_internal, vfprintf)
  2274. ldbl_strong_alias (_IO_vfprintf_internal, _IO_vfprintf);
  2275. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement