138451Smsmith/*-
238451Smsmith * Copyright (c) 1986, 1988, 1991, 1993
338451Smsmith *	The Regents of the University of California.  All rights reserved.
438451Smsmith * (c) UNIX System Laboratories, Inc.
538451Smsmith * All or some portions of this file are derived from material licensed
638451Smsmith * to the University of California by American Telephone and Telegraph
738451Smsmith * Co. or Unix System Laboratories, Inc. and are reproduced herein with
838451Smsmith * the permission of UNIX System Laboratories, Inc.
938451Smsmith *
1038451Smsmith * Redistribution and use in source and binary forms, with or without
1138451Smsmith * modification, are permitted provided that the following conditions
1238451Smsmith * are met:
1338451Smsmith * 1. Redistributions of source code must retain the above copyright
1438451Smsmith *    notice, this list of conditions and the following disclaimer.
1538451Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1638451Smsmith *    notice, this list of conditions and the following disclaimer in the
1738451Smsmith *    documentation and/or other materials provided with the distribution.
1838451Smsmith * 4. Neither the name of the University nor the names of its contributors
1938451Smsmith *    may be used to endorse or promote products derived from this software
2038451Smsmith *    without specific prior written permission.
2138451Smsmith *
2238451Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2338451Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2438451Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2538451Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2638451Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2738451Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2838451Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2938451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3038451Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3138451Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3238451Smsmith * SUCH DAMAGE.
3338451Smsmith *
3438451Smsmith *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
3538451Smsmith */
3638451Smsmith
3784221Sdillon#include <sys/cdefs.h>
3884221Sdillon__FBSDID("$FreeBSD: stable/11/stand/libsa/printf.c 346477 2019-04-21 03:43:27Z kevans $");
3984221Sdillon
4038451Smsmith/*
4138451Smsmith * Standaloneified version of the FreeBSD kernel printf family.
4238451Smsmith */
4338451Smsmith
4438451Smsmith#include <sys/types.h>
45113159Speter#include <sys/stddef.h>
46113159Speter#include <sys/stdint.h>
47103949Smike#include <limits.h>
4855137Speter#include <string.h>
4938451Smsmith#include "stand.h"
5038451Smsmith
5138451Smsmith/*
5238451Smsmith * Note that stdarg.h and the ANSI style va_start macro is used for both
5338451Smsmith * ANSI and traditional C compilers.
5438451Smsmith */
5538451Smsmith#include <machine/stdarg.h>
5638451Smsmith
57113159Speter#define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1)
58113159Speter
59266878Shselaskytypedef void (kvprintf_fn_t)(int, void *);
60266878Shselasky
61156518Sjkimstatic char	*ksprintn (char *buf, uintmax_t num, int base, int *len, int upper);
62266878Shselaskystatic int	kvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap);
6338451Smsmith
64266878Shselaskystatic void
65266878Shselaskyputchar_wrapper(int cc, void *arg)
66266878Shselasky{
67266879Shselasky
68266878Shselasky	putchar(cc);
69266878Shselasky}
70266878Shselasky
7138451Smsmithint
7238451Smsmithprintf(const char *fmt, ...)
7338451Smsmith{
7438451Smsmith	va_list ap;
7538451Smsmith	int retval;
7638451Smsmith
7738451Smsmith	va_start(ap, fmt);
78266878Shselasky	retval = kvprintf(fmt, putchar_wrapper, NULL, 10, ap);
7938451Smsmith	va_end(ap);
8038451Smsmith	return retval;
8138451Smsmith}
8238451Smsmith
83334935Sianint
8438451Smsmithvprintf(const char *fmt, va_list ap)
8538451Smsmith{
86266879Shselasky
87334935Sian	return (kvprintf(fmt, putchar_wrapper, NULL, 10, ap));
8838451Smsmith}
8938451Smsmith
9038451Smsmithint
9138451Smsmithsprintf(char *buf, const char *cfmt, ...)
9238451Smsmith{
9338451Smsmith	int retval;
9438451Smsmith	va_list ap;
9538451Smsmith
9638451Smsmith	va_start(ap, cfmt);
9738451Smsmith	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
9838451Smsmith	buf[retval] = '\0';
9938451Smsmith	va_end(ap);
10038451Smsmith	return retval;
10138451Smsmith}
10238451Smsmith
103266878Shselaskystruct print_buf {
104266878Shselasky	char *buf;
105266878Shselasky	size_t size;
106266878Shselasky};
107266878Shselasky
108266878Shselaskystatic void
109266878Shselaskysnprint_func(int ch, void *arg)
110266878Shselasky{
111266878Shselasky	struct print_buf *pbuf = arg;
112266878Shselasky
113266878Shselasky	if (pbuf->size < 2) {
114266878Shselasky		/*
115266878Shselasky		 * Reserve last buffer position for the terminating
116266878Shselasky		 * character:
117266878Shselasky		 */
118266878Shselasky		return;
119266878Shselasky	}
120266878Shselasky	*(pbuf->buf)++ = ch;
121266878Shselasky	pbuf->size--;
122266878Shselasky}
123266878Shselasky
124266878Shselaskyint
125346477Skevansasprintf(char **buf, const char *cfmt, ...)
126346477Skevans{
127346477Skevans	int retval;
128346477Skevans	struct print_buf arg;
129346477Skevans	va_list ap;
130346477Skevans
131346477Skevans	*buf = NULL;
132346477Skevans	va_start(ap, cfmt);
133346477Skevans	retval = kvprintf(cfmt, NULL, NULL, 10, ap);
134346477Skevans	va_end(ap);
135346477Skevans	if (retval <= 0)
136346477Skevans		return (-1);
137346477Skevans
138346477Skevans	arg.size = retval + 1;
139346477Skevans	arg.buf = *buf = malloc(arg.size);
140346477Skevans	if (*buf == NULL)
141346477Skevans		return (-1);
142346477Skevans
143346477Skevans	va_start(ap, cfmt);
144346477Skevans	retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap);
145346477Skevans	va_end(ap);
146346477Skevans
147346477Skevans	if (arg.size >= 1)
148346477Skevans		*(arg.buf)++ = 0;
149346477Skevans	return (retval);
150346477Skevans}
151346477Skevans
152346477Skevansint
153266878Shselaskysnprintf(char *buf, size_t size, const char *cfmt, ...)
154266878Shselasky{
155266878Shselasky	int retval;
156266878Shselasky	va_list ap;
157266878Shselasky	struct print_buf arg;
158266878Shselasky
159266878Shselasky	arg.buf = buf;
160266878Shselasky	arg.size = size;
161266878Shselasky
162266878Shselasky	va_start(ap, cfmt);
163266878Shselasky	retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap);
164266878Shselasky	va_end(ap);
165266878Shselasky
166266878Shselasky	if (arg.size >= 1)
167266878Shselasky		*(arg.buf)++ = 0;
168266878Shselasky	return retval;
169266878Shselasky}
170266878Shselasky
171334935Sianint
172334935Sianvsnprintf(char *buf, size_t size, const char *cfmt, va_list ap)
173334935Sian{
174334935Sian	struct print_buf arg;
175334935Sian	int retval;
176334935Sian
177334935Sian	arg.buf = buf;
178334935Sian	arg.size = size;
179334935Sian
180334935Sian	retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap);
181334935Sian
182334935Sian	if (arg.size >= 1)
183334935Sian		*(arg.buf)++ = 0;
184334935Sian
185334935Sian	return (retval);
186334935Sian}
187334935Sian
188334935Sianint
18940805Smsmithvsprintf(char *buf, const char *cfmt, va_list ap)
19040805Smsmith{
19140805Smsmith	int	retval;
19240805Smsmith
19340805Smsmith	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
19440805Smsmith	buf[retval] = '\0';
195334935Sian
196334935Sian	return (retval);
19740805Smsmith}
19840805Smsmith
19938451Smsmith/*
200113159Speter * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
201113159Speter * order; return an optional length and a pointer to the last character
202113159Speter * written in the buffer (i.e., the first character of the string).
203113159Speter * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
20438451Smsmith */
20538451Smsmithstatic char *
206156518Sjkimksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
207113159Speter{
208156518Sjkim	char *p, c;
20938451Smsmith
210113159Speter	p = nbuf;
211113159Speter	*p = '\0';
21238451Smsmith	do {
213156518Sjkim		c = hex2ascii(num % base);
214156518Sjkim		*++p = upper ? toupper(c) : c;
215113159Speter	} while (num /= base);
21638451Smsmith	if (lenp)
217113159Speter		*lenp = p - nbuf;
21838451Smsmith	return (p);
21938451Smsmith}
22038451Smsmith
22138451Smsmith/*
22238451Smsmith * Scaled down version of printf(3).
22338451Smsmith *
22438451Smsmith * Two additional formats:
22538451Smsmith *
22638451Smsmith * The format %b is supported to decode error registers.
22738451Smsmith * Its usage is:
22838451Smsmith *
22938451Smsmith *	printf("reg=%b\n", regval, "<base><arg>*");
23038451Smsmith *
23138451Smsmith * where <base> is the output base expressed as a control character, e.g.
23238451Smsmith * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
23338451Smsmith * the first of which gives the bit number to be inspected (origin 1), and
23438451Smsmith * the next characters (up to a control character, i.e. a character <= 32),
23538451Smsmith * give the name of the register.  Thus:
23638451Smsmith *
237277560Sdanfe *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE");
23838451Smsmith *
23938451Smsmith * would produce output:
24038451Smsmith *
24138451Smsmith *	reg=3<BITTWO,BITONE>
24238451Smsmith *
24338451Smsmith * XXX:  %D  -- Hexdump, takes pointer and separator string:
24438451Smsmith *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
24538451Smsmith *		("%*D", len, ptr, " " -> XX XX XX XX ...
24638451Smsmith */
24738451Smsmithstatic int
248266878Shselaskykvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap)
24938451Smsmith{
250266878Shselasky#define PCHAR(c) {int cc=(c); if (func) (*func)(cc, arg); else *d++ = cc; retval++; }
251113159Speter	char nbuf[MAXNBUF];
252113159Speter	char *d;
253113159Speter	const char *p, *percent, *q;
254300078Simp	uint16_t *S;
25538451Smsmith	u_char *up;
25638451Smsmith	int ch, n;
257113159Speter	uintmax_t num;
258113159Speter	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
259209837Sjkim	int cflag, hflag, jflag, tflag, zflag;
260156518Sjkim	int dwidth, upper;
26138451Smsmith	char padc;
262209837Sjkim	int stop = 0, retval = 0;
26338451Smsmith
264113159Speter	num = 0;
26538451Smsmith	if (!func)
26638451Smsmith		d = (char *) arg;
26738451Smsmith	else
26838451Smsmith		d = NULL;
26938451Smsmith
27038451Smsmith	if (fmt == NULL)
27138451Smsmith		fmt = "(fmt null)\n";
27238451Smsmith
27338451Smsmith	if (radix < 2 || radix > 36)
27438451Smsmith		radix = 10;
27538451Smsmith
27638451Smsmith	for (;;) {
27738451Smsmith		padc = ' ';
27838451Smsmith		width = 0;
279209837Sjkim		while ((ch = (u_char)*fmt++) != '%' || stop) {
280113159Speter			if (ch == '\0')
281113159Speter				return (retval);
28238451Smsmith			PCHAR(ch);
28338451Smsmith		}
284113159Speter		percent = fmt - 1;
285113159Speter		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
286156518Sjkim		sign = 0; dot = 0; dwidth = 0; upper = 0;
287209837Sjkim		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
28838451Smsmithreswitch:	switch (ch = (u_char)*fmt++) {
28938451Smsmith		case '.':
29038451Smsmith			dot = 1;
29138451Smsmith			goto reswitch;
29238451Smsmith		case '#':
29338451Smsmith			sharpflag = 1;
29438451Smsmith			goto reswitch;
29538451Smsmith		case '+':
29638451Smsmith			sign = 1;
29738451Smsmith			goto reswitch;
29838451Smsmith		case '-':
29938451Smsmith			ladjust = 1;
30038451Smsmith			goto reswitch;
30138451Smsmith		case '%':
30238451Smsmith			PCHAR(ch);
30338451Smsmith			break;
30438451Smsmith		case '*':
30538451Smsmith			if (!dot) {
30638451Smsmith				width = va_arg(ap, int);
30738451Smsmith				if (width < 0) {
30838451Smsmith					ladjust = !ladjust;
30938451Smsmith					width = -width;
31038451Smsmith				}
31138451Smsmith			} else {
31238451Smsmith				dwidth = va_arg(ap, int);
31338451Smsmith			}
31438451Smsmith			goto reswitch;
31538451Smsmith		case '0':
31638451Smsmith			if (!dot) {
31738451Smsmith				padc = '0';
31838451Smsmith				goto reswitch;
31938451Smsmith			}
32038451Smsmith		case '1': case '2': case '3': case '4':
32138451Smsmith		case '5': case '6': case '7': case '8': case '9':
32238451Smsmith				for (n = 0;; ++fmt) {
32338451Smsmith					n = n * 10 + ch - '0';
32438451Smsmith					ch = *fmt;
32538451Smsmith					if (ch < '0' || ch > '9')
32638451Smsmith						break;
32738451Smsmith				}
32838451Smsmith			if (dot)
32938451Smsmith				dwidth = n;
33038451Smsmith			else
33138451Smsmith				width = n;
33238451Smsmith			goto reswitch;
33338451Smsmith		case 'b':
334209837Sjkim			num = (u_int)va_arg(ap, int);
33538451Smsmith			p = va_arg(ap, char *);
336156518Sjkim			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
33738451Smsmith				PCHAR(*q--);
33838451Smsmith
339113159Speter			if (num == 0)
34038451Smsmith				break;
34138451Smsmith
34238451Smsmith			for (tmp = 0; *p;) {
34338451Smsmith				n = *p++;
344113159Speter				if (num & (1 << (n - 1))) {
34538451Smsmith					PCHAR(tmp ? ',' : '<');
34638451Smsmith					for (; (n = *p) > ' '; ++p)
34738451Smsmith						PCHAR(n);
34838451Smsmith					tmp = 1;
34938451Smsmith				} else
35038451Smsmith					for (; *p > ' '; ++p)
35138451Smsmith						continue;
35238451Smsmith			}
35338451Smsmith			if (tmp)
35438451Smsmith				PCHAR('>');
35538451Smsmith			break;
35638451Smsmith		case 'c':
35738451Smsmith			PCHAR(va_arg(ap, int));
35838451Smsmith			break;
35938451Smsmith		case 'D':
36038451Smsmith			up = va_arg(ap, u_char *);
36138451Smsmith			p = va_arg(ap, char *);
36238451Smsmith			if (!width)
36338451Smsmith				width = 16;
36438451Smsmith			while(width--) {
36538451Smsmith				PCHAR(hex2ascii(*up >> 4));
36638451Smsmith				PCHAR(hex2ascii(*up & 0x0f));
36738451Smsmith				up++;
36838451Smsmith				if (width)
36938451Smsmith					for (q=p;*q;q++)
37038451Smsmith						PCHAR(*q);
37138451Smsmith			}
37238451Smsmith			break;
37338451Smsmith		case 'd':
374113159Speter		case 'i':
375113159Speter			base = 10;
37638451Smsmith			sign = 1;
377113159Speter			goto handle_sign;
378209837Sjkim		case 'h':
379209837Sjkim			if (hflag) {
380209837Sjkim				hflag = 0;
381209837Sjkim				cflag = 1;
382209837Sjkim			} else
383209837Sjkim				hflag = 1;
384209837Sjkim			goto reswitch;
385113159Speter		case 'j':
386113159Speter			jflag = 1;
387113159Speter			goto reswitch;
38838451Smsmith		case 'l':
389113159Speter			if (lflag) {
390113159Speter				lflag = 0;
391113159Speter				qflag = 1;
392113159Speter			} else
393113159Speter				lflag = 1;
39438451Smsmith			goto reswitch;
39538451Smsmith		case 'n':
396113159Speter			if (jflag)
397113159Speter				*(va_arg(ap, intmax_t *)) = retval;
398113159Speter			else if (qflag)
399113159Speter				*(va_arg(ap, quad_t *)) = retval;
400113159Speter			else if (lflag)
401113159Speter				*(va_arg(ap, long *)) = retval;
402113159Speter			else if (zflag)
403113159Speter				*(va_arg(ap, size_t *)) = retval;
404209837Sjkim			else if (hflag)
405209837Sjkim				*(va_arg(ap, short *)) = retval;
406209837Sjkim			else if (cflag)
407209837Sjkim				*(va_arg(ap, char *)) = retval;
408113159Speter			else
409113159Speter				*(va_arg(ap, int *)) = retval;
410113159Speter			break;
41138451Smsmith		case 'o':
41238451Smsmith			base = 8;
413113159Speter			goto handle_nosign;
41438451Smsmith		case 'p':
41538451Smsmith			base = 16;
416113159Speter			sharpflag = (width == 0);
417113159Speter			sign = 0;
418113159Speter			num = (uintptr_t)va_arg(ap, void *);
41938451Smsmith			goto number;
420113159Speter		case 'q':
421113159Speter			qflag = 1;
422113159Speter			goto reswitch;
423113159Speter		case 'r':
424113159Speter			base = radix;
425113159Speter			if (sign)
426113159Speter				goto handle_sign;
427113159Speter			goto handle_nosign;
42838451Smsmith		case 's':
42938451Smsmith			p = va_arg(ap, char *);
43038451Smsmith			if (p == NULL)
43138451Smsmith				p = "(null)";
43238451Smsmith			if (!dot)
43338451Smsmith				n = strlen (p);
43438451Smsmith			else
43538451Smsmith				for (n = 0; n < dwidth && p[n]; n++)
43638451Smsmith					continue;
43738451Smsmith
43838451Smsmith			width -= n;
43938451Smsmith
44038451Smsmith			if (!ladjust && width > 0)
44138451Smsmith				while (width--)
44238451Smsmith					PCHAR(padc);
44338451Smsmith			while (n--)
44438451Smsmith				PCHAR(*p++);
44538451Smsmith			if (ladjust && width > 0)
44638451Smsmith				while (width--)
44738451Smsmith					PCHAR(padc);
44838451Smsmith			break;
449300078Simp		case 'S':	/* Assume console can cope with wide chars */
450300078Simp			for (S = va_arg(ap, uint16_t *); *S != 0; S++)
451300078Simp				PCHAR(*S);
452300078Simp 			break;
453113159Speter		case 't':
454113159Speter			tflag = 1;
455113159Speter			goto reswitch;
45638451Smsmith		case 'u':
45738451Smsmith			base = 10;
458113159Speter			goto handle_nosign;
459156518Sjkim		case 'X':
460156518Sjkim			upper = 1;
46138451Smsmith		case 'x':
46238451Smsmith			base = 16;
463113159Speter			goto handle_nosign;
464113159Speter		case 'y':
465113159Speter			base = 16;
466113159Speter			sign = 1;
467113159Speter			goto handle_sign;
468113159Speter		case 'z':
469113159Speter			zflag = 1;
470113159Speter			goto reswitch;
471113159Speterhandle_nosign:
472113159Speter			sign = 0;
473113159Speter			if (jflag)
474113159Speter				num = va_arg(ap, uintmax_t);
475113159Speter			else if (qflag)
476113159Speter				num = va_arg(ap, u_quad_t);
477113159Speter			else if (tflag)
478113159Speter				num = va_arg(ap, ptrdiff_t);
479113159Speter			else if (lflag)
480113159Speter				num = va_arg(ap, u_long);
481113159Speter			else if (zflag)
482113159Speter				num = va_arg(ap, size_t);
483209837Sjkim			else if (hflag)
484209837Sjkim				num = (u_short)va_arg(ap, int);
485209837Sjkim			else if (cflag)
486209837Sjkim				num = (u_char)va_arg(ap, int);
487113159Speter			else
488113159Speter				num = va_arg(ap, u_int);
489113159Speter			goto number;
490113159Speterhandle_sign:
491113159Speter			if (jflag)
492113159Speter				num = va_arg(ap, intmax_t);
493113159Speter			else if (qflag)
494113159Speter				num = va_arg(ap, quad_t);
495113159Speter			else if (tflag)
496113159Speter				num = va_arg(ap, ptrdiff_t);
497113159Speter			else if (lflag)
498113159Speter				num = va_arg(ap, long);
499113159Speter			else if (zflag)
500185037Sdelphij				num = va_arg(ap, ssize_t);
501209837Sjkim			else if (hflag)
502209837Sjkim				num = (short)va_arg(ap, int);
503209837Sjkim			else if (cflag)
504209837Sjkim				num = (char)va_arg(ap, int);
505113159Speter			else
506113159Speter				num = va_arg(ap, int);
507113159Speternumber:
508113159Speter			if (sign && (intmax_t)num < 0) {
50938451Smsmith				neg = 1;
510113159Speter				num = -(intmax_t)num;
51138451Smsmith			}
512209837Sjkim			p = ksprintn(nbuf, num, base, &n, upper);
513209837Sjkim			tmp = 0;
514113159Speter			if (sharpflag && num != 0) {
51538451Smsmith				if (base == 8)
51638451Smsmith					tmp++;
51738451Smsmith				else if (base == 16)
51838451Smsmith					tmp += 2;
51938451Smsmith			}
52038451Smsmith			if (neg)
52138451Smsmith				tmp++;
52238451Smsmith
523209837Sjkim			if (!ladjust && padc == '0')
524209837Sjkim				dwidth = width - tmp;
525209949Sjkim			width -= tmp + imax(dwidth, n);
526209837Sjkim			dwidth -= n;
527209837Sjkim			if (!ladjust)
528209837Sjkim				while (width-- > 0)
529209837Sjkim					PCHAR(' ');
53038451Smsmith			if (neg)
53138451Smsmith				PCHAR('-');
532113159Speter			if (sharpflag && num != 0) {
53338451Smsmith				if (base == 8) {
53438451Smsmith					PCHAR('0');
53538451Smsmith				} else if (base == 16) {
53638451Smsmith					PCHAR('0');
53738451Smsmith					PCHAR('x');
53838451Smsmith				}
53938451Smsmith			}
540209837Sjkim			while (dwidth-- > 0)
541209837Sjkim				PCHAR('0');
54238451Smsmith
54338451Smsmith			while (*p)
54438451Smsmith				PCHAR(*p--);
54538451Smsmith
546209837Sjkim			if (ladjust)
547209837Sjkim				while (width-- > 0)
548209837Sjkim					PCHAR(' ');
54938451Smsmith
55038451Smsmith			break;
55138451Smsmith		default:
552113159Speter			while (percent < fmt)
553113159Speter				PCHAR(*percent++);
554209837Sjkim			/*
555277560Sdanfe			 * Since we ignore a formatting argument it is no
556209837Sjkim			 * longer safe to obey the remaining formatting
557209837Sjkim			 * arguments as the arguments will no longer match
558209837Sjkim			 * the format specs.
559209837Sjkim			 */
560209837Sjkim			stop = 1;
56138451Smsmith			break;
56238451Smsmith		}
56338451Smsmith	}
56438451Smsmith#undef PCHAR
56538451Smsmith}
566