1 /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
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. */
31 #include "../locale/localeinfo.h"
33 /* Include the shared code for parsing the format string. */
34 #include "printf-parse.h"
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. */
41 /* This code is for use in libio. */
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
51 #define va_list _IO_va_list
53 #define BUFSIZ _IO_BUFSIZ
54 #define ARGCHECK(s, format) \
57 /* Check file argument for consistence. */ \
59 if (s->_flags & _IO_NO_WRITES || format == NULL) \
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. */
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) \
79 /* Check file argument for consistence. */ \
80 if (!__validfp(s) || !s->__mode.__write || format == NULL) \
87 if (__flshfp (s, EOF) == EOF) \
91 #define UNBUFFERED_P(s) ((s)->__buffer == NULL)
92 #endif /* USE_IN_LIBIO */
98 register const int outc = (x); \
99 if (putc (outc, s) == EOF) \
105 #define outstring(string, len) \
110 if (PUT (s, string, len) != len) \
116 register const char *cp = string; \
117 register int l = len; \
123 /* Helper function to provide temporary buffering for unbuffered streams. */
124 static int buffered_vfprintf
__P ((FILE *stream
, const char *fmt
, va_list));
126 static printf_function printf_unknown
;
128 extern printf_function
**__printf_function_table
;
130 static char *group_number
__P ((char *, char *, const char *, wchar_t));
134 vfprintf (s
, format
, ap
)
139 /* The character used as thousands separator. */
140 wchar_t thousands_sep
;
142 /* The string describing the size of groups of digits. */
143 const char *grouping
;
145 /* Array with information about the needed arguments. This has to be
146 dynamically extendable. */
149 struct printf_spec
*specs
;
151 /* The number of arguments the format string requests. This will
152 determine the size of the array needed to store the argument
156 union printf_arg
*args_value
;
158 /* Positional parameters refer to arguments directly. This could also
159 determine the maximum number of arguments. Track the maximum number. */
162 /* End of leading constant string. */
163 const char *lead_str_end
;
165 /* Number of characters written. */
166 register size_t done
= 0;
168 /* Running pointer through format string. */
171 /* Just a counter. */
174 ARGCHECK (s
, format
);
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
);
181 /* Reset multibyte characters to their initial state. */
182 (void) mblen ((char *) NULL
, 0);
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')
192 nspecs_max
= 32; /* A more or less arbitrary start value. */
193 specs
= alloca (nspecs_max
* sizeof (struct printf_spec
));
198 /* Find the first format specifier. */
199 lead_str_end
= find_spec (format
);
201 for (f
= lead_str_end
; *f
!= '\0'; f
= specs
[nspecs
++].next_fmt
)
203 if (nspecs
>= nspecs_max
)
205 /* Extend the array of format specifiers. */
206 struct printf_spec
*old
= specs
;
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;
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;
224 /* Parse the format specifier. */
225 nargs
+= parse_one_spec (f
, nargs
, &specs
[nspecs
], &max_ref_arg
);
228 /* Determine the number of arguments the format string consumes. */
229 nargs
= MAX (nargs
, max_ref_arg
);
231 /* Allocate memory for the argument descriptions. */
232 args_type
= alloca (nargs
* sizeof (int));
233 args_value
= alloca (nargs
* sizeof (union printf_arg
));
235 /* XXX Could do sanity check here:
236 Initialize args_type elts to zero.
237 If any is still zero after this loop, format is invalid. */
239 /* Fill in the types of all the arguments. */
240 for (cnt
= 0; cnt
< nspecs
; ++cnt
)
242 /* If the width is determined by an argument this is an int. */
243 if (specs
[cnt
].width_arg
!= -1)
244 args_type
[specs
[cnt
].width_arg
] = PA_INT
;
246 /* If the precision is determined by an argument this is an int. */
247 if (specs
[cnt
].prec_arg
!= -1)
248 args_type
[specs
[cnt
].prec_arg
] = PA_INT
;
250 switch (specs
[cnt
].ndata_args
)
252 case 0: /* No arguments. */
254 case 1: /* One argument; we already have the type. */
255 args_type
[specs
[cnt
].data_arg
] = specs
[cnt
].data_arg_type
;
258 /* We have more than one argument for this format spec. We must
259 call the arginfo function again to determine all the types. */
260 (void) (*__printf_arginfo_table
[specs
[cnt
].info
.spec
])
262 specs
[cnt
].ndata_args
, &args_type
[specs
[cnt
].data_arg
]);
267 /* Now we know all the types and the order. Fill in the argument values. */
268 for (cnt
= 0; cnt
< nargs
; ++cnt
)
269 switch (args_type
[cnt
])
271 #define T(tag, mem, type) \
273 args_value[cnt].mem = va_arg (ap, type); \
276 T (PA_CHAR
, pa_char
, int); /* Promoted. */
277 T (PA_INT
|PA_FLAG_SHORT
, pa_short_int
, int); /* Promoted. */
278 T (PA_INT
, pa_int
, int);
279 T (PA_INT
|PA_FLAG_LONG
, pa_long_int
, long int);
280 T (PA_INT
|PA_FLAG_LONG_LONG
, pa_long_long_int
, long long int);
281 T (PA_FLOAT
, pa_float
, double); /* Promoted. */
282 T (PA_DOUBLE
, pa_double
, double);
283 T (PA_DOUBLE
|PA_FLAG_LONG_DOUBLE
, pa_long_double
, long double);
284 T (PA_STRING
, pa_string
, const char *);
285 T (PA_POINTER
, pa_pointer
, void *);
288 if ((args_type
[cnt
] & PA_FLAG_PTR
) != 0)
289 args_value
[cnt
].pa_pointer
= va_arg (ap
, void *);
293 /* Write the literal text before the first format. */
294 outstring (format
, lead_str_end
- format
);
296 /* Now walk through all format specifiers and process them. */
297 for (cnt
= 0; cnt
< nspecs
; ++cnt
)
299 printf_function
*function
; /* Auxiliary function to do output. */
300 int is_neg
; /* Decimal integer is negative. */
301 int base
; /* Base of a number to be written. */
302 unsigned long long int num
; /* Integral number to be written. */
303 const char *str
; /* String to be written. */
304 char errorbuf
[1024]; /* Buffer sometimes used by %m. */
306 if (specs
[cnt
].width_arg
!= -1)
308 /* Extract the field width from an argument. */
309 specs
[cnt
].info
.width
= args_value
[specs
[cnt
].width_arg
].pa_int
;
311 if (specs
[cnt
].info
.width
< 0)
312 /* If the width value is negative left justification is selected
313 and the value is taken as being positive. */
315 specs
[cnt
].info
.width
= -specs
[cnt
].info
.width
;
316 specs
[cnt
].info
.left
= 1;
320 if (specs
[cnt
].prec_arg
!= -1)
322 /* Extract the precision from an argument. */
323 specs
[cnt
].info
.prec
= args_value
[specs
[cnt
].prec_arg
].pa_int
;
325 if (specs
[cnt
].info
.prec
< 0)
326 /* If the precision is negative the precision is omitted. */
327 specs
[cnt
].info
.prec
= -1;
330 /* Check for a user-defined handler for this spec. */
331 function
= (__printf_function_table
== NULL
? NULL
:
332 __printf_function_table
[specs
[cnt
].info
.spec
]);
334 if (function
!= NULL
)
335 use_function
: /* Built-in formats with helpers use this. */
339 const void *ptr
[specs
[cnt
].ndata_args
];
341 /* Fill in an array of pointers to the argument values. */
342 for (i
= 0; i
< specs
[cnt
].ndata_args
; ++i
)
343 ptr
[i
] = &args_value
[specs
[cnt
].data_arg
+ i
];
345 /* Call the function. */
346 function_done
= (*function
) (s
, &specs
[cnt
].info
, ptr
);
348 /* If an error occured don't do any further work. */
349 if (function_done
< 0)
352 done
+= function_done
;
355 switch (specs
[cnt
].info
.spec
)
358 /* Write a literal "%". */
364 long long int signed_num
;
366 /* Decimal integer. */
368 if (specs
[cnt
].info
.is_longlong
)
369 signed_num
= args_value
[specs
[cnt
].data_arg
].pa_long_long_int
;
370 else if (specs
[cnt
].info
.is_long
)
371 signed_num
= args_value
[specs
[cnt
].data_arg
].pa_long_int
;
372 else if (!specs
[cnt
].info
.is_short
)
373 signed_num
= args_value
[specs
[cnt
].data_arg
].pa_int
;
375 signed_num
= args_value
[specs
[cnt
].data_arg
].pa_short_int
;
377 is_neg
= signed_num
< 0;
378 num
= is_neg
? (- signed_num
) : signed_num
;
383 /* Decimal unsigned integer. */
385 goto unsigned_number
;
388 /* Octal unsigned integer. */
390 goto unsigned_number
;
393 /* Hexadecimal unsigned integer. */
395 /* Hex with lower-case digits. */
399 /* Unsigned number of base BASE. */
401 if (specs
[cnt
].info
.is_longlong
)
402 num
= args_value
[specs
[cnt
].data_arg
].pa_u_long_long_int
;
403 else if (specs
[cnt
].info
.is_long
)
404 num
= args_value
[specs
[cnt
].data_arg
].pa_u_long_int
;
405 else if (!specs
[cnt
].info
.is_short
)
406 num
= args_value
[specs
[cnt
].data_arg
].pa_u_int
;
408 num
= args_value
[specs
[cnt
].data_arg
].pa_u_short_int
;
410 /* ANSI only specifies the `+' and
411 ` ' flags for signed conversions. */
413 specs
[cnt
].info
.showsign
= 0;
414 specs
[cnt
].info
.space
= 0;
417 /* Number of base BASE. */
420 char *const workend
= &work
[sizeof(work
) - 1];
423 /* Supply a default precision if none was given. */
424 if (specs
[cnt
].info
.prec
== -1)
425 specs
[cnt
].info
.prec
= 1;
427 /* Put the number in WORK. */
428 w
= _itoa (num
, workend
+ 1, base
, specs
[cnt
].info
.spec
== 'X');
430 if (specs
[cnt
].info
.group
&& grouping
)
431 w
= group_number (w
, workend
, grouping
, thousands_sep
);
432 specs
[cnt
].info
.width
-= workend
- w
;
433 specs
[cnt
].info
.prec
-= workend
- w
;
435 if (num
!= 0 && specs
[cnt
].info
.alt
&& base
== 8
436 && specs
[cnt
].info
.prec
<= 0)
438 /* Add octal marker. */
440 --specs
[cnt
].info
.width
;
443 if (specs
[cnt
].info
.prec
> 0)
445 /* Add zeros to the precision. */
446 specs
[cnt
].info
.width
-= specs
[cnt
].info
.prec
;
447 while (specs
[cnt
].info
.prec
-- > 0)
451 if (num
!= 0 && specs
[cnt
].info
.alt
&& base
== 16)
452 /* Account for 0X hex marker. */
453 specs
[cnt
].info
.width
-= 2;
455 if (is_neg
|| specs
[cnt
].info
.showsign
|| specs
[cnt
].info
.space
)
456 --specs
[cnt
].info
.width
;
458 if (!specs
[cnt
].info
.left
&& specs
[cnt
].info
.pad
== ' ')
463 else if (specs
[cnt
].info
.showsign
)
465 else if (specs
[cnt
].info
.space
)
468 if (num
!= 0 && specs
[cnt
].info
.alt
&& base
== 16)
471 outchar (specs
[cnt
].info
.spec
);
474 if (!specs
[cnt
].info
.left
&& specs
[cnt
].info
.pad
== '0')
477 /* Write the number. */
478 while (++w
<= workend
)
481 if (specs
[cnt
].info
.left
)
492 /* Floating-point number. This is handled by printf_fp.c. */
493 extern printf_function __printf_fp
;
494 function
= __printf_fp
;
500 if (!specs
[cnt
].info
.left
)
502 --specs
[cnt
].info
.width
;
505 outchar ((unsigned char) args_value
[specs
[cnt
].data_arg
].pa_char
);
506 if (specs
[cnt
].info
.left
)
512 static const char null
[] = "(null)";
515 str
= args_value
[specs
[cnt
].data_arg
].pa_string
;
521 /* Write "(null)" if there's space. */
522 if (specs
[cnt
].info
.prec
== -1
523 || specs
[cnt
].info
.prec
>= (int) sizeof (null
) - 1)
526 len
= sizeof (null
) - 1;
534 else if (specs
[cnt
].info
.prec
!= -1)
536 /* Search for the end of the string, but don't search
537 past the length specified by the precision. */
538 const char *end
= memchr (str
, '\0', specs
[cnt
].info
.prec
);
542 len
= specs
[cnt
].info
.prec
;
547 specs
[cnt
].info
.width
-= len
;
549 if (!specs
[cnt
].info
.left
)
551 outstring (str
, len
);
552 if (specs
[cnt
].info
.left
)
558 /* Generic pointer. */
561 ptr
= args_value
[specs
[cnt
].data_arg
].pa_pointer
;
564 /* If the pointer is not NULL, write it as a %#x spec. */
566 num
= (unsigned long long int) (unsigned long int) ptr
;
568 specs
[cnt
].info
.alt
= 1;
569 specs
[cnt
].info
.spec
= 'x';
570 specs
[cnt
].info
.group
= 0;
575 /* Write "(nil)" for a nil pointer. */
577 /* Make sure the full string "(nil)" is printed. */
578 if (specs
[cnt
].info
.prec
< 5)
579 specs
[cnt
].info
.prec
= 5;
586 /* Answer the count of characters written. */
587 if (specs
[cnt
].info
.is_longlong
)
589 args_value
[specs
[cnt
].data_arg
].pa_pointer
= done
;
590 else if (specs
[cnt
].info
.is_long
)
592 args_value
[specs
[cnt
].data_arg
].pa_pointer
= done
;
593 else if (!specs
[cnt
].info
.is_short
)
595 args_value
[specs
[cnt
].data_arg
].pa_pointer
= done
;
598 args_value
[specs
[cnt
].data_arg
].pa_pointer
= done
;
603 extern char *_strerror_internal
__P ((int, char *buf
, size_t));
604 str
= _strerror_internal (errno
, errorbuf
, sizeof errorbuf
);
609 /* Unrecognized format specifier. */
610 function
= printf_unknown
;
614 /* Write the following constant string. */
615 outstring (specs
[cnt
].end_of_fmt
,
616 specs
[cnt
].next_fmt
- specs
[cnt
].end_of_fmt
);
623 /* Handle an unknown format specifier. This prints out a canonicalized
624 representation of the format spec itself. */
627 printf_unknown (s
, info
, args
)
629 const struct printf_info
*info
;
630 const void **const args
;
634 char *const workend
= &work
[sizeof(work
) - 1];
645 else if (info
->space
)
649 if (info
->pad
== '0')
652 if (info
->width
!= 0)
654 w
= _itoa (info
->width
, workend
+ 1, 10, 0);
655 while (++w
<= workend
)
659 if (info
->prec
!= -1)
662 w
= _itoa (info
->prec
, workend
+ 1, 10, 0);
663 while (++w
<= workend
)
667 if (info
->spec
!= '\0')
668 outchar (info
->spec
);
673 /* Group the digits according to the grouping rules of the current locale.
674 The interpretation of GROUPING is as in `struct lconv' from <locale.h>. */
677 group_number (char *w
, char *workend
, const char *grouping
,
678 wchar_t thousands_sep
)
683 /* We treat all negative values like CHAR_MAX. */
685 if (*grouping
== CHAR_MAX
|| *grouping
< 0)
686 /* No grouping should be done. */
691 /* Copy existing string so that nothing gets overwritten. */
692 src
= (char *) alloca (workend
- w
);
693 memcpy (src
, w
+ 1, workend
- w
);
694 s
= &src
[workend
- w
- 1];
697 /* Process all characters in the string. */
702 if (--len
== 0 && s
>= src
)
704 /* A new group begins. */
705 *w
-- = thousands_sep
;
708 if (*grouping
== '\0')
709 /* The previous grouping repeats ad infinitum. */
711 else if (*grouping
== CHAR_MAX
|| *grouping
< 0)
713 /* No further grouping to be done.
714 Copy the rest of the number. */
726 /* Helper "class" for `fprintf to unbuffered': creates a temporary buffer. */
729 struct _IO_FILE_plus _f
;
730 _IO_FILE
*_put_stream
;
734 _IO_helper_overflow (s
, c
)
738 _IO_FILE
*target
= ((struct helper_file
*) s
)->_put_stream
;
739 int used
= s
->_IO_write_ptr
- s
->_IO_write_base
;
742 _IO_size_t written
= _IO_sputn (target
, s
->_IO_write_base
, used
);
743 s
->_IO_write_ptr
-= written
;
745 return _IO_putc (c
, s
);
748 static const struct _IO_jump_t _IO_helper_jumps
=
751 _IO_default_underflow
,
756 _IO_default_doallocate
,
757 _IO_default_pbackfail
,
770 buffered_vfprintf (s
, format
, args
)
771 register _IO_FILE
*s
;
775 char buf
[_IO_BUFSIZ
];
776 struct helper_file helper
;
777 register _IO_FILE
*hp
= (_IO_FILE
*) &helper
;
778 int result
, to_flush
;
780 /* Initialize helper. */
781 helper
._put_stream
= s
;
782 hp
->_IO_write_base
= buf
;
783 hp
->_IO_write_ptr
= buf
;
784 hp
->_IO_write_end
= buf
+ sizeof buf
;
785 hp
->_IO_file_flags
= _IO_MAGIC
|_IO_NO_READS
;
786 hp
->_jumps
= (struct _IO_jump_t
*) &_IO_helper_jumps
;
788 /* Now print to helper instead. */
789 result
= _IO_vfprintf (hp
, format
, args
);
791 /* Now flush anything from the helper to the S. */
792 if ((to_flush
= hp
->_IO_write_ptr
- hp
->_IO_write_base
) > 0)
794 if (_IO_sputn (s
, hp
->_IO_write_base
, to_flush
) != to_flush
)
801 #else /* !USE_IN_LIBIO */
804 buffered_vfprintf (s
, format
, args
)
812 s
->__bufp
= s
->__buffer
= buf
;
813 s
->__bufsize
= sizeof buf
;
814 s
->__put_limit
= s
->__buffer
+ s
->__bufsize
;
815 s
->__get_limit
= s
->__buffer
;
817 /* Now use buffer to print. */
818 result
= vfprintf (s
, format
, args
);
820 if (fflush (s
) == EOF
)
822 s
->__buffer
= s
->__bufp
= s
->__get_limit
= s
->__put_limit
= NULL
;
829 /* Pads string with given number of a specified character.
830 This code is taken from iopadn.c of the GNU I/O library. */
832 static const char blanks
[PADSIZE
] =
833 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
834 static const char zeroes
[PADSIZE
] =
835 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
838 __printf_pad (s
, pad
, count
)
846 padptr
= pad
== ' ' ? blanks
: zeroes
;
848 for (i
= count
; i
>= PADSIZE
; i
-= PADSIZE
)
849 if (PUT (s
, padptr
, PADSIZE
) != PADSIZE
)
852 if (PUT (s
, padptr
, i
) != i
)
858 #endif /* USE_IN_LIBIO */