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