xref: /minix3/sys/lib/libsa/subr_prf.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: subr_prf.c,v 1.27 2014/08/30 14:24:02 tsutsui Exp $	*/
258a2b000SEvgeniy Ivanov 
358a2b000SEvgeniy Ivanov /*-
458a2b000SEvgeniy Ivanov  * Copyright (c) 1993
558a2b000SEvgeniy Ivanov  *	The Regents of the University of California.  All rights reserved.
658a2b000SEvgeniy Ivanov  *
758a2b000SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
858a2b000SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
958a2b000SEvgeniy Ivanov  * are met:
1058a2b000SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
1158a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
1258a2b000SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
1358a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
1458a2b000SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
1558a2b000SEvgeniy Ivanov  * 3. Neither the name of the University nor the names of its contributors
1658a2b000SEvgeniy Ivanov  *    may be used to endorse or promote products derived from this software
1758a2b000SEvgeniy Ivanov  *    without specific prior written permission.
1858a2b000SEvgeniy Ivanov  *
1958a2b000SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2058a2b000SEvgeniy Ivanov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2158a2b000SEvgeniy Ivanov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2258a2b000SEvgeniy Ivanov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2358a2b000SEvgeniy Ivanov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2458a2b000SEvgeniy Ivanov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2558a2b000SEvgeniy Ivanov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2658a2b000SEvgeniy Ivanov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2758a2b000SEvgeniy Ivanov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2858a2b000SEvgeniy Ivanov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2958a2b000SEvgeniy Ivanov  * SUCH DAMAGE.
3058a2b000SEvgeniy Ivanov  *
3158a2b000SEvgeniy Ivanov  *	@(#)printf.c	8.1 (Berkeley) 6/11/93
3258a2b000SEvgeniy Ivanov  */
3358a2b000SEvgeniy Ivanov 
3458a2b000SEvgeniy Ivanov /*
3558a2b000SEvgeniy Ivanov  * Scaled down version of printf(3).
3658a2b000SEvgeniy Ivanov  */
3758a2b000SEvgeniy Ivanov 
3858a2b000SEvgeniy Ivanov #include <sys/cdefs.h>
3958a2b000SEvgeniy Ivanov #include <sys/types.h>
4058a2b000SEvgeniy Ivanov #include <sys/stdint.h>		/* XXX: for intptr_t */
4158a2b000SEvgeniy Ivanov 
4258a2b000SEvgeniy Ivanov #include "stand.h"
4358a2b000SEvgeniy Ivanov 
4458a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
4558a2b000SEvgeniy Ivanov #define INTMAX_T	longlong_t
4658a2b000SEvgeniy Ivanov #define UINTMAX_T	u_longlong_t
4758a2b000SEvgeniy Ivanov #else
4858a2b000SEvgeniy Ivanov #define INTMAX_T	long
4958a2b000SEvgeniy Ivanov #define UINTMAX_T	u_long
5058a2b000SEvgeniy Ivanov #endif
5158a2b000SEvgeniy Ivanov 
5258a2b000SEvgeniy Ivanov #if 0 /* XXX: abuse intptr_t until the situation with ptrdiff_t is clear */
5358a2b000SEvgeniy Ivanov #define PTRDIFF_T	ptrdiff_t
5458a2b000SEvgeniy Ivanov #else
5558a2b000SEvgeniy Ivanov #define PTRDIFF_T	intptr_t
5658a2b000SEvgeniy Ivanov #endif
5758a2b000SEvgeniy Ivanov 
5858a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
5958a2b000SEvgeniy Ivanov static void kprintn(void (*)(int), UINTMAX_T, int, int, int);
6058a2b000SEvgeniy Ivanov #else
6158a2b000SEvgeniy Ivanov static void kprintn(void (*)(int), UINTMAX_T, int);
6258a2b000SEvgeniy Ivanov #endif
6358a2b000SEvgeniy Ivanov static void sputchar(int);
6458a2b000SEvgeniy Ivanov static void kdoprnt(void (*)(int), const char *, va_list);
6558a2b000SEvgeniy Ivanov 
6658a2b000SEvgeniy Ivanov static char *sbuf, *ebuf;
6751b1cfd6SKees Jongenburger #if defined(__minix)
6851b1cfd6SKees Jongenburger /* vsnprintf: add support for returning the amount of characters that would have been
6951b1cfd6SKees Jongenburger  * written if the buffer was large enough */
7051b1cfd6SKees Jongenburger static int  scount;
7151b1cfd6SKees Jongenburger #endif /* defined(__minix) */
7258a2b000SEvgeniy Ivanov 
7358a2b000SEvgeniy Ivanov const char hexdigits[16] = "0123456789abcdef";
7458a2b000SEvgeniy Ivanov 
7558a2b000SEvgeniy Ivanov #define LONG		0x01
7658a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
7758a2b000SEvgeniy Ivanov #define LLONG		0x02
7858a2b000SEvgeniy Ivanov #endif
7984d9c625SLionel Sambuc 
8084d9c625SLionel Sambuc #if defined(__minix)
8184d9c625SLionel Sambuc #define HEXCAP		0x100
8284d9c625SLionel Sambuc #endif /* defined(__minix) */
8384d9c625SLionel Sambuc 
8458a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
8558a2b000SEvgeniy Ivanov #define ALT		0x04
8658a2b000SEvgeniy Ivanov #define SPACE		0x08
8758a2b000SEvgeniy Ivanov #define LADJUST		0x10
8858a2b000SEvgeniy Ivanov #define SIGN		0x20
8958a2b000SEvgeniy Ivanov #define ZEROPAD		0x40
9058a2b000SEvgeniy Ivanov #define NEGATIVE	0x80
9158a2b000SEvgeniy Ivanov #define KPRINTN(base)	kprintn(put, ul, base, lflag, width)
92*0a6a1f1dSLionel Sambuc #define RADJUSTZEROPAD()					\
9358a2b000SEvgeniy Ivanov do {								\
9458a2b000SEvgeniy Ivanov 	if ((lflag & (ZEROPAD|LADJUST)) == ZEROPAD) {		\
9558a2b000SEvgeniy Ivanov 		while (width-- > 0)				\
9658a2b000SEvgeniy Ivanov 			put('0');				\
9758a2b000SEvgeniy Ivanov 	}							\
9858a2b000SEvgeniy Ivanov } while (/*CONSTCOND*/0)
99*0a6a1f1dSLionel Sambuc #define LADJUSTPAD()						\
10058a2b000SEvgeniy Ivanov do {								\
10158a2b000SEvgeniy Ivanov 	if (lflag & LADJUST) {					\
10258a2b000SEvgeniy Ivanov 		while (width-- > 0)				\
10358a2b000SEvgeniy Ivanov 			put(' ');				\
10458a2b000SEvgeniy Ivanov 	}							\
10558a2b000SEvgeniy Ivanov } while (/*CONSTCOND*/0)
106*0a6a1f1dSLionel Sambuc #define RADJUSTPAD()						\
10758a2b000SEvgeniy Ivanov do {								\
10858a2b000SEvgeniy Ivanov 	if ((lflag & (ZEROPAD|LADJUST)) == 0) {			\
10958a2b000SEvgeniy Ivanov 		while (width-- > 0)				\
11058a2b000SEvgeniy Ivanov 			put(' ');				\
11158a2b000SEvgeniy Ivanov 	}							\
11258a2b000SEvgeniy Ivanov } while (/*CONSTCOND*/0)
11358a2b000SEvgeniy Ivanov #else	/* LIBSA_PRINTF_WIDTH_SUPPORT */
11458a2b000SEvgeniy Ivanov #define KPRINTN(base)	kprintn(put, ul, base)
115*0a6a1f1dSLionel Sambuc #define RADJUSTZEROPAD()	/**/
116*0a6a1f1dSLionel Sambuc #define LADJUSTPAD()		/**/
117*0a6a1f1dSLionel Sambuc #define RADJUSTPAD()		/**/
11858a2b000SEvgeniy Ivanov #endif	/* LIBSA_PRINTF_WIDTH_SUPPORT */
11958a2b000SEvgeniy Ivanov 
12058a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
12158a2b000SEvgeniy Ivanov #define KPRINT(base)						\
12258a2b000SEvgeniy Ivanov do {								\
12358a2b000SEvgeniy Ivanov 	ul = (lflag & LLONG)					\
12458a2b000SEvgeniy Ivanov 	    ? va_arg(ap, u_longlong_t)				\
12558a2b000SEvgeniy Ivanov 	    : (lflag & LONG)					\
12658a2b000SEvgeniy Ivanov 		? va_arg(ap, u_long)				\
12758a2b000SEvgeniy Ivanov 		: va_arg(ap, u_int);				\
12858a2b000SEvgeniy Ivanov 	KPRINTN(base);						\
12958a2b000SEvgeniy Ivanov } while (/*CONSTCOND*/0)
13058a2b000SEvgeniy Ivanov #else	/* LIBSA_PRINTF_LONGLONG_SUPPORT */
13158a2b000SEvgeniy Ivanov #define KPRINT(base)						\
13258a2b000SEvgeniy Ivanov do {								\
13358a2b000SEvgeniy Ivanov 	ul = (lflag & LONG)					\
13458a2b000SEvgeniy Ivanov 	    ? va_arg(ap, u_long) : va_arg(ap, u_int);		\
13558a2b000SEvgeniy Ivanov 	KPRINTN(base);						\
13658a2b000SEvgeniy Ivanov } while (/*CONSTCOND*/0)
13758a2b000SEvgeniy Ivanov #endif	/* LIBSA_PRINTF_LONGLONG_SUPPORT */
13858a2b000SEvgeniy Ivanov 
13958a2b000SEvgeniy Ivanov static void
sputchar(int c)14058a2b000SEvgeniy Ivanov sputchar(int c)
14158a2b000SEvgeniy Ivanov {
14251b1cfd6SKees Jongenburger #if defined(__minix)
14351b1cfd6SKees Jongenburger 	scount++; /* increase scount regardless */
14451b1cfd6SKees Jongenburger 	if (!sbuf) return; /* hanlde NULL sbuf  */
14551b1cfd6SKees Jongenburger #endif /* defined(__minix) */
146*0a6a1f1dSLionel Sambuc 
14758a2b000SEvgeniy Ivanov 	if (sbuf < ebuf)
14858a2b000SEvgeniy Ivanov 		*sbuf++ = c;
14958a2b000SEvgeniy Ivanov }
15058a2b000SEvgeniy Ivanov 
15158a2b000SEvgeniy Ivanov void
vprintf(const char * fmt,va_list ap)15258a2b000SEvgeniy Ivanov vprintf(const char *fmt, va_list ap)
15358a2b000SEvgeniy Ivanov {
15458a2b000SEvgeniy Ivanov 
15558a2b000SEvgeniy Ivanov 	kdoprnt(putchar, fmt, ap);
15684d9c625SLionel Sambuc #if defined(__minix) && defined(LIBSA_PRINTF_WIDTH_SUPPORT)
15784d9c625SLionel Sambuc 	/* BJG: our libminc kputc() relies on a 0 to flush the diag buffer. */
15884d9c625SLionel Sambuc 	putchar(0);
15984d9c625SLionel Sambuc #endif /* defined(__minix) && defined(LIBSA_PRINTF_WIDTH_SUPPORT) */
16058a2b000SEvgeniy Ivanov }
16158a2b000SEvgeniy Ivanov 
16258a2b000SEvgeniy Ivanov int
vsnprintf(char * buf,size_t size,const char * fmt,va_list ap)16358a2b000SEvgeniy Ivanov vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
16458a2b000SEvgeniy Ivanov {
16558a2b000SEvgeniy Ivanov 
16658a2b000SEvgeniy Ivanov 	sbuf = buf;
16758a2b000SEvgeniy Ivanov 	ebuf = buf + size - 1;
16851b1cfd6SKees Jongenburger #if defined(__minix)
16951b1cfd6SKees Jongenburger 	scount = 0; /* use scount to keep track of written items */
17051b1cfd6SKees Jongenburger #endif /* defined(__minix) */
17151b1cfd6SKees Jongenburger 
17258a2b000SEvgeniy Ivanov 	kdoprnt(sputchar, fmt, ap);
17351b1cfd6SKees Jongenburger 
17451b1cfd6SKees Jongenburger #if defined(__minix)
17551b1cfd6SKees Jongenburger 	if (sbuf){ /* handle case where sbuf == NULL */
17651b1cfd6SKees Jongenburger 		*sbuf = '\0';
17751b1cfd6SKees Jongenburger 	}
178129adfebSDavid van Moolenbroek #if defined(_MINIX_MAGIC)
179129adfebSDavid van Moolenbroek 	sbuf = ebuf = NULL; /* leave no dangling pointers */
180129adfebSDavid van Moolenbroek #endif
18151b1cfd6SKees Jongenburger 	return scount;
18251b1cfd6SKees Jongenburger #else /* __minix is not defined */
18358a2b000SEvgeniy Ivanov 	*sbuf = '\0';
18458a2b000SEvgeniy Ivanov 	return sbuf - buf;
18551b1cfd6SKees Jongenburger #endif  /* defined(__minix) */
18658a2b000SEvgeniy Ivanov }
18758a2b000SEvgeniy Ivanov 
18858a2b000SEvgeniy Ivanov static void
kdoprnt(void (* put)(int),const char * fmt,va_list ap)18958a2b000SEvgeniy Ivanov kdoprnt(void (*put)(int), const char *fmt, va_list ap)
19058a2b000SEvgeniy Ivanov {
19158a2b000SEvgeniy Ivanov 	char *p;
19258a2b000SEvgeniy Ivanov 	int ch;
19358a2b000SEvgeniy Ivanov 	UINTMAX_T ul;
19458a2b000SEvgeniy Ivanov 	int lflag;
19558a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
19658a2b000SEvgeniy Ivanov 	int width;
19758a2b000SEvgeniy Ivanov 	char *q;
1983814aed5SDavid van Moolenbroek #if defined(__minix)
1993814aed5SDavid van Moolenbroek 	int max;
2003814aed5SDavid van Moolenbroek #endif /* defined(__minix) */
20158a2b000SEvgeniy Ivanov #endif
20258a2b000SEvgeniy Ivanov 
20358a2b000SEvgeniy Ivanov 	for (;;) {
20458a2b000SEvgeniy Ivanov 		while ((ch = *fmt++) != '%') {
20558a2b000SEvgeniy Ivanov 			if (ch == '\0')
20658a2b000SEvgeniy Ivanov 				return;
20758a2b000SEvgeniy Ivanov 			put(ch);
20858a2b000SEvgeniy Ivanov 		}
20958a2b000SEvgeniy Ivanov 		lflag = 0;
21058a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
21158a2b000SEvgeniy Ivanov 		width = 0;
2123814aed5SDavid van Moolenbroek #if defined(__minix)
2133814aed5SDavid van Moolenbroek 		max = -1;
2143814aed5SDavid van Moolenbroek #endif /* defined(__minix) */
21558a2b000SEvgeniy Ivanov #endif
21658a2b000SEvgeniy Ivanov reswitch:
21758a2b000SEvgeniy Ivanov 		switch (ch = *fmt++) {
21858a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
21984d9c625SLionel Sambuc #if defined(__minix)
22084d9c625SLionel Sambuc 		case '.':
2213814aed5SDavid van Moolenbroek 			if (*fmt == '*') {
2223814aed5SDavid van Moolenbroek 				max = va_arg(ap, int);
22384d9c625SLionel Sambuc 				fmt++;
2243814aed5SDavid van Moolenbroek 			} else for (max = 0; *fmt >= '0' && *fmt <= '9'; fmt++)
2253814aed5SDavid van Moolenbroek 				max = max * 10 + *fmt - '0';
22684d9c625SLionel Sambuc 			goto reswitch;
22784d9c625SLionel Sambuc #endif /* defined(__minix) */
22858a2b000SEvgeniy Ivanov 		case '#':
22958a2b000SEvgeniy Ivanov 			lflag |= ALT;
23058a2b000SEvgeniy Ivanov 			goto reswitch;
23158a2b000SEvgeniy Ivanov 		case ' ':
23258a2b000SEvgeniy Ivanov 			lflag |= SPACE;
23358a2b000SEvgeniy Ivanov 			goto reswitch;
23458a2b000SEvgeniy Ivanov 		case '-':
23558a2b000SEvgeniy Ivanov 			lflag |= LADJUST;
23658a2b000SEvgeniy Ivanov 			goto reswitch;
23758a2b000SEvgeniy Ivanov 		case '+':
23858a2b000SEvgeniy Ivanov 			lflag |= SIGN;
23958a2b000SEvgeniy Ivanov 			goto reswitch;
24058a2b000SEvgeniy Ivanov 		case '0':
24158a2b000SEvgeniy Ivanov 			lflag |= ZEROPAD;
24258a2b000SEvgeniy Ivanov 			goto reswitch;
24358a2b000SEvgeniy Ivanov 		case '1': case '2': case '3': case '4': case '5':
24458a2b000SEvgeniy Ivanov 		case '6': case '7': case '8': case '9':
24558a2b000SEvgeniy Ivanov 			for (;;) {
24658a2b000SEvgeniy Ivanov 				width *= 10;
24758a2b000SEvgeniy Ivanov 				width += ch - '0';
24858a2b000SEvgeniy Ivanov 				ch = *fmt;
24958a2b000SEvgeniy Ivanov 				if ((unsigned)ch - '0' > 9)
25058a2b000SEvgeniy Ivanov 					break;
25158a2b000SEvgeniy Ivanov 				++fmt;
25258a2b000SEvgeniy Ivanov 			}
25358a2b000SEvgeniy Ivanov #endif
25458a2b000SEvgeniy Ivanov 			goto reswitch;
25558a2b000SEvgeniy Ivanov 		case 'l':
25658a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
25758a2b000SEvgeniy Ivanov 			if (*fmt == 'l') {
25858a2b000SEvgeniy Ivanov 				++fmt;
25958a2b000SEvgeniy Ivanov 				lflag |= LLONG;
26058a2b000SEvgeniy Ivanov 			} else
26158a2b000SEvgeniy Ivanov #endif
26258a2b000SEvgeniy Ivanov 				lflag |= LONG;
26358a2b000SEvgeniy Ivanov 			goto reswitch;
264*0a6a1f1dSLionel Sambuc 		case 'j':
265*0a6a1f1dSLionel Sambuc #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
266*0a6a1f1dSLionel Sambuc 			if (sizeof(intmax_t) == sizeof(long long))
267*0a6a1f1dSLionel Sambuc 				lflag |= LLONG;
268*0a6a1f1dSLionel Sambuc 			else
269*0a6a1f1dSLionel Sambuc #endif
270*0a6a1f1dSLionel Sambuc 			if (sizeof(intmax_t) == sizeof(long))
271*0a6a1f1dSLionel Sambuc 				lflag |= LONG;
272*0a6a1f1dSLionel Sambuc 			goto reswitch;
27358a2b000SEvgeniy Ivanov 		case 't':
27458a2b000SEvgeniy Ivanov 			if (sizeof(PTRDIFF_T) == sizeof(long))
27558a2b000SEvgeniy Ivanov 				lflag |= LONG;
27658a2b000SEvgeniy Ivanov 			goto reswitch;
27758a2b000SEvgeniy Ivanov 		case 'z':
27858a2b000SEvgeniy Ivanov 			if (sizeof(ssize_t) == sizeof(long))
27958a2b000SEvgeniy Ivanov 				lflag |= LONG;
28058a2b000SEvgeniy Ivanov 			goto reswitch;
28158a2b000SEvgeniy Ivanov 		case 'c':
28258a2b000SEvgeniy Ivanov 			ch = va_arg(ap, int);
28358a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
28458a2b000SEvgeniy Ivanov 			--width;
28558a2b000SEvgeniy Ivanov #endif
286*0a6a1f1dSLionel Sambuc 			RADJUSTPAD();
28758a2b000SEvgeniy Ivanov 			put(ch & 0xFF);
288*0a6a1f1dSLionel Sambuc 			LADJUSTPAD();
28958a2b000SEvgeniy Ivanov 			break;
29058a2b000SEvgeniy Ivanov 		case 's':
29158a2b000SEvgeniy Ivanov 			p = va_arg(ap, char *);
29258a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
29358a2b000SEvgeniy Ivanov 			for (q = p; *q != '\0'; ++q)
29458a2b000SEvgeniy Ivanov 				continue;
2953814aed5SDavid van Moolenbroek #if defined(__minix)
2963814aed5SDavid van Moolenbroek 			if (max >= 0 && q - p > max)
2973814aed5SDavid van Moolenbroek 				q = &p[max];
2983814aed5SDavid van Moolenbroek #endif /* defined(__minix) */
29958a2b000SEvgeniy Ivanov 			width -= q - p;
30058a2b000SEvgeniy Ivanov #endif
301*0a6a1f1dSLionel Sambuc 			RADJUSTPAD();
3023814aed5SDavid van Moolenbroek #if defined(LIBSA_PRINTF_WIDTH_SUPPORT) && defined(__minix)
3033814aed5SDavid van Moolenbroek 			while ((max < 0 || max-- > 0) &&
3043814aed5SDavid van Moolenbroek 			    (ch = (unsigned char)*p++))
3053814aed5SDavid van Moolenbroek #else /* !defined(LIBSA_PRINTF_WIDTH_SUPPORT) || !defined(__minix) */
30658a2b000SEvgeniy Ivanov 			while ((ch = (unsigned char)*p++))
3073814aed5SDavid van Moolenbroek #endif /* !defined(LIBSA_PRINTF_WIDTH_SUPPORT) || !defined(__minix) */
30858a2b000SEvgeniy Ivanov 				put(ch);
309*0a6a1f1dSLionel Sambuc 			LADJUSTPAD();
31058a2b000SEvgeniy Ivanov 			break;
31158a2b000SEvgeniy Ivanov 		case 'd':
31258a2b000SEvgeniy Ivanov 			ul =
31358a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
31458a2b000SEvgeniy Ivanov 			(lflag & LLONG) ? va_arg(ap, longlong_t) :
31558a2b000SEvgeniy Ivanov #endif
31658a2b000SEvgeniy Ivanov 			(lflag & LONG) ? va_arg(ap, long) : va_arg(ap, int);
31758a2b000SEvgeniy Ivanov 			if ((INTMAX_T)ul < 0) {
31858a2b000SEvgeniy Ivanov 				ul = -(INTMAX_T)ul;
31958a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
32058a2b000SEvgeniy Ivanov 				lflag |= NEGATIVE;
32158a2b000SEvgeniy Ivanov #else
32258a2b000SEvgeniy Ivanov 				put('-');
32358a2b000SEvgeniy Ivanov #endif
32458a2b000SEvgeniy Ivanov 			}
32558a2b000SEvgeniy Ivanov 			KPRINTN(10);
32658a2b000SEvgeniy Ivanov 			break;
32758a2b000SEvgeniy Ivanov 		case 'o':
32858a2b000SEvgeniy Ivanov 			KPRINT(8);
32958a2b000SEvgeniy Ivanov 			break;
33058a2b000SEvgeniy Ivanov 		case 'u':
33158a2b000SEvgeniy Ivanov 			KPRINT(10);
33258a2b000SEvgeniy Ivanov 			break;
33358a2b000SEvgeniy Ivanov 		case 'p':
33458a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
33558a2b000SEvgeniy Ivanov 			lflag |= (LONG|ALT);
33658a2b000SEvgeniy Ivanov #else
33758a2b000SEvgeniy Ivanov 			put('0');
33858a2b000SEvgeniy Ivanov 			put('x');
33958a2b000SEvgeniy Ivanov #endif
34058a2b000SEvgeniy Ivanov 			/* FALLTHROUGH */
34158a2b000SEvgeniy Ivanov 		case 'x':
34258a2b000SEvgeniy Ivanov 			KPRINT(16);
34358a2b000SEvgeniy Ivanov 			break;
34484d9c625SLionel Sambuc #if defined(__minix)
34584d9c625SLionel Sambuc 		case 'X':
34684d9c625SLionel Sambuc 			lflag |= HEXCAP;
34784d9c625SLionel Sambuc 			KPRINT(16);
34884d9c625SLionel Sambuc 			break;
34984d9c625SLionel Sambuc #endif /* defined(__minix) */
35058a2b000SEvgeniy Ivanov 		default:
35158a2b000SEvgeniy Ivanov 			if (ch == '\0')
35258a2b000SEvgeniy Ivanov 				return;
35358a2b000SEvgeniy Ivanov 			put(ch);
35458a2b000SEvgeniy Ivanov 			break;
35558a2b000SEvgeniy Ivanov 		}
35658a2b000SEvgeniy Ivanov 	}
35758a2b000SEvgeniy Ivanov }
35858a2b000SEvgeniy Ivanov 
35958a2b000SEvgeniy Ivanov static void
36058a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
kprintn(void (* put)(int),UINTMAX_T ul,int base,int lflag,int width)36158a2b000SEvgeniy Ivanov kprintn(void (*put)(int), UINTMAX_T ul, int base, int lflag, int width)
36258a2b000SEvgeniy Ivanov #else
36358a2b000SEvgeniy Ivanov kprintn(void (*put)(int), UINTMAX_T ul, int base)
36458a2b000SEvgeniy Ivanov #endif
36558a2b000SEvgeniy Ivanov {
36658a2b000SEvgeniy Ivanov 					/* hold a INTMAX_T in base 8 */
36758a2b000SEvgeniy Ivanov 	char *p, buf[(sizeof(INTMAX_T) * NBBY / 3) + 1 + 2 /* ALT + SIGN */];
36858a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
36958a2b000SEvgeniy Ivanov 	char *q;
37058a2b000SEvgeniy Ivanov #endif
37158a2b000SEvgeniy Ivanov 
37258a2b000SEvgeniy Ivanov 	p = buf;
37358a2b000SEvgeniy Ivanov 	do {
37458a2b000SEvgeniy Ivanov 		*p++ = hexdigits[ul % base];
37584d9c625SLionel Sambuc #if defined(__minix)
37684d9c625SLionel Sambuc #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
37784d9c625SLionel Sambuc 		/* LSC: Quick hack to support capital hex printout. */
37884d9c625SLionel Sambuc 		if ((lflag & HEXCAP) && (*(p-1) >= 'a') && (*(p-1) <= 'z')) {
37984d9c625SLionel Sambuc 			*(p-1) -= 32;
38084d9c625SLionel Sambuc 		}
38184d9c625SLionel Sambuc #endif
38284d9c625SLionel Sambuc #endif /* defined(__minix) */
38358a2b000SEvgeniy Ivanov 	} while (ul /= base);
38458a2b000SEvgeniy Ivanov #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
38558a2b000SEvgeniy Ivanov 	q = p;
38658a2b000SEvgeniy Ivanov 	if (lflag & ALT && *(p - 1) != '0') {
38758a2b000SEvgeniy Ivanov 		if (base == 8) {
38858a2b000SEvgeniy Ivanov 			*p++ = '0';
38958a2b000SEvgeniy Ivanov 		} else if (base == 16) {
39058a2b000SEvgeniy Ivanov 			*p++ = 'x';
39158a2b000SEvgeniy Ivanov 			*p++ = '0';
39258a2b000SEvgeniy Ivanov 		}
39358a2b000SEvgeniy Ivanov 	}
39458a2b000SEvgeniy Ivanov 	if (lflag & NEGATIVE)
39558a2b000SEvgeniy Ivanov 		*p++ = '-';
39658a2b000SEvgeniy Ivanov 	else if (lflag & SIGN)
39758a2b000SEvgeniy Ivanov 		*p++ = '+';
39858a2b000SEvgeniy Ivanov 	else if (lflag & SPACE)
39958a2b000SEvgeniy Ivanov 		*p++ = ' ';
40058a2b000SEvgeniy Ivanov 	width -= p - buf;
401*0a6a1f1dSLionel Sambuc 	if (lflag & ZEROPAD) {
40258a2b000SEvgeniy Ivanov 		while (p > q)
40358a2b000SEvgeniy Ivanov 			put(*--p);
40458a2b000SEvgeniy Ivanov 	}
40558a2b000SEvgeniy Ivanov #endif
406*0a6a1f1dSLionel Sambuc 	RADJUSTPAD();
407*0a6a1f1dSLionel Sambuc 	RADJUSTZEROPAD();
40858a2b000SEvgeniy Ivanov 	do {
40958a2b000SEvgeniy Ivanov 		put(*--p);
41058a2b000SEvgeniy Ivanov 	} while (p > buf);
411*0a6a1f1dSLionel Sambuc 	LADJUSTPAD();
41258a2b000SEvgeniy Ivanov }
413