1 /* $NetBSD: subr_prf.c,v 1.27 2014/08/30 14:24:02 tsutsui Exp $ */
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * @(#)printf.c 8.1 (Berkeley) 6/11/93
35 * Scaled down version of printf(3).
38 #include <sys/cdefs.h>
39 #include <sys/types.h>
40 #include <sys/stdint.h> /* XXX: for intptr_t */
44 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
45 #define INTMAX_T longlong_t
46 #define UINTMAX_T u_longlong_t
49 #define UINTMAX_T u_long
52 #if 0 /* XXX: abuse intptr_t until the situation with ptrdiff_t is clear */
53 #define PTRDIFF_T ptrdiff_t
55 #define PTRDIFF_T intptr_t
58 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
59 static void kprintn(void (*)(int), UINTMAX_T
, int, int, int);
61 static void kprintn(void (*)(int), UINTMAX_T
, int);
63 static void sputchar(int);
64 static void kdoprnt(void (*)(int), const char *, va_list);
66 static char *sbuf
, *ebuf
;
68 /* vsnprintf: add support for returning the amount of characters that would have been
69 * written if the buffer was large enough */
71 #endif /* defined(__minix) */
73 const char hexdigits
[16] = "0123456789abcdef";
76 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
82 #endif /* defined(__minix) */
84 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
91 #define KPRINTN(base) kprintn(put, ul, base, lflag, width)
92 #define RADJUSTZEROPAD() \
94 if ((lflag & (ZEROPAD|LADJUST)) == ZEROPAD) { \
98 } while (/*CONSTCOND*/0)
99 #define LADJUSTPAD() \
101 if (lflag & LADJUST) { \
102 while (width-- > 0) \
105 } while (/*CONSTCOND*/0)
106 #define RADJUSTPAD() \
108 if ((lflag & (ZEROPAD|LADJUST)) == 0) { \
109 while (width-- > 0) \
112 } while (/*CONSTCOND*/0)
113 #else /* LIBSA_PRINTF_WIDTH_SUPPORT */
114 #define KPRINTN(base) kprintn(put, ul, base)
115 #define RADJUSTZEROPAD() /**/
116 #define LADJUSTPAD() /**/
117 #define RADJUSTPAD() /**/
118 #endif /* LIBSA_PRINTF_WIDTH_SUPPORT */
120 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
121 #define KPRINT(base) \
123 ul = (lflag & LLONG) \
124 ? va_arg(ap, u_longlong_t) \
126 ? va_arg(ap, u_long) \
127 : va_arg(ap, u_int); \
129 } while (/*CONSTCOND*/0)
130 #else /* LIBSA_PRINTF_LONGLONG_SUPPORT */
131 #define KPRINT(base) \
133 ul = (lflag & LONG) \
134 ? va_arg(ap, u_long) : va_arg(ap, u_int); \
136 } while (/*CONSTCOND*/0)
137 #endif /* LIBSA_PRINTF_LONGLONG_SUPPORT */
143 scount
++; /* increase scount regardless */
144 if (!sbuf
) return; /* hanlde NULL sbuf */
145 #endif /* defined(__minix) */
152 vprintf(const char *fmt
, va_list ap
)
155 kdoprnt(putchar
, fmt
, ap
);
156 #if defined(__minix) && defined(LIBSA_PRINTF_WIDTH_SUPPORT)
157 /* BJG: our libminc kputc() relies on a 0 to flush the diag buffer. */
159 #endif /* defined(__minix) && defined(LIBSA_PRINTF_WIDTH_SUPPORT) */
163 vsnprintf(char *buf
, size_t size
, const char *fmt
, va_list ap
)
167 ebuf
= buf
+ size
- 1;
169 scount
= 0; /* use scount to keep track of written items */
170 #endif /* defined(__minix) */
172 kdoprnt(sputchar
, fmt
, ap
);
175 if (sbuf
){ /* handle case where sbuf == NULL */
178 #if defined(_MINIX_MAGIC)
179 sbuf
= ebuf
= NULL
; /* leave no dangling pointers */
182 #else /* __minix is not defined */
185 #endif /* defined(__minix) */
189 kdoprnt(void (*put
)(int), const char *fmt
, va_list ap
)
195 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
200 #endif /* defined(__minix) */
204 while ((ch
= *fmt
++) != '%') {
210 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
214 #endif /* defined(__minix) */
217 switch (ch
= *fmt
++) {
218 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
222 max
= va_arg(ap
, int);
224 } else for (max
= 0; *fmt
>= '0' && *fmt
<= '9'; fmt
++)
225 max
= max
* 10 + *fmt
- '0';
227 #endif /* defined(__minix) */
243 case '1': case '2': case '3': case '4': case '5':
244 case '6': case '7': case '8': case '9':
249 if ((unsigned)ch
- '0' > 9)
256 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
265 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
266 if (sizeof(intmax_t) == sizeof(long long))
270 if (sizeof(intmax_t) == sizeof(long))
274 if (sizeof(PTRDIFF_T
) == sizeof(long))
278 if (sizeof(ssize_t
) == sizeof(long))
282 ch
= va_arg(ap
, int);
283 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
291 p
= va_arg(ap
, char *);
292 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
293 for (q
= p
; *q
!= '\0'; ++q
)
296 if (max
>= 0 && q
- p
> max
)
298 #endif /* defined(__minix) */
302 #if defined(LIBSA_PRINTF_WIDTH_SUPPORT) && defined(__minix)
303 while ((max
< 0 || max
-- > 0) &&
304 (ch
= (unsigned char)*p
++))
305 #else /* !defined(LIBSA_PRINTF_WIDTH_SUPPORT) || !defined(__minix) */
306 while ((ch
= (unsigned char)*p
++))
307 #endif /* !defined(LIBSA_PRINTF_WIDTH_SUPPORT) || !defined(__minix) */
313 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
314 (lflag
& LLONG
) ? va_arg(ap
, longlong_t
) :
316 (lflag
& LONG
) ? va_arg(ap
, long) : va_arg(ap
, int);
317 if ((INTMAX_T
)ul
< 0) {
319 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
334 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
349 #endif /* defined(__minix) */
360 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
361 kprintn(void (*put
)(int), UINTMAX_T ul
, int base
, int lflag
, int width
)
363 kprintn(void (*put
)(int), UINTMAX_T ul
, int base
)
366 /* hold a INTMAX_T in base 8 */
367 char *p
, buf
[(sizeof(INTMAX_T
) * NBBY
/ 3) + 1 + 2 /* ALT + SIGN */];
368 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
374 *p
++ = hexdigits
[ul
% base
];
376 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
377 /* LSC: Quick hack to support capital hex printout. */
378 if ((lflag
& HEXCAP
) && (*(p
-1) >= 'a') && (*(p
-1) <= 'z')) {
382 #endif /* defined(__minix) */
383 } while (ul
/= base
);
384 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
386 if (lflag
& ALT
&& *(p
- 1) != '0') {
389 } else if (base
== 16) {
394 if (lflag
& NEGATIVE
)
396 else if (lflag
& SIGN
)
398 else if (lflag
& SPACE
)
401 if (lflag
& ZEROPAD
) {