08a488ce810576fdf76896d71676debb44d3b53c
[platform/upstream/glibc.git] / stdio-common / vfprintf.c
1 /* Copyright (C) 1991, 1992, 1993, 1994, 1995 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 Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 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 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB.  If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA.  */
18
19 #include <ctype.h>
20 #include <errno.h>
21 #include <float.h>
22 #include <limits.h>
23 #include <math.h>
24 #include <printf.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <printf.h>
29 #include <stddef.h>
30 #include "_itoa.h"
31 #include "../locale/localeinfo.h"
32
33 /* Include the shared code for parsing the format string.  */
34 #include "printf-parse.h"
35
36
37 /* This function from the GNU C library is also used in libio.
38    To compile for use in libio, compile with -DUSE_IN_LIBIO.  */
39
40 #ifdef USE_IN_LIBIO
41 /* This code is for use in libio.  */
42 #include <libioP.h>
43 #define PUT(f, s, n)    _IO_sputn (f, s, n)
44 #define PAD(padchar)                                                          \
45   if (specs[cnt].info.width > 0)                                              \
46     done += _IO_padn (s, padchar, specs[cnt].info.width)
47 #define PUTC(c, f)      _IO_putc (c, f)
48 #define vfprintf        _IO_vfprintf
49 #define size_t          _IO_size_t
50 #define FILE            _IO_FILE
51 #define va_list         _IO_va_list
52 #undef  BUFSIZ
53 #define BUFSIZ          _IO_BUFSIZ
54 #define ARGCHECK(s, format)                                                   \
55   do                                                                          \
56     {                                                                         \
57       /* Check file argument for consistence.  */                             \
58       CHECK_FILE (s, -1);                                                     \
59       if (s->_flags & _IO_NO_WRITES || format == NULL)                        \
60         {                                                                     \
61           MAYBE_SET_EINVAL;                                                   \
62           return -1;                                                          \
63         }                                                                     \
64     } while (0)
65 #define UNBUFFERED_P(s) ((s)->_IO_file_flags & _IO_UNBUFFERED)
66 #else /* ! USE_IN_LIBIO */
67 /* This code is for use in the GNU C library.  */
68 #include <stdio.h>
69 #define PUTC(c, f)      putc (c, f)
70 #define PUT(f, s, n)    fwrite (s, 1, n, f)
71 ssize_t __printf_pad __P ((FILE *, char pad, size_t n));
72 #define PAD(padchar)                                                          \
73   if (specs[cnt].info.width > 0)                                              \
74     { if (__printf_pad (s, padchar, specs[cnt].info.width) == -1)             \
75         return -1; else done += specs[cnt].info.width; }
76 #define ARGCHECK(s, format) \
77   do                                                                          \
78     {                                                                         \
79       /* Check file argument for consistence.  */                             \
80       if (!__validfp(s) || !s->__mode.__write || format == NULL)              \
81         {                                                                     \
82           errno = EINVAL;                                                     \
83           return -1;                                                          \
84         }                                                                     \
85       if (!s->__seen)                                                         \
86         {                                                                     \
87           if (__flshfp (s, EOF) == EOF)                                       \
88             return -1;                                                        \
89         }                                                                     \
90     } while (0)
91 #define UNBUFFERED_P(s) ((s)->__buffer == NULL)
92 #endif /* USE_IN_LIBIO */
93
94
95 #define outchar(x)                                                            \
96   do                                                                          \
97     {                                                                         \
98       register const int outc = (x);                                          \
99       if (PUTC (outc, s) == EOF)                                              \
100         return -1;                                                            \
101       else                                                                    \
102         ++done;                                                               \
103     } while (0)
104
105 #define outstring(string, len)                                                \
106   do                                                                          \
107     {                                                                         \
108       if (len > 20)                                                           \
109         {                                                                     \
110           if (PUT (s, string, len) != len)                                    \
111             return -1;                                                        \
112           done += len;                                                        \
113         }                                                                     \
114       else                                                                    \
115         {                                                                     \
116           register const char *cp = string;                                   \
117           register int l = len;                                               \
118           while (l-- > 0)                                                     \
119             outchar (*cp++);                                                  \
120         }                                                                     \
121     } while (0)
122
123 /* Helper function to provide temporary buffering for unbuffered streams.  */
124 static int buffered_vfprintf __P ((FILE *stream, const char *fmt, va_list));
125
126 static printf_function printf_unknown;
127
128 extern printf_function **__printf_function_table;
129
130 static char *group_number __P ((char *, char *, const char *, wchar_t));
131
132
133 int
134 vfprintf (s, format, ap)
135     register FILE *s;
136     const char *format;
137     va_list ap;
138 {
139   /* The character used as thousands separator.  */
140   wchar_t thousands_sep;
141
142   /* The string describing the size of groups of digits.  */
143   const char *grouping;
144
145   /* Array with information about the needed arguments.  This has to be
146      dynamically extendable.  */
147   size_t nspecs;
148   size_t nspecs_max;
149   struct printf_spec *specs;
150
151   /* The number of arguments the format string requests.  This will
152      determine the size of the array needed to store the argument
153      attributes.  */
154   size_t nargs;
155   int *args_type;
156   union printf_arg *args_value;
157
158   /* Positional parameters refer to arguments directly.  This could also
159      determine the maximum number of arguments.  Track the maximum number.  */
160   size_t max_ref_arg;
161
162   /* End of leading constant string.  */
163   const char *lead_str_end;
164
165   /* Number of characters written.  */
166   register size_t done = 0;
167
168   /* Running pointer through format string.  */
169   const char *f;
170
171   /* Just a counter.  */
172   int cnt;
173
174   ARGCHECK (s, format);
175
176   if (UNBUFFERED_P (s))
177     /* Use a helper function which will allocate a local temporary buffer
178        for the stream and then call us again.  */
179     return buffered_vfprintf (s, format, ap);
180
181   /* Reset multibyte characters to their initial state.  */
182   (void) mblen ((char *) NULL, 0);
183
184   /* Figure out the thousands separator character.  */
185   if (mbtowc (&thousands_sep, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
186               strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
187     thousands_sep = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
188   grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
189   if (*grouping == '\0' || *grouping == CHAR_MAX || thousands_sep == L'\0')
190     grouping = NULL;
191
192   nspecs_max = 32;              /* A more or less arbitrary start value.  */
193   specs = alloca (nspecs_max * sizeof (struct printf_spec));
194   nspecs = 0;
195   nargs = 0;
196   max_ref_arg = 0;
197
198   /* Find the first format specifier.  */
199   lead_str_end = find_spec (format);
200
201   for (f = lead_str_end; *f != '\0'; f = specs[nspecs++].next_fmt)
202     {
203       if (nspecs >= nspecs_max)
204         {
205           /* Extend the array of format specifiers.  */
206           struct printf_spec *old = specs;
207
208           nspecs_max *= 2;
209           specs = alloca (nspecs_max * sizeof (struct printf_spec));
210           if (specs == &old[nspecs])
211             /* Stack grows up, OLD was the last thing allocated; extend it.  */
212             nspecs_max += nspecs_max / 2;
213           else
214             {
215               /* Copy the old array's elements to the new space.  */
216               memcpy (specs, old, nspecs * sizeof (struct printf_spec));
217               if (old == &specs[nspecs])
218                 /* Stack grows down, OLD was just below the new SPECS.
219                    We can use that space when the new space runs out.  */
220                 nspecs_max += nspecs_max / 2;
221             }
222         }
223
224       /* Parse the format specifier.  */
225       nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg);
226     }
227
228   /* Determine the number of arguments the format string consumes.  */
229   nargs = MAX (nargs, max_ref_arg);
230
231   /* Allocate memory for the argument descriptions.  */
232   args_type = alloca (nargs * sizeof (int));
233   memset (args_type, 0, nargs * sizeof (int));
234   args_value = alloca (nargs * sizeof (union printf_arg));
235
236   /* XXX Could do sanity check here: If any element in ARGS_TYPE is
237      still zero after this loop, format is invalid.  For now we simply
238      use 0 as the value.  */
239
240   /* Fill in the types of all the arguments.  */
241   for (cnt = 0; cnt < nspecs; ++cnt)
242     {
243       /* If the width is determined by an argument this is an int.  */
244       if (specs[cnt].width_arg != -1)
245         args_type[specs[cnt].width_arg] = PA_INT;
246
247       /* If the precision is determined by an argument this is an int.  */
248       if (specs[cnt].prec_arg != -1)
249         args_type[specs[cnt].prec_arg] = PA_INT;
250
251       switch (specs[cnt].ndata_args)
252         {
253         case 0:                 /* No arguments.  */
254           break;
255         case 1:                 /* One argument; we already have the type.  */
256           args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type;
257           break;
258         default:
259           /* We have more than one argument for this format spec.  We must
260              call the arginfo function again to determine all the types.  */
261           (void) (*__printf_arginfo_table[specs[cnt].info.spec])
262             (&specs[cnt].info,
263              specs[cnt].ndata_args, &args_type[specs[cnt].data_arg]);
264           break;
265         }
266     }
267
268   /* Now we know all the types and the order.  Fill in the argument values.  */
269   for (cnt = 0; cnt < nargs; ++cnt)
270     switch (args_type[cnt])
271       {
272 #define T(tag, mem, type)                                                     \
273       case tag:                                                               \
274         args_value[cnt].mem = va_arg (ap, type);                              \
275         break
276
277         T (PA_CHAR, pa_char, int); /* Promoted.  */
278         T (PA_INT|PA_FLAG_SHORT, pa_short_int, int); /* Promoted.  */
279         T (PA_INT, pa_int, int);
280         T (PA_INT|PA_FLAG_LONG, pa_long_int, long int);
281         T (PA_INT|PA_FLAG_LONG_LONG, pa_long_long_int, long long int);
282         T (PA_FLOAT, pa_float, double); /* Promoted.  */
283         T (PA_DOUBLE, pa_double, double);
284         T (PA_DOUBLE|PA_FLAG_LONG_DOUBLE, pa_long_double, long double);
285         T (PA_STRING, pa_string, const char *);
286         T (PA_POINTER, pa_pointer, void *);
287 #undef T
288       default:
289         if ((args_type[cnt] & PA_FLAG_PTR) != 0)
290           args_value[cnt].pa_pointer = va_arg (ap, void *);
291         else
292           args_value[cnt].pa_long_double = 0.0;
293         break;
294       }
295
296   /* Write the literal text before the first format.  */
297   outstring (format, lead_str_end - format);
298
299   /* Now walk through all format specifiers and process them.  */
300   for (cnt = 0; cnt < nspecs; ++cnt)
301     {
302       printf_function *function; /* Auxiliary function to do output.  */
303       int is_neg;               /* Decimal integer is negative.  */
304       int base;                 /* Base of a number to be written.  */
305       unsigned long long int num; /* Integral number to be written.  */
306       const char *str;          /* String to be written.  */
307       char errorbuf[1024];      /* Buffer sometimes used by %m.  */
308
309       if (specs[cnt].width_arg != -1)
310         {
311           /* Extract the field width from an argument.  */
312           specs[cnt].info.width = args_value[specs[cnt].width_arg].pa_int;
313
314           if (specs[cnt].info.width < 0)
315             /* If the width value is negative left justification is selected
316                and the value is taken as being positive.  */
317             {
318               specs[cnt].info.width = -specs[cnt].info.width;
319               specs[cnt].info.left = 1;
320             }
321         }
322
323       if (specs[cnt].prec_arg != -1)
324         {
325           /* Extract the precision from an argument.  */
326           specs[cnt].info.prec = args_value[specs[cnt].prec_arg].pa_int;
327
328           if (specs[cnt].info.prec < 0)
329             /* If the precision is negative the precision is omitted.  */
330             specs[cnt].info.prec = -1;
331         }
332
333       /* Check for a user-defined handler for this spec.  */
334       function = (__printf_function_table == NULL ? NULL :
335                   __printf_function_table[specs[cnt].info.spec]);
336
337       if (function != NULL)
338       use_function:             /* Built-in formats with helpers use this.  */
339         {
340           int function_done;
341           unsigned int i;
342           const void *ptr[specs[cnt].ndata_args];
343
344           /* Fill in an array of pointers to the argument values.  */
345           for (i = 0; i < specs[cnt].ndata_args; ++i)
346             ptr[i] = &args_value[specs[cnt].data_arg + i];
347
348           /* Call the function.  */
349           function_done = (*function) (s, &specs[cnt].info, ptr);
350
351           /* If an error occured don't do any further work.  */
352           if (function_done < 0)
353             return -1;
354
355           done += function_done;
356         }
357       else
358         switch (specs[cnt].info.spec)
359           {
360           case '%':
361             /* Write a literal "%".  */
362             outchar ('%');
363             break;
364           case 'i':
365           case 'd':
366             {
367               long long int signed_num;
368
369               /* Decimal integer.  */
370               base = 10;
371               if (specs[cnt].info.is_longlong)
372                 signed_num = args_value[specs[cnt].data_arg].pa_long_long_int;
373               else if (specs[cnt].info.is_long)
374                 signed_num = args_value[specs[cnt].data_arg].pa_long_int;
375               else if (!specs[cnt].info.is_short)
376                 signed_num = args_value[specs[cnt].data_arg].pa_int;
377               else
378                 signed_num = args_value[specs[cnt].data_arg].pa_short_int;
379
380               is_neg = signed_num < 0;
381               num = is_neg ? (- signed_num) : signed_num;
382               goto number;
383             }
384
385           case 'u':
386             /* Decimal unsigned integer.  */
387             base = 10;
388             goto unsigned_number;
389
390           case 'o':
391             /* Octal unsigned integer.  */
392             base = 8;
393             goto unsigned_number;
394
395           case 'X':
396             /* Hexadecimal unsigned integer.  */
397           case 'x':
398             /* Hex with lower-case digits.  */
399             base = 16;
400
401           unsigned_number:
402             /* Unsigned number of base BASE.  */
403
404             if (specs[cnt].info.is_longlong)
405               num = args_value[specs[cnt].data_arg].pa_u_long_long_int;
406             else if (specs[cnt].info.is_long)
407               num = args_value[specs[cnt].data_arg].pa_u_long_int;
408             else if (!specs[cnt].info.is_short)
409               num = args_value[specs[cnt].data_arg].pa_u_int;
410             else
411               num = args_value[specs[cnt].data_arg].pa_u_short_int;
412
413             /* ANSI only specifies the `+' and
414                ` ' flags for signed conversions.  */
415             is_neg = 0;
416             specs[cnt].info.showsign = 0;
417             specs[cnt].info.space = 0;
418
419           number:
420             /* Number of base BASE.  */
421             {
422               char work[BUFSIZ];
423               char *const workend = &work[sizeof(work) - 1];
424               register char *w;
425
426               if (specs[cnt].info.prec == -1)
427                   /* Supply a default precision if none was given.  */
428                   specs[cnt].info.prec = 1;
429               else
430                 /* We have to take care for the '0' flag.  If a
431                    precision is given it must be ignored.  */
432                 specs[cnt].info.pad = ' ';
433
434               /* If the precision is 0 and the number is 0 nothing has
435                  to be written for the number.  */
436               if (specs[cnt].info.prec == 0 && num == 0)
437                 w = workend;
438               else
439                 {
440                   /* Put the number in WORK.  */
441                   w = _itoa (num, workend + 1, base,
442                              specs[cnt].info.spec == 'X');
443                   w -= 1;
444                   if (specs[cnt].info.group && grouping)
445                     w = group_number (w, workend, grouping, thousands_sep);
446                 }
447               specs[cnt].info.width -= workend - w;
448               specs[cnt].info.prec -= workend - w;
449
450               if (num != 0 && specs[cnt].info.alt && base == 8
451                   && specs[cnt].info.prec <= 0)
452                 {
453                   /* Add octal marker.  */
454                   *w-- = '0';
455                   --specs[cnt].info.width;
456                 }
457
458               if (specs[cnt].info.prec > 0)
459                 {
460                   /* Add zeros to the precision.  */
461                   specs[cnt].info.width -= specs[cnt].info.prec;
462                   while (specs[cnt].info.prec-- > 0)
463                     *w-- = '0';
464                 }
465
466               if (num != 0 && specs[cnt].info.alt && base == 16)
467                 /* Account for 0X hex marker.  */
468                 specs[cnt].info.width -= 2;
469
470               if (is_neg || specs[cnt].info.showsign || specs[cnt].info.space)
471                 --specs[cnt].info.width;
472
473               if (!specs[cnt].info.left && specs[cnt].info.pad == ' ')
474                 PAD (' ');
475
476               if (is_neg)
477                 outchar ('-');
478               else if (specs[cnt].info.showsign)
479                 outchar ('+');
480               else if (specs[cnt].info.space)
481                 outchar (' ');
482
483               if (num != 0 && specs[cnt].info.alt && base == 16)
484                 {
485                   outchar ('0');
486                   outchar (specs[cnt].info.spec);
487                 }
488
489               if (!specs[cnt].info.left && specs[cnt].info.pad == '0')
490                 PAD ('0');
491
492               /* Write the number.  */
493               while (++w <= workend)
494                 outchar (*w);
495
496               if (specs[cnt].info.left)
497                 PAD (' ');
498             }
499             break;
500
501           case 'e':
502           case 'E':
503           case 'f':
504           case 'g':
505           case 'G':
506             {
507               /* Floating-point number.  This is handled by printf_fp.c.  */
508               extern printf_function __printf_fp;
509               function = __printf_fp;
510               goto use_function;
511             }
512
513           case 'c':
514             /* Character.  */
515             --specs[cnt].info.width;/* Account for the character itself.  */
516             if (!specs[cnt].info.left)
517               PAD (' ');
518             outchar ((unsigned char) args_value[specs[cnt].data_arg].pa_char);
519             if (specs[cnt].info.left)
520               PAD (' ');
521             break;
522
523           case 's':
524             {
525               static const char null[] = "(null)";
526               size_t len;
527
528               str = args_value[specs[cnt].data_arg].pa_string;
529
530             string:
531
532               if (str == NULL)
533                 {
534                   /* Write "(null)" if there's space.  */
535                   if (specs[cnt].info.prec == -1
536                       || specs[cnt].info.prec >= (int) sizeof (null) - 1)
537                     {
538                       str = null;
539                       len = sizeof (null) - 1;
540                     }
541                   else
542                     {
543                       str = "";
544                       len = 0;
545                     }
546                 }
547               else if (specs[cnt].info.prec != -1)
548                 {
549                   /* Search for the end of the string, but don't search
550                      past the length specified by the precision.  */
551                   const char *end = memchr (str, '\0', specs[cnt].info.prec);
552                   if (end)
553                     len = end - str;
554                   else
555                     len = specs[cnt].info.prec;
556                 }
557               else
558                 len = strlen (str);
559
560               specs[cnt].info.width -= len;
561
562               if (!specs[cnt].info.left)
563                 PAD (' ');
564               outstring (str, len);
565               if (specs[cnt].info.left)
566                 PAD (' ');
567             }
568             break;
569
570           case 'p':
571             /* Generic pointer.  */
572             {
573               const void *ptr;
574               ptr = args_value[specs[cnt].data_arg].pa_pointer;
575               if (ptr != NULL)
576                 {
577                   /* If the pointer is not NULL, write it as a %#x spec.  */
578                   base = 16;
579                   num = (unsigned long long int) (unsigned long int) ptr;
580                   is_neg = 0;
581                   specs[cnt].info.alt = 1;
582                   specs[cnt].info.spec = 'x';
583                   specs[cnt].info.group = 0;
584                   goto number;
585                 }
586               else
587                 {
588                   /* Write "(nil)" for a nil pointer.  */
589                   str = "(nil)";
590                   /* Make sure the full string "(nil)" is printed.  */
591                   if (specs[cnt].info.prec < 5)
592                     specs[cnt].info.prec = 5;
593                   goto string;
594                 }
595             }
596             break;
597
598           case 'n':
599             /* Answer the count of characters written.  */
600             if (specs[cnt].info.is_longlong)
601               *(long long int *)
602                 args_value[specs[cnt].data_arg].pa_pointer = done;
603             else if (specs[cnt].info.is_long)
604               *(long int *)
605                 args_value[specs[cnt].data_arg].pa_pointer = done;
606             else if (!specs[cnt].info.is_short)
607               *(int *)
608                 args_value[specs[cnt].data_arg].pa_pointer = done;
609             else
610               *(short int *)
611                 args_value[specs[cnt].data_arg].pa_pointer = done;
612             break;
613
614           case 'm':
615             {
616               extern char *_strerror_internal __P ((int, char *buf, size_t));
617               str = _strerror_internal (errno, errorbuf, sizeof errorbuf);
618               goto string;
619             }
620
621           default:
622             /* Unrecognized format specifier.  */
623             function = printf_unknown;
624             goto use_function;
625           }
626
627       /* Write the following constant string.  */
628       outstring (specs[cnt].end_of_fmt,
629                  specs[cnt].next_fmt - specs[cnt].end_of_fmt);
630     }
631
632   return done;
633 }
634
635 #ifdef USE_IN_LIBIO
636 # undef vfprintf
637 # ifdef strong_alias
638 /* This is for glibc.  */
639 strong_alias (_IO_vfprintf, vfprintf)
640 # else
641 #  if defined __ELF__ || defined __GNU_LIBRARY__
642 #   include <gnu-stabs.h>
643 #   ifdef weak_alias
644 weak_alias (_IO_vfprintf, vfprintf);
645 #   endif
646 #  endif
647 # endif
648 #endif
649
650
651 /* Handle an unknown format specifier.  This prints out a canonicalized
652    representation of the format spec itself.  */
653
654 static int
655 printf_unknown (s, info, args)
656   FILE *s;
657   const struct printf_info *info;
658   const void **const args;
659 {
660   int done = 0;
661   char work[BUFSIZ];
662   char *const workend = &work[sizeof(work) - 1];
663   register char *w;
664
665   outchar ('%');
666
667   if (info->alt)
668     outchar ('#');
669   if (info->group)
670     outchar ('\'');
671   if (info->showsign)
672     outchar ('+');
673   else if (info->space)
674     outchar (' ');
675   if (info->left)
676     outchar ('-');
677   if (info->pad == '0')
678     outchar ('0');
679
680   if (info->width != 0)
681     {
682       w = _itoa (info->width, workend + 1, 10, 0);
683       while (++w <= workend)
684         outchar (*w);
685     }
686
687   if (info->prec != -1)
688     {
689       outchar ('.');
690       w = _itoa (info->prec, workend + 1, 10, 0);
691       while (++w <= workend)
692         outchar (*w);
693     }
694
695   if (info->spec != '\0')
696     outchar (info->spec);
697
698   return done;
699 }
700 \f
701 /* Group the digits according to the grouping rules of the current locale.
702    The interpretation of GROUPING is as in `struct lconv' from <locale.h>.  */
703
704 static char *
705 group_number (char *w, char *workend, const char *grouping,
706               wchar_t thousands_sep)
707 {
708   int len;
709   char *src, *s;
710
711   /* We treat all negative values like CHAR_MAX.  */
712
713   if (*grouping == CHAR_MAX || *grouping < 0)
714     /* No grouping should be done.  */
715     return w;
716
717   len = *grouping;
718
719   /* Copy existing string so that nothing gets overwritten.  */
720   src = (char *) alloca (workend - w);
721   memcpy (src, w + 1, workend - w);
722   s = &src[workend - w - 1];
723   w = workend;
724
725   /* Process all characters in the string.  */
726   while (s >= src)
727     {
728       *w-- = *s--;
729
730       if (--len == 0 && s >= src)
731         {
732           /* A new group begins.  */
733           *w-- = thousands_sep;
734
735           len = *grouping++;
736           if (*grouping == '\0')
737             /* The previous grouping repeats ad infinitum.  */
738             --grouping;
739           else if (*grouping == CHAR_MAX || *grouping < 0)
740             {
741               /* No further grouping to be done.
742                  Copy the rest of the number.  */
743               do
744                 *w-- = *s--;
745               while (s >= src);
746               break;
747             }
748         }
749     }
750   return w;
751 }
752 \f
753 #ifdef USE_IN_LIBIO
754 /* Helper "class" for `fprintf to unbuffered': creates a temporary buffer.  */
755 struct helper_file
756   {
757     struct _IO_FILE_plus _f;
758     _IO_FILE *_put_stream;
759   };
760
761 static int
762 _IO_helper_overflow (s, c)
763   _IO_FILE *s;
764   int c;
765 {
766   _IO_FILE *target = ((struct helper_file*) s)->_put_stream;
767   int used = s->_IO_write_ptr - s->_IO_write_base;
768   if (used)
769     {
770       _IO_size_t written = _IO_sputn (target, s->_IO_write_base, used);
771       s->_IO_write_ptr -= written;
772     }
773   return _IO_putc (c, s);
774 }
775
776 static const struct _IO_jump_t _IO_helper_jumps =
777   {
778     JUMP_INIT_DUMMY,
779     JUMP_INIT (finish, _IO_default_finish),
780     JUMP_INIT (overflow, _IO_helper_overflow),
781     JUMP_INIT (underflow, _IO_default_underflow),
782     JUMP_INIT (uflow, _IO_default_uflow),
783     JUMP_INIT (pbackfail, _IO_default_pbackfail),
784     JUMP_INIT (xsputn, _IO_default_xsputn),
785     JUMP_INIT (xsgetn, _IO_default_xsgetn),
786     JUMP_INIT (seekoff, _IO_default_seekoff),
787     JUMP_INIT (seekpos, _IO_default_seekpos),
788     JUMP_INIT (setbuf, _IO_default_setbuf),
789     JUMP_INIT (sync, _IO_default_sync),
790     JUMP_INIT (doallocate, _IO_default_doallocate),
791     JUMP_INIT (read, _IO_default_read),
792     JUMP_INIT (write, _IO_default_write),
793     JUMP_INIT (seek, _IO_default_seek),
794     JUMP_INIT (close, _IO_default_close),
795     JUMP_INIT (stat, _IO_default_stat)
796   };
797
798 static int
799 buffered_vfprintf (s, format, args)
800   register _IO_FILE *s;
801   char const *format;
802   _IO_va_list args;
803 {
804   char buf[_IO_BUFSIZ];
805   struct helper_file helper;
806   register _IO_FILE *hp = (_IO_FILE *) &helper;
807   int result, to_flush;
808
809   /* Initialize helper.  */
810   helper._put_stream = s;
811   hp->_IO_write_base = buf;
812   hp->_IO_write_ptr = buf;
813   hp->_IO_write_end = buf + sizeof buf;
814   hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS;
815   _IO_JUMPS (hp) = (struct _IO_jump_t *) &_IO_helper_jumps;
816
817   /* Now print to helper instead.  */
818   result = _IO_vfprintf (hp, format, args);
819
820   /* Now flush anything from the helper to the S. */
821   if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0)
822     {
823       if (_IO_sputn (s, hp->_IO_write_base, to_flush) != to_flush)
824         return -1;
825     }
826
827   return result;
828 }
829
830 #else /* !USE_IN_LIBIO */
831
832 static int
833 buffered_vfprintf (s, format, args)
834   register FILE *s;
835   char const *format;
836   va_list args;
837 {
838   char buf[BUFSIZ];
839   int result;
840
841   s->__bufp = s->__buffer = buf;
842   s->__bufsize = sizeof buf;
843   s->__put_limit = s->__buffer + s->__bufsize;
844   s->__get_limit = s->__buffer;
845
846   /* Now use buffer to print.  */
847   result = vfprintf (s, format, args);
848
849   if (fflush (s) == EOF)
850     result = -1;
851   s->__buffer = s->__bufp = s->__get_limit = s->__put_limit = NULL;
852   s->__bufsize = 0;
853
854   return result;
855 }
856
857
858 /* Pads string with given number of a specified character.
859    This code is taken from iopadn.c of the GNU I/O library.  */
860 #define PADSIZE 16
861 static const char blanks[PADSIZE] =
862 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
863 static const char zeroes[PADSIZE] =
864 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
865
866 ssize_t
867 __printf_pad (s, pad, count)
868      FILE *s;
869      char pad;
870      size_t count;
871 {
872   const char *padptr;
873   register size_t i;
874
875   padptr = pad == ' ' ? blanks : zeroes;
876
877   for (i = count; i >= PADSIZE; i -= PADSIZE)
878     if (PUT (s, padptr, PADSIZE) != PADSIZE)
879       return -1;
880   if (i > 0)
881     if (PUT (s, padptr, i) != i)
882       return -1;
883
884   return count;
885 }
886 #undef PADSIZE
887 #endif /* USE_IN_LIBIO */