1335c4bemsmith/*-
2335c4bemsmith * Copyright (c) 1986, 1988, 1991, 1993
3335c4bemsmith *	The Regents of the University of California.  All rights reserved.
4335c4bemsmith * (c) UNIX System Laboratories, Inc.
5335c4bemsmith * All or some portions of this file are derived from material licensed
6335c4bemsmith * to the University of California by American Telephone and Telegraph
7335c4bemsmith * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8335c4bemsmith * the permission of UNIX System Laboratories, Inc.
9335c4bemsmith *
10335c4bemsmith * Redistribution and use in source and binary forms, with or without
11335c4bemsmith * modification, are permitted provided that the following conditions
12335c4bemsmith * are met:
13335c4bemsmith * 1. Redistributions of source code must retain the above copyright
14335c4bemsmith *    notice, this list of conditions and the following disclaimer.
15335c4bemsmith * 2. Redistributions in binary form must reproduce the above copyright
16335c4bemsmith *    notice, this list of conditions and the following disclaimer in the
17335c4bemsmith *    documentation and/or other materials provided with the distribution.
187e6cabdimp * 3. Neither the name of the University nor the names of its contributors
19335c4bemsmith *    may be used to endorse or promote products derived from this software
20335c4bemsmith *    without specific prior written permission.
21335c4bemsmith *
22335c4bemsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23335c4bemsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24335c4bemsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25335c4bemsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26335c4bemsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27335c4bemsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28335c4bemsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29335c4bemsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30335c4bemsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31335c4bemsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32335c4bemsmith * SUCH DAMAGE.
33335c4bemsmith *
34335c4bemsmith *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
35335c4bemsmith */
36335c4bemsmith
37f6666a6dillon#include <sys/cdefs.h>
38f6666a6dillon__FBSDID("$FreeBSD$");
39f6666a6dillon
40335c4bemsmith/*
41335c4bemsmith * Standaloneified version of the FreeBSD kernel printf family.
42335c4bemsmith */
43335c4bemsmith
44335c4bemsmith#include <sys/types.h>
45a3ab268peter#include <sys/stddef.h>
46a3ab268peter#include <sys/stdint.h>
4786a758emike#include <limits.h>
48070fb07peter#include <string.h>
49335c4bemsmith#include "stand.h"
50335c4bemsmith
51335c4bemsmith/*
52335c4bemsmith * Note that stdarg.h and the ANSI style va_start macro is used for both
53335c4bemsmith * ANSI and traditional C compilers.
54335c4bemsmith */
55335c4bemsmith#include <machine/stdarg.h>
56335c4bemsmith
57a3ab268peter#define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1)
58a3ab268peter
596b258c1hselaskytypedef void (kvprintf_fn_t)(int, void *);
606b258c1hselasky
617e4fc3bjkimstatic char	*ksprintn (char *buf, uintmax_t num, int base, int *len, int upper);
626b258c1hselaskystatic int	kvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap);
636b258c1hselasky
646b258c1hselaskystatic void
656b258c1hselaskyputchar_wrapper(int cc, void *arg)
666b258c1hselasky{
674c1dfc8hselasky
686b258c1hselasky	putchar(cc);
696b258c1hselasky}
70335c4bemsmith
71335c4bemsmithint
72335c4bemsmithprintf(const char *fmt, ...)
73335c4bemsmith{
74335c4bemsmith	va_list ap;
75335c4bemsmith	int retval;
76335c4bemsmith
77335c4bemsmith	va_start(ap, fmt);
786b258c1hselasky	retval = kvprintf(fmt, putchar_wrapper, NULL, 10, ap);
79335c4bemsmith	va_end(ap);
80335c4bemsmith	return retval;
81335c4bemsmith}
82335c4bemsmith
8398ec7f9ianint
84335c4bemsmithvprintf(const char *fmt, va_list ap)
85335c4bemsmith{
864c1dfc8hselasky
8798ec7f9ian	return (kvprintf(fmt, putchar_wrapper, NULL, 10, ap));
88335c4bemsmith}
89335c4bemsmith
90335c4bemsmithint
91335c4bemsmithsprintf(char *buf, const char *cfmt, ...)
92335c4bemsmith{
93335c4bemsmith	int retval;
94335c4bemsmith	va_list ap;
95335c4bemsmith
96335c4bemsmith	va_start(ap, cfmt);
97335c4bemsmith	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
98335c4bemsmith	buf[retval] = '\0';
99335c4bemsmith	va_end(ap);
100335c4bemsmith	return retval;
101335c4bemsmith}
102335c4bemsmith
1036b258c1hselaskystruct print_buf {
1046b258c1hselasky	char *buf;
1056b258c1hselasky	size_t size;
1066b258c1hselasky};
1076b258c1hselasky
1086b258c1hselaskystatic void
1096b258c1hselaskysnprint_func(int ch, void *arg)
1106b258c1hselasky{
1116b258c1hselasky	struct print_buf *pbuf = arg;
1126b258c1hselasky
1136b258c1hselasky	if (pbuf->size < 2) {
1146b258c1hselasky		/*
1156b258c1hselasky		 * Reserve last buffer position for the terminating
1166b258c1hselasky		 * character:
1176b258c1hselasky		 */
1186b258c1hselasky		return;
1196b258c1hselasky	}
1206b258c1hselasky	*(pbuf->buf)++ = ch;
1216b258c1hselasky	pbuf->size--;
1226b258c1hselasky}
1236b258c1hselasky
1246b258c1hselaskyint
125e9b9f14tsoomeasprintf(char **buf, const char *cfmt, ...)
126e9b9f14tsoome{
127e9b9f14tsoome	int retval;
128e9b9f14tsoome	struct print_buf arg;
129e9b9f14tsoome	va_list ap;
130e9b9f14tsoome
131e9b9f14tsoome	*buf = NULL;
132e9b9f14tsoome	va_start(ap, cfmt);
133e9b9f14tsoome	retval = kvprintf(cfmt, NULL, NULL, 10, ap);
134e9b9f14tsoome	va_end(ap);
135e9b9f14tsoome	if (retval <= 0)
136e9b9f14tsoome		return (-1);
137e9b9f14tsoome
138e9b9f14tsoome	arg.size = retval + 1;
139e9b9f14tsoome	arg.buf = *buf = malloc(arg.size);
140e9b9f14tsoome	if (*buf == NULL)
141e9b9f14tsoome		return (-1);
142e9b9f14tsoome
143e9b9f14tsoome	va_start(ap, cfmt);
144e9b9f14tsoome	retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap);
145e9b9f14tsoome	va_end(ap);
146e9b9f14tsoome
147e9b9f14tsoome	if (arg.size >= 1)
148e9b9f14tsoome		*(arg.buf)++ = 0;
149e9b9f14tsoome	return (retval);
150e9b9f14tsoome}
151e9b9f14tsoome
152e9b9f14tsoomeint
1536b258c1hselaskysnprintf(char *buf, size_t size, const char *cfmt, ...)
1546b258c1hselasky{
1556b258c1hselasky	int retval;
1566b258c1hselasky	va_list ap;
1576b258c1hselasky	struct print_buf arg;
1586b258c1hselasky
1596b258c1hselasky	arg.buf = buf;
1606b258c1hselasky	arg.size = size;
1616b258c1hselasky
1626b258c1hselasky	va_start(ap, cfmt);
1636b258c1hselasky	retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap);
1646b258c1hselasky	va_end(ap);
1656b258c1hselasky
1666b258c1hselasky	if (arg.size >= 1)
1676b258c1hselasky		*(arg.buf)++ = 0;
1686b258c1hselasky	return retval;
1696b258c1hselasky}
1706b258c1hselasky
17198ec7f9ianint
172c5e6cf9ianvsnprintf(char *buf, size_t size, const char *cfmt, va_list ap)
173c5e6cf9ian{
174c5e6cf9ian	struct print_buf arg;
17598ec7f9ian	int retval;
176c5e6cf9ian
177c5e6cf9ian	arg.buf = buf;
178c5e6cf9ian	arg.size = size;
179c5e6cf9ian
18098ec7f9ian	retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap);
181c5e6cf9ian
182c5e6cf9ian	if (arg.size >= 1)
183c5e6cf9ian		*(arg.buf)++ = 0;
18498ec7f9ian
18598ec7f9ian	return (retval);
186c5e6cf9ian}
187c5e6cf9ian
18898ec7f9ianint
189f00eb1amsmithvsprintf(char *buf, const char *cfmt, va_list ap)
190f00eb1amsmith{
191f00eb1amsmith	int	retval;
192f00eb1amsmith
193f00eb1amsmith	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
194f00eb1amsmith	buf[retval] = '\0';
19598ec7f9ian
19698ec7f9ian	return (retval);
197f00eb1amsmith}
198f00eb1amsmith
199335c4bemsmith/*
200a3ab268peter * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
201a3ab268peter * order; return an optional length and a pointer to the last character
202a3ab268peter * written in the buffer (i.e., the first character of the string).
203a3ab268peter * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
204335c4bemsmith */
205335c4bemsmithstatic char *
2067e4fc3bjkimksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
207a3ab268peter{
2087e4fc3bjkim	char *p, c;
209335c4bemsmith
210a3ab268peter	p = nbuf;
211a3ab268peter	*p = '\0';
212335c4bemsmith	do {
2137e4fc3bjkim		c = hex2ascii(num % base);
2147e4fc3bjkim		*++p = upper ? toupper(c) : c;
215a3ab268peter	} while (num /= base);
216335c4bemsmith	if (lenp)
217a3ab268peter		*lenp = p - nbuf;
218335c4bemsmith	return (p);
219335c4bemsmith}
220335c4bemsmith
221335c4bemsmith/*
222335c4bemsmith * Scaled down version of printf(3).
223335c4bemsmith *
224335c4bemsmith * Two additional formats:
225335c4bemsmith *
226335c4bemsmith * The format %b is supported to decode error registers.
227335c4bemsmith * Its usage is:
228335c4bemsmith *
229335c4bemsmith *	printf("reg=%b\n", regval, "<base><arg>*");
230335c4bemsmith *
231335c4bemsmith * where <base> is the output base expressed as a control character, e.g.
232335c4bemsmith * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
233335c4bemsmith * the first of which gives the bit number to be inspected (origin 1), and
234335c4bemsmith * the next characters (up to a control character, i.e. a character <= 32),
235335c4bemsmith * give the name of the register.  Thus:
236335c4bemsmith *
237d20a416danfe *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE");
238335c4bemsmith *
239335c4bemsmith * would produce output:
240335c4bemsmith *
241335c4bemsmith *	reg=3<BITTWO,BITONE>
242335c4bemsmith *
243335c4bemsmith * XXX:  %D  -- Hexdump, takes pointer and separator string:
244335c4bemsmith *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
245335c4bemsmith *		("%*D", len, ptr, " " -> XX XX XX XX ...
246335c4bemsmith */
247335c4bemsmithstatic int
2486b258c1hselaskykvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap)
249335c4bemsmith{
2504e632cftsoome#define PCHAR(c) { \
2514e632cftsoome	int cc = (c);				\
2524e632cftsoome						\
2534e632cftsoome	if (func) {				\
2544e632cftsoome		(*func)(cc, arg);		\
2554e632cftsoome	} else if (d != NULL) {			\
2564e632cftsoome		*d++ = cc;			\
2574e632cftsoome	}					\
2584e632cftsoome	retval++;				\
2594e632cftsoome	}
2604e632cftsoome
261a3ab268peter	char nbuf[MAXNBUF];
262a3ab268peter	char *d;
263a3ab268peter	const char *p, *percent, *q;
264ad9174cimp	uint16_t *S;
265335c4bemsmith	u_char *up;
266335c4bemsmith	int ch, n;
267a3ab268peter	uintmax_t num;
268a3ab268peter	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
2690fac9c7jkim	int cflag, hflag, jflag, tflag, zflag;
2707e4fc3bjkim	int dwidth, upper;
271335c4bemsmith	char padc;
2720fac9c7jkim	int stop = 0, retval = 0;
273335c4bemsmith
274a3ab268peter	num = 0;
275335c4bemsmith	if (!func)
276335c4bemsmith		d = (char *) arg;
277335c4bemsmith	else
278335c4bemsmith		d = NULL;
279335c4bemsmith
280335c4bemsmith	if (fmt == NULL)
281335c4bemsmith		fmt = "(fmt null)\n";
282335c4bemsmith
283335c4bemsmith	if (radix < 2 || radix > 36)
284335c4bemsmith		radix = 10;
285335c4bemsmith
286335c4bemsmith	for (;;) {
287335c4bemsmith		padc = ' ';
288335c4bemsmith		width = 0;
2890fac9c7jkim		while ((ch = (u_char)*fmt++) != '%' || stop) {
290a3ab268peter			if (ch == '\0')
291a3ab268peter				return (retval);
292335c4bemsmith			PCHAR(ch);
293335c4bemsmith		}
294a3ab268peter		percent = fmt - 1;
295a3ab268peter		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
2967e4fc3bjkim		sign = 0; dot = 0; dwidth = 0; upper = 0;
2970fac9c7jkim		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
298335c4bemsmithreswitch:	switch (ch = (u_char)*fmt++) {
299335c4bemsmith		case '.':
300335c4bemsmith			dot = 1;
301335c4bemsmith			goto reswitch;
302335c4bemsmith		case '#':
303335c4bemsmith			sharpflag = 1;
304335c4bemsmith			goto reswitch;
305335c4bemsmith		case '+':
306335c4bemsmith			sign = 1;
307335c4bemsmith			goto reswitch;
308335c4bemsmith		case '-':
309335c4bemsmith			ladjust = 1;
310335c4bemsmith			goto reswitch;
311335c4bemsmith		case '%':
312335c4bemsmith			PCHAR(ch);
313335c4bemsmith			break;
314335c4bemsmith		case '*':
315335c4bemsmith			if (!dot) {
316335c4bemsmith				width = va_arg(ap, int);
317335c4bemsmith				if (width < 0) {
318335c4bemsmith					ladjust = !ladjust;
319335c4bemsmith					width = -width;
320335c4bemsmith				}
321335c4bemsmith			} else {
322335c4bemsmith				dwidth = va_arg(ap, int);
323335c4bemsmith			}
324335c4bemsmith			goto reswitch;
325335c4bemsmith		case '0':
326335c4bemsmith			if (!dot) {
327335c4bemsmith				padc = '0';
328335c4bemsmith				goto reswitch;
329335c4bemsmith			}
330335c4bemsmith		case '1': case '2': case '3': case '4':
331335c4bemsmith		case '5': case '6': case '7': case '8': case '9':
332335c4bemsmith				for (n = 0;; ++fmt) {
333335c4bemsmith					n = n * 10 + ch - '0';
334335c4bemsmith					ch = *fmt;
335335c4bemsmith					if (ch < '0' || ch > '9')
336335c4bemsmith						break;
337335c4bemsmith				}
338335c4bemsmith			if (dot)
339335c4bemsmith				dwidth = n;
340335c4bemsmith			else
341335c4bemsmith				width = n;
342335c4bemsmith			goto reswitch;
343335c4bemsmith		case 'b':
3440fac9c7jkim			num = (u_int)va_arg(ap, int);
345335c4bemsmith			p = va_arg(ap, char *);
3467e4fc3bjkim			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
347335c4bemsmith				PCHAR(*q--);
348335c4bemsmith
349a3ab268peter			if (num == 0)
350335c4bemsmith				break;
351335c4bemsmith
352335c4bemsmith			for (tmp = 0; *p;) {
353335c4bemsmith				n = *p++;
354a3ab268peter				if (num & (1 << (n - 1))) {
355335c4bemsmith					PCHAR(tmp ? ',' : '<');
356335c4bemsmith					for (; (n = *p) > ' '; ++p)
357335c4bemsmith						PCHAR(n);
358335c4bemsmith					tmp = 1;
359335c4bemsmith				} else
360335c4bemsmith					for (; *p > ' '; ++p)
361335c4bemsmith						continue;
362335c4bemsmith			}
363335c4bemsmith			if (tmp)
364335c4bemsmith				PCHAR('>');
365335c4bemsmith			break;
366335c4bemsmith		case 'c':
367335c4bemsmith			PCHAR(va_arg(ap, int));
368335c4bemsmith			break;
369335c4bemsmith		case 'D':
370335c4bemsmith			up = va_arg(ap, u_char *);
371335c4bemsmith			p = va_arg(ap, char *);
372335c4bemsmith			if (!width)
373335c4bemsmith				width = 16;
374335c4bemsmith			while(width--) {
375335c4bemsmith				PCHAR(hex2ascii(*up >> 4));
376335c4bemsmith				PCHAR(hex2ascii(*up & 0x0f));
377335c4bemsmith				up++;
378335c4bemsmith				if (width)
379335c4bemsmith					for (q=p;*q;q++)
380335c4bemsmith						PCHAR(*q);
381335c4bemsmith			}
382335c4bemsmith			break;
383335c4bemsmith		case 'd':
384a3ab268peter		case 'i':
385335c4bemsmith			base = 10;
386a3ab268peter			sign = 1;
387a3ab268peter			goto handle_sign;
3880fac9c7jkim		case 'h':
3890fac9c7jkim			if (hflag) {
3900fac9c7jkim				hflag = 0;
3910fac9c7jkim				cflag = 1;
3920fac9c7jkim			} else
3930fac9c7jkim				hflag = 1;
3940fac9c7jkim			goto reswitch;
395a3ab268peter		case 'j':
396a3ab268peter			jflag = 1;
397a3ab268peter			goto reswitch;
398335c4bemsmith		case 'l':
399a3ab268peter			if (lflag) {
400a3ab268peter				lflag = 0;
401a3ab268peter				qflag = 1;
402a3ab268peter			} else
403a3ab268peter				lflag = 1;
404335c4bemsmith			goto reswitch;
405335c4bemsmith		case 'n':
406a3ab268peter			if (jflag)
407a3ab268peter				*(va_arg(ap, intmax_t *)) = retval;
408a3ab268peter			else if (qflag)
409a3ab268peter				*(va_arg(ap, quad_t *)) = retval;
410a3ab268peter			else if (lflag)
411a3ab268peter				*(va_arg(ap, long *)) = retval;
412a3ab268peter			else if (zflag)
413a3ab268peter				*(va_arg(ap, size_t *)) = retval;
4140fac9c7jkim			else if (hflag)
4150fac9c7jkim				*(va_arg(ap, short *)) = retval;
4160fac9c7jkim			else if (cflag)
4170fac9c7jkim				*(va_arg(ap, char *)) = retval;
418a3ab268peter			else
419a3ab268peter				*(va_arg(ap, int *)) = retval;
420a3ab268peter			break;
421335c4bemsmith		case 'o':
422335c4bemsmith			base = 8;
423a3ab268peter			goto handle_nosign;
424335c4bemsmith		case 'p':
425335c4bemsmith			base = 16;
426a3ab268peter			sharpflag = (width == 0);
427a3ab268peter			sign = 0;
428a3ab268peter			num = (uintptr_t)va_arg(ap, void *);
429335c4bemsmith			goto number;
430a3ab268peter		case 'q':
431a3ab268peter			qflag = 1;
432a3ab268peter			goto reswitch;
433a3ab268peter		case 'r':
434a3ab268peter			base = radix;
435a3ab268peter			if (sign)
436a3ab268peter				goto handle_sign;
437a3ab268peter			goto handle_nosign;
438335c4bemsmith		case 's':
439335c4bemsmith			p = va_arg(ap, char *);
440335c4bemsmith			if (p == NULL)
441335c4bemsmith				p = "(null)";
442335c4bemsmith			if (!dot)
443335c4bemsmith				n = strlen (p);
444335c4bemsmith			else
445335c4bemsmith				for (n = 0; n < dwidth && p[n]; n++)
446335c4bemsmith					continue;
447335c4bemsmith
448335c4bemsmith			width -= n;
449335c4bemsmith
450335c4bemsmith			if (!ladjust && width > 0)
451335c4bemsmith				while (width--)
452335c4bemsmith					PCHAR(padc);
453335c4bemsmith			while (n--)
454335c4bemsmith				PCHAR(*p++);
455335c4bemsmith			if (ladjust && width > 0)
456335c4bemsmith				while (width--)
457335c4bemsmith					PCHAR(padc);
458335c4bemsmith			break;
459ad9174cimp		case 'S':	/* Assume console can cope with wide chars */
460ad9174cimp			for (S = va_arg(ap, uint16_t *); *S != 0; S++)
461ad9174cimp				PCHAR(*S);
462ad9174cimp 			break;
463a3ab268peter		case 't':
464a3ab268peter			tflag = 1;
465a3ab268peter			goto reswitch;
466335c4bemsmith		case 'u':
467335c4bemsmith			base = 10;
468a3ab268peter			goto handle_nosign;
469a3ab268peter		case 'X':
4707e4fc3bjkim			upper = 1;
4717e4fc3bjkim		case 'x':
472a3ab268peter			base = 16;
473a3ab268peter			goto handle_nosign;
474a3ab268peter		case 'y':
475335c4bemsmith			base = 16;
476a3ab268peter			sign = 1;
477a3ab268peter			goto handle_sign;
478a3ab268peter		case 'z':
479a3ab268peter			zflag = 1;
480a3ab268peter			goto reswitch;
481a3ab268peterhandle_nosign:
482a3ab268peter			sign = 0;
483a3ab268peter			if (jflag)
484a3ab268peter				num = va_arg(ap, uintmax_t);
485a3ab268peter			else if (qflag)
486a3ab268peter				num = va_arg(ap, u_quad_t);
487a3ab268peter			else if (tflag)
488a3ab268peter				num = va_arg(ap, ptrdiff_t);
489a3ab268peter			else if (lflag)
490a3ab268peter				num = va_arg(ap, u_long);
491a3ab268peter			else if (zflag)
492a3ab268peter				num = va_arg(ap, size_t);
4930fac9c7jkim			else if (hflag)
4940fac9c7jkim				num = (u_short)va_arg(ap, int);
4950fac9c7jkim			else if (cflag)
4960fac9c7jkim				num = (u_char)va_arg(ap, int);
497a3ab268peter			else
498a3ab268peter				num = va_arg(ap, u_int);
499a3ab268peter			goto number;
500a3ab268peterhandle_sign:
501a3ab268peter			if (jflag)
502a3ab268peter				num = va_arg(ap, intmax_t);
503a3ab268peter			else if (qflag)
504a3ab268peter				num = va_arg(ap, quad_t);
505a3ab268peter			else if (tflag)
506a3ab268peter				num = va_arg(ap, ptrdiff_t);
507a3ab268peter			else if (lflag)
508a3ab268peter				num = va_arg(ap, long);
509a3ab268peter			else if (zflag)
510256094ddelphij				num = va_arg(ap, ssize_t);
5110fac9c7jkim			else if (hflag)
5120fac9c7jkim				num = (short)va_arg(ap, int);
5130fac9c7jkim			else if (cflag)
5140fac9c7jkim				num = (char)va_arg(ap, int);
515a3ab268peter			else
516a3ab268peter				num = va_arg(ap, int);
517a3ab268peternumber:
518a3ab268peter			if (sign && (intmax_t)num < 0) {
519335c4bemsmith				neg = 1;
520a3ab268peter				num = -(intmax_t)num;
521335c4bemsmith			}
5220fac9c7jkim			p = ksprintn(nbuf, num, base, &n, upper);
5230fac9c7jkim			tmp = 0;
524a3ab268peter			if (sharpflag && num != 0) {
525335c4bemsmith				if (base == 8)
526335c4bemsmith					tmp++;
527335c4bemsmith				else if (base == 16)
528335c4bemsmith					tmp += 2;
529335c4bemsmith			}
530335c4bemsmith			if (neg)
531335c4bemsmith				tmp++;
532335c4bemsmith
5330fac9c7jkim			if (!ladjust && padc == '0')
5340fac9c7jkim				dwidth = width - tmp;
53506b6c27jkim			width -= tmp + imax(dwidth, n);
5360fac9c7jkim			dwidth -= n;
5370fac9c7jkim			if (!ladjust)
5380fac9c7jkim				while (width-- > 0)
5390fac9c7jkim					PCHAR(' ');
540335c4bemsmith			if (neg)
541335c4bemsmith				PCHAR('-');
542a3ab268peter			if (sharpflag && num != 0) {
543335c4bemsmith				if (base == 8) {
544335c4bemsmith					PCHAR('0');
545335c4bemsmith				} else if (base == 16) {
546335c4bemsmith					PCHAR('0');
547335c4bemsmith					PCHAR('x');
548335c4bemsmith				}
549335c4bemsmith			}
5500fac9c7jkim			while (dwidth-- > 0)
5510fac9c7jkim				PCHAR('0');
552335c4bemsmith
553335c4bemsmith			while (*p)
554335c4bemsmith				PCHAR(*p--);
555335c4bemsmith
5560fac9c7jkim			if (ladjust)
5570fac9c7jkim				while (width-- > 0)
5580fac9c7jkim					PCHAR(' ');
559335c4bemsmith
560335c4bemsmith			break;
561335c4bemsmith		default:
562a3ab268peter			while (percent < fmt)
563a3ab268peter				PCHAR(*percent++);
5640fac9c7jkim			/*
565d20a416danfe			 * Since we ignore a formatting argument it is no
5660fac9c7jkim			 * longer safe to obey the remaining formatting
5670fac9c7jkim			 * arguments as the arguments will no longer match
5680fac9c7jkim			 * the format specs.
5690fac9c7jkim			 */
5700fac9c7jkim			stop = 1;
571335c4bemsmith			break;
572335c4bemsmith		}
573335c4bemsmith	}
574335c4bemsmith#undef PCHAR
575335c4bemsmith}
576