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. */
20 #include <localeinfo.h>
34 /* This function from the GNU C library is also used in libio.
35 To compile for use in libio, compile with -DUSE_IN_LIBIO. */
38 /* This code is for use in libio. */
40 #define PUT(f, s, n) _IO_sputn (f, s, n)
41 #define PAD(padchar) _IO_padn (s, padchar, width)
42 #define PUTC(c, f) _IO_putc(c, f)
43 #define vfprintf _IO_vfprintf
44 #define size_t _IO_size_t
46 #define va_list _IO_va_list
48 #define BUFSIZ _IO_BUFSIZ
49 #define ARGCHECK(s, format) \
52 /* Check file argument for consistence. */ \
54 if (s->_flags & _IO_NO_WRITES || format == NULL) \
60 #define UNBUFFERED_P(s) ((s)->_IO_file_flags & _IO_UNBUFFERED)
61 #else /* ! USE_IN_LIBIO */
62 /* This code is for use in the GNU C library. */
64 #define PUTC(c, f) putc (c, f)
65 #define PUT(f, s, n) fwrite (s, 1, n, f)
66 ssize_t __printf_pad
__P ((FILE *, char pad
, int n
));
67 #define PAD(padchar) __printf_pad (s, padchar, width)
68 #define ARGCHECK(s, format) \
71 /* Check file argument for consistence. */ \
72 if (!__validfp(s) || !s->__mode.__write || format == NULL) \
79 if (__flshfp (s, EOF) == EOF) \
83 #define UNBUFFERED_P(s) ((s)->__buffer == NULL)
84 #endif /* USE_IN_LIBIO */
90 register CONST int outc = (x); \
91 if (putc(outc, s) == EOF) \
97 /* Advances STRING after writing LEN chars of it. */
98 #define outstring(string, len) \
103 if (PUT (s, string, len) != len) \
110 outchar (*string++); \
113 /* Helper function to provide temporary buffering for unbuffered streams. */
114 static int buffered_vfprintf
__P ((FILE *stream
, const char *fmt
, va_list));
116 /* Cast the next arg, of type ARGTYPE, into CASTTYPE, and put it in VAR. */
117 #define castarg(var, argtype, casttype) \
118 var = (casttype) va_arg(args, argtype)
119 /* Get the next arg, of type TYPE, and put it in VAR. */
120 #define nextarg(var, type) castarg(var, type, type)
122 static printf_function printf_unknown
;
124 extern printf_function
**__printf_function_table
;
127 #define HAVE_LONGLONG
128 #define LONGLONG long long
130 #define LONGLONG long
133 static char *group_number
__P ((char *, char *, const char *, wchar_t));
136 DEFUN(vfprintf
, (s
, format
, args
),
137 register FILE *s AND CONST
char *format AND
va_list args
)
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 /* Pointer into the format string. */
146 register CONST
char *f
;
148 /* Number of characters written. */
149 register size_t done
= 0;
151 ARGCHECK (s
, format
);
153 if (UNBUFFERED_P (s
))
154 /* Use a helper function which will allocate a local temporary buffer
155 for the stream and then call us again. */
156 return buffered_vfprintf (s
, format
, args
);
158 /* Reset multibyte characters to their initial state. */
159 (void) mblen ((char *) NULL
, 0);
161 /* Figure out the thousands seperator character. */
162 if (mbtowc (&thousands_sep
, _numeric_info
->thousands_sep
,
163 strlen (_numeric_info
->thousands_sep
)) <= 0)
164 thousands_sep
= (wchar_t) *_numeric_info
->thousands_sep
;
165 grouping
= _numeric_info
->grouping
; /* Cache the grouping info array. */
166 if (*grouping
== '\0' || thousands_sep
== L
'\0')
172 /* Type modifiers. */
173 char is_short
, is_long
, is_long_double
;
175 /* We use the `L' modifier for `long long int'. */
176 #define is_longlong is_long_double
178 #define is_longlong 0
180 /* Format spec modifiers. */
181 char space
, showsign
, left
, alt
, group
;
183 /* Padding character: ' ' or '0'. */
185 /* Width of a field. */
187 /* Precision of a field. */
190 /* Decimal integer is negative. */
193 /* Current character of the format. */
196 /* Base of a number to be written. */
198 /* Integral values to be written. */
199 unsigned LONGLONG
int num
;
200 LONGLONG
int signed_num
;
202 /* String to be written. */
204 char errorbuf
[1024]; /* Buffer sometimes used by %m. */
206 /* Auxiliary function to do output. */
207 printf_function
*function
;
211 /* Non-ASCII, may be a multibyte. */
212 int len
= mblen (f
, strlen (f
));
222 /* This isn't a format spec, so write everything out until the
223 next one. To properly handle multibyte characters, we cannot
224 just search for a '%'. Since multibyte characters are hairy
225 (and dealt with above), if we hit any byte above 127 (only
226 those can start a multibyte character) we just punt back to
230 while (*f
!= '\0' && *f
!= '%' && isascii (*f
));
236 /* Check for "%%". Note that although the ANSI standard lists
237 '%' as a conversion specifier, it says "The complete format
238 specification shall be `%%'," so we can avoid all the width
239 and precision processing. */
247 /* Check for spec modifiers. */
248 space
= showsign
= left
= alt
= group
= 0;
250 while (*f
== ' ' || *f
== '+' || *f
== '-' || *f
== '#' || *f
== '0' ||
255 /* Output a space in place of a sign, when there is no sign. */
259 /* Always output + or - for numbers. */
263 /* Left-justify things. */
267 /* Use the "alternate form":
268 Hex has 0x or 0X, FP always has a decimal point. */
276 /* Show grouping in numbers if the locale information
284 /* Get the field width. */
288 /* The field width is given in an argument.
289 A negative field width indicates left justification. */
305 /* Get the precision. */
306 /* -1 means none given; 0 means explicit 0. */
313 /* The precision is given in an argument. */
320 else if (isdigit (*f
))
323 while (*f
!= '\0' && isdigit (*f
))
330 /* "%.?" is treated like "%.0?". */
334 /* If there was a precision specified, ignore the 0 flag and always
339 /* Check for type modifiers. */
340 is_short
= is_long
= is_long_double
= 0;
341 while (*f
== 'h' || *f
== 'l' || *f
== 'L' || *f
== 'q')
345 /* int's are short int's. */
351 /* A double `l' is equivalent to an `L'. */
355 /* int's are long int's. */
359 /* double's are long double's, and int's are long long int's. */
364 /* int's are size_t's. */
366 assert (sizeof(size_t) <= sizeof(unsigned long long int));
367 is_longlong
= sizeof(size_t) > sizeof(unsigned long int);
369 is_long
= sizeof(size_t) > sizeof(unsigned int);
373 /* 4.4 uses this for long long. */
382 /* Format specification. */
384 function
= (__printf_function_table
== NULL
? NULL
:
385 __printf_function_table
[fc
]);
386 if (function
== NULL
)
391 /* Decimal integer. */
394 nextarg(signed_num
, LONGLONG
int);
396 nextarg(signed_num
, long int);
398 castarg(signed_num
, int, long int);
400 castarg(signed_num
, int, short int);
402 is_neg
= signed_num
< 0;
403 num
= is_neg
? (- signed_num
) : signed_num
;
407 /* Decimal unsigned integer. */
409 goto unsigned_number
;
412 /* Octal unsigned integer. */
414 goto unsigned_number
;
417 /* Hexadecimal unsigned integer. */
419 /* Hex with lower-case digits. */
424 /* Unsigned number of base BASE. */
427 castarg(num
, LONGLONG
int, unsigned LONGLONG
int);
429 castarg(num
, long int, unsigned long int);
431 castarg(num
, int, unsigned int);
433 castarg(num
, int, unsigned short int);
435 /* ANSI only specifies the `+' and
436 ` ' flags for signed conversions. */
437 is_neg
= showsign
= space
= 0;
440 /* Number of base BASE. */
443 char *CONST workend
= &work
[sizeof(work
) - 1];
446 /* Supply a default precision if none was given. */
450 /* Put the number in WORK. */
451 w
= _itoa (num
, workend
+ 1, base
, fc
== 'X') - 1;
452 if (group
&& grouping
)
453 w
= group_number (w
, workend
, grouping
, thousands_sep
);
454 width
-= workend
- w
;
457 if (alt
&& base
== 8 && prec
<= 0)
470 if (alt
&& base
== 16)
473 if (is_neg
|| showsign
|| space
)
476 if (!left
&& pad
== ' ')
486 if (alt
&& base
== 16)
492 if (!left
&& pad
== '0')
495 /* Write the number. */
496 while (++w
<= workend
)
510 /* Floating-point number. */
511 extern printf_function __printf_fp
;
512 function
= __printf_fp
;
524 outchar ((unsigned char) num
);
531 static CONST
char null
[] = "(null)";
534 nextarg(str
, CONST
char *);
539 /* Write "(null)" if there's space. */
540 if (prec
== -1 || prec
>= (int) sizeof(null
) - 1)
543 len
= sizeof(null
) - 1;
553 if (prec
!= -1 && (size_t) prec
< len
)
559 outstring (str
, len
);
566 /* Generic pointer. */
569 nextarg(ptr
, CONST PTR
);
572 /* If the pointer is not NULL, write it as a %#x spec. */
576 num
= (unsigned LONGLONG
int) (unsigned long int) ptr
;
583 /* Write "(nil)" for a nil pointer. */
584 static CONST
char nil
[] = "(nil)";
585 register CONST
char *p
;
587 width
-= sizeof (nil
) - 1;
590 for (p
= nil
; *p
!= '\0'; ++p
)
599 /* Answer the count of characters written. */
603 nextarg(p
, LONGLONG
int *);
609 nextarg(p
, long int *);
621 nextarg(p
, short int *);
628 extern char *_strerror_internal
__P ((int, char buf
[1024]));
629 str
= _strerror_internal (errno
, errorbuf
);
634 /* Unrecognized format specifier. */
635 function
= printf_unknown
;
642 struct printf_info info
;
647 info
.is_long_double
= is_long_double
;
648 info
.is_short
= is_short
;
649 info
.is_long
= is_long
;
653 info
.showsign
= showsign
;
657 function_done
= (*function
) (s
, &info
, &args
);
658 if (function_done
< 0)
661 done
+= function_done
;
670 DEFUN(printf_unknown
, (s
, info
, arg
),
671 FILE *s AND CONST
struct printf_info
*info AND
va_list *arg
)
675 char *CONST workend
= &work
[sizeof(work
) - 1];
677 register int prec
= info
->prec
, width
= info
->width
;
687 else if (info
->space
)
691 if (info
->pad
== '0')
697 *w
-- = '0' + (width
% 10);
700 while (++w
<= workend
)
703 if (info
->prec
!= -1)
709 *w
-- = '0' + (prec
% 10);
712 while (++w
<= workend
)
721 /* Group the digits according to the grouping rules of the current locale.
722 The interpretation of GROUPING is as in `struct lconv' from <locale.h>. */
725 group_number (char *w
, char *workend
, const char *grouping
,
726 wchar_t thousands_sep
)
731 /* We treat all negative values like CHAR_MAX. */
733 if (*grouping
== CHAR_MAX
|| *grouping
< 0)
734 /* No grouping should be done. */
739 /* Copy existing string so that nothing gets overwritten. */
740 src
= (char *) alloca (workend
- w
);
741 memcpy (src
, w
+ 1, workend
- w
);
742 s
= &src
[workend
- w
- 1];
745 /* Process all characters in the string. */
750 if (--len
== 0 && s
>= src
)
752 /* A new group begins. */
753 *w
-- = thousands_sep
;
756 if (*grouping
== '\0')
757 /* The previous grouping repeats ad infinitum. */
759 else if (*grouping
== CHAR_MAX
|| *grouping
< 0)
761 /* No further grouping to be done.
762 Copy the rest of the number. */
775 /* Helper "class" for `fprintf to unbuffered': creates a temporary buffer. */
778 struct _IO_FILE_plus _f
;
779 _IO_FILE
*_put_stream
;
783 DEFUN(_IO_helper_overflow
, (s
, c
), _IO_FILE
*s AND
int c
)
785 _IO_FILE
*target
= ((struct helper_file
*) s
)->_put_stream
;
786 int used
= s
->_IO_write_ptr
- s
->_IO_write_base
;
789 _IO_size_t written
= _IO_sputn (target
, s
->_IO_write_base
, used
);
790 s
->_IO_write_ptr
-= written
;
792 return _IO_putc (c
, s
);
795 static const struct _IO_jump_t _IO_helper_jumps
=
798 _IO_default_underflow
,
803 _IO_default_doallocate
,
804 _IO_default_pbackfail
,
817 DEFUN(buffered_vfprintf
, (s
, format
, args
),
818 register _IO_FILE
*s AND
char CONST
*format AND _IO_va_list args
)
820 char buf
[_IO_BUFSIZ
];
821 struct helper_file helper
;
822 register _IO_FILE
*hp
= (_IO_FILE
*) &helper
;
823 int result
, to_flush
;
825 /* Initialize helper. */
826 helper
._put_stream
= s
;
827 hp
->_IO_write_base
= buf
;
828 hp
->_IO_write_ptr
= buf
;
829 hp
->_IO_write_end
= buf
+ sizeof buf
;
830 hp
->_IO_file_flags
= _IO_MAGIC
|_IO_NO_READS
;
831 hp
->_jumps
= (struct _IO_jump_t
*) &_IO_helper_jumps
;
833 /* Now print to helper instead. */
834 result
= _IO_vfprintf (hp
, format
, args
);
836 /* Now flush anything from the helper to the S. */
837 if ((to_flush
= hp
->_IO_write_ptr
- hp
->_IO_write_base
) > 0)
839 if (_IO_sputn (s
, hp
->_IO_write_base
, to_flush
) != to_flush
)
846 #else /* !USE_IN_LIBIO */
849 DEFUN(buffered_vfprintf
, (s
, format
, args
),
850 register FILE *s AND
char CONST
*format AND
va_list args
)
855 s
->__bufp
= s
->__buffer
= buf
;
856 s
->__bufsize
= sizeof buf
;
857 s
->__put_limit
= s
->__buffer
+ s
->__bufsize
;
858 s
->__get_limit
= s
->__buffer
;
860 /* Now use buffer to print. */
861 result
= vfprintf (s
, format
, args
);
863 if (fflush (s
) == EOF
)
865 s
->__buffer
= s
->__bufp
= s
->__get_limit
= s
->__put_limit
= NULL
;
872 /* Pads string with given number of a specified character.
873 This code is taken from iopadn.c of the GNU I/O library. */
875 static const char blanks
[PADSIZE
] =
876 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
877 static const char zeroes
[PADSIZE
] =
878 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
881 __printf_pad (s
, pad
, count
)
888 size_t written
= 0, w
;
890 padptr
= pad
== ' ' ? blanks
: zeroes
;
892 for (i
= count
; i
>= PADSIZE
; i
-= PADSIZE
)
894 w
= PUT(s
, padptr
, PADSIZE
);
901 w
= PUT(s
, padptr
, i
);
907 #endif /* USE_IN_LIBIO */