1a9643ea8Slogwang /*-
2a9643ea8Slogwang * Copyright (c) 1986, 1988, 1991, 1993
3a9643ea8Slogwang * The Regents of the University of California. All rights reserved.
4a9643ea8Slogwang * (c) UNIX System Laboratories, Inc.
5a9643ea8Slogwang * All or some portions of this file are derived from material licensed
6a9643ea8Slogwang * to the University of California by American Telephone and Telegraph
7a9643ea8Slogwang * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8a9643ea8Slogwang * the permission of UNIX System Laboratories, Inc.
9a9643ea8Slogwang *
10a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without
11a9643ea8Slogwang * modification, are permitted provided that the following conditions
12a9643ea8Slogwang * are met:
13a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright
14a9643ea8Slogwang * notice, this list of conditions and the following disclaimer.
15a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright
16a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in the
17a9643ea8Slogwang * documentation and/or other materials provided with the distribution.
18a9643ea8Slogwang * 4. Neither the name of the University nor the names of its contributors
19a9643ea8Slogwang * may be used to endorse or promote products derived from this software
20a9643ea8Slogwang * without specific prior written permission.
21a9643ea8Slogwang *
22a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23a9643ea8Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24a9643ea8Slogwang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25a9643ea8Slogwang * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26a9643ea8Slogwang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27a9643ea8Slogwang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28a9643ea8Slogwang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29a9643ea8Slogwang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30a9643ea8Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31a9643ea8Slogwang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32a9643ea8Slogwang * SUCH DAMAGE.
33a9643ea8Slogwang *
34a9643ea8Slogwang * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
35a9643ea8Slogwang */
36a9643ea8Slogwang
37a9643ea8Slogwang #include <sys/cdefs.h>
38a9643ea8Slogwang __FBSDID("$FreeBSD$");
39a9643ea8Slogwang
40a9643ea8Slogwang #include "opt_ddb.h"
41a9643ea8Slogwang
42a9643ea8Slogwang #include <sys/param.h>
43a9643ea8Slogwang #include <sys/systm.h>
44a9643ea8Slogwang #include <sys/lock.h>
45a9643ea8Slogwang #include <sys/kdb.h>
46a9643ea8Slogwang #include <sys/mutex.h>
47a9643ea8Slogwang #include <sys/sx.h>
48a9643ea8Slogwang #include <sys/kernel.h>
49a9643ea8Slogwang #include <sys/msgbuf.h>
50a9643ea8Slogwang #include <sys/malloc.h>
51a9643ea8Slogwang #include <sys/priv.h>
52a9643ea8Slogwang #include <sys/proc.h>
53a9643ea8Slogwang #include <sys/stddef.h>
54a9643ea8Slogwang #include <sys/sysctl.h>
55a9643ea8Slogwang #include <sys/tty.h>
56a9643ea8Slogwang #include <sys/syslog.h>
57a9643ea8Slogwang #include <sys/cons.h>
58a9643ea8Slogwang #include <sys/uio.h>
59a9643ea8Slogwang #include <sys/ctype.h>
60*22ce4affSfengbojiang #include <sys/sbuf.h>
61a9643ea8Slogwang
62a9643ea8Slogwang #ifdef DDB
63a9643ea8Slogwang #include <ddb/ddb.h>
64a9643ea8Slogwang #endif
65a9643ea8Slogwang
66a9643ea8Slogwang /*
67a9643ea8Slogwang * Note that stdarg.h and the ANSI style va_start macro is used for both
68a9643ea8Slogwang * ANSI and traditional C compilers.
69a9643ea8Slogwang */
70a9643ea8Slogwang #include <machine/stdarg.h>
71a9643ea8Slogwang
72a9643ea8Slogwang #define TOCONS 0x01
73a9643ea8Slogwang #define TOTTY 0x02
74a9643ea8Slogwang #define TOLOG 0x04
75a9643ea8Slogwang
76a9643ea8Slogwang /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
77a9643ea8Slogwang #define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
78a9643ea8Slogwang
79a9643ea8Slogwang struct putchar_arg {
80a9643ea8Slogwang int flags;
81a9643ea8Slogwang int pri;
82a9643ea8Slogwang struct tty *tty;
83a9643ea8Slogwang char *p_bufr;
84a9643ea8Slogwang size_t n_bufr;
85a9643ea8Slogwang char *p_next;
86a9643ea8Slogwang size_t remain;
87a9643ea8Slogwang };
88a9643ea8Slogwang
89a9643ea8Slogwang struct snprintf_arg {
90a9643ea8Slogwang char *str;
91a9643ea8Slogwang size_t remain;
92a9643ea8Slogwang };
93a9643ea8Slogwang
94a9643ea8Slogwang int putchar(int c);
95a9643ea8Slogwang int puts(const char *str);
96a9643ea8Slogwang
97a9643ea8Slogwang
98a9643ea8Slogwang static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
99a9643ea8Slogwang
100a9643ea8Slogwang /*
101a9643ea8Slogwang * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
102a9643ea8Slogwang * order; return an optional length and a pointer to the last character
103a9643ea8Slogwang * written in the buffer (i.e., the first character of the string).
104a9643ea8Slogwang * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
105a9643ea8Slogwang */
106a9643ea8Slogwang static char *
ksprintn(char * nbuf,uintmax_t num,int base,int * lenp,int upper)107a9643ea8Slogwang ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
108a9643ea8Slogwang {
109a9643ea8Slogwang char *p, c;
110a9643ea8Slogwang
111a9643ea8Slogwang p = nbuf;
112a9643ea8Slogwang *p = '\0';
113a9643ea8Slogwang do {
114a9643ea8Slogwang c = hex2ascii(num % base);
115a9643ea8Slogwang *++p = upper ? toupper(c) : c;
116a9643ea8Slogwang } while (num /= base);
117a9643ea8Slogwang if (lenp)
118a9643ea8Slogwang *lenp = p - nbuf;
119a9643ea8Slogwang return (p);
120a9643ea8Slogwang }
121a9643ea8Slogwang
122a9643ea8Slogwang static void
putbuf(int c,struct putchar_arg * ap)123a9643ea8Slogwang putbuf(int c, struct putchar_arg *ap)
124a9643ea8Slogwang {
125a9643ea8Slogwang /* Check if no console output buffer was provided. */
126a9643ea8Slogwang if (ap->p_bufr == NULL) {
127a9643ea8Slogwang /* Output direct to the console. */
128a9643ea8Slogwang if (ap->flags & TOCONS)
129a9643ea8Slogwang putchar(c);
130a9643ea8Slogwang
131a9643ea8Slogwang } else {
132a9643ea8Slogwang /* Buffer the character: */
133a9643ea8Slogwang *ap->p_next++ = c;
134a9643ea8Slogwang ap->remain--;
135a9643ea8Slogwang
136a9643ea8Slogwang /* Always leave the buffer zero terminated. */
137a9643ea8Slogwang *ap->p_next = '\0';
138a9643ea8Slogwang
139a9643ea8Slogwang /* Check if the buffer needs to be flushed. */
140a9643ea8Slogwang if (ap->remain == 2 || c == '\n') {
141a9643ea8Slogwang
142a9643ea8Slogwang if (ap->flags & TOCONS) {
143a9643ea8Slogwang puts(ap->p_bufr);
144a9643ea8Slogwang }
145a9643ea8Slogwang
146a9643ea8Slogwang ap->p_next = ap->p_bufr;
147a9643ea8Slogwang ap->remain = ap->n_bufr;
148a9643ea8Slogwang *ap->p_next = '\0';
149a9643ea8Slogwang }
150a9643ea8Slogwang
151a9643ea8Slogwang /*
152a9643ea8Slogwang * Since we fill the buffer up one character at a time,
153a9643ea8Slogwang * this should not happen. We should always catch it when
154a9643ea8Slogwang * ap->remain == 2 (if not sooner due to a newline), flush
155a9643ea8Slogwang * the buffer and move on. One way this could happen is
156a9643ea8Slogwang * if someone sets PRINTF_BUFR_SIZE to 1 or something
157a9643ea8Slogwang * similarly silly.
158a9643ea8Slogwang */
159a9643ea8Slogwang KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd",
160a9643ea8Slogwang ap->remain));
161a9643ea8Slogwang }
162a9643ea8Slogwang }
163a9643ea8Slogwang
164a9643ea8Slogwang /*
165a9643ea8Slogwang * Print a character on console or users terminal. If destination is
166a9643ea8Slogwang * the console then the last bunch of characters are saved in msgbuf for
167a9643ea8Slogwang * inspection later.
168a9643ea8Slogwang */
169a9643ea8Slogwang static void
kputchar(int c,void * arg)170a9643ea8Slogwang kputchar(int c, void *arg)
171a9643ea8Slogwang {
172a9643ea8Slogwang struct putchar_arg *ap = (struct putchar_arg*) arg;
173a9643ea8Slogwang int flags = ap->flags;
174a9643ea8Slogwang int putbuf_done = 0;
175a9643ea8Slogwang
176a9643ea8Slogwang if (flags & TOCONS) {
177a9643ea8Slogwang putbuf(c, ap);
178a9643ea8Slogwang putbuf_done = 1;
179a9643ea8Slogwang }
180a9643ea8Slogwang
181a9643ea8Slogwang if ((flags & TOLOG) && (putbuf_done == 0)) {
182a9643ea8Slogwang if (c != '\0')
183a9643ea8Slogwang putbuf(c, ap);
184a9643ea8Slogwang }
185a9643ea8Slogwang }
186a9643ea8Slogwang
187a9643ea8Slogwang /*
188a9643ea8Slogwang * Scaled down version of printf(3).
189a9643ea8Slogwang *
190a9643ea8Slogwang * Two additional formats:
191a9643ea8Slogwang *
192a9643ea8Slogwang * The format %b is supported to decode error registers.
193a9643ea8Slogwang * Its usage is:
194a9643ea8Slogwang *
195a9643ea8Slogwang * printf("reg=%b\n", regval, "<base><arg>*");
196a9643ea8Slogwang *
197a9643ea8Slogwang * where <base> is the output base expressed as a control character, e.g.
198a9643ea8Slogwang * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
199a9643ea8Slogwang * the first of which gives the bit number to be inspected (origin 1), and
200a9643ea8Slogwang * the next characters (up to a control character, i.e. a character <= 32),
201a9643ea8Slogwang * give the name of the register. Thus:
202a9643ea8Slogwang *
203a9643ea8Slogwang * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
204a9643ea8Slogwang *
205a9643ea8Slogwang * would produce output:
206a9643ea8Slogwang *
207a9643ea8Slogwang * reg=3<BITTWO,BITONE>
208a9643ea8Slogwang *
209a9643ea8Slogwang * XXX: %D -- Hexdump, takes pointer and separator string:
210a9643ea8Slogwang * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
211a9643ea8Slogwang * ("%*D", len, ptr, " " -> XX XX XX XX ...
212a9643ea8Slogwang */
213a9643ea8Slogwang int
kvprintf(char const * fmt,void (* func)(int,void *),void * arg,int radix,va_list ap)214a9643ea8Slogwang kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
215a9643ea8Slogwang {
216a9643ea8Slogwang #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
217a9643ea8Slogwang char nbuf[MAXNBUF];
218a9643ea8Slogwang char *d;
219a9643ea8Slogwang const char *p, *percent, *q;
220a9643ea8Slogwang u_char *up;
221a9643ea8Slogwang int ch, n;
222a9643ea8Slogwang uintmax_t num;
223a9643ea8Slogwang int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
224a9643ea8Slogwang int cflag, hflag, jflag, tflag, zflag;
225a9643ea8Slogwang int dwidth, upper;
226a9643ea8Slogwang char padc;
227a9643ea8Slogwang int stop = 0, retval = 0;
228a9643ea8Slogwang
229a9643ea8Slogwang num = 0;
230a9643ea8Slogwang if (!func)
231a9643ea8Slogwang d = (char *) arg;
232a9643ea8Slogwang else
233a9643ea8Slogwang d = NULL;
234a9643ea8Slogwang
235a9643ea8Slogwang if (fmt == NULL)
236a9643ea8Slogwang fmt = "(fmt null)\n";
237a9643ea8Slogwang
238a9643ea8Slogwang if (radix < 2 || radix > 36)
239a9643ea8Slogwang radix = 10;
240a9643ea8Slogwang
241a9643ea8Slogwang for (;;) {
242a9643ea8Slogwang padc = ' ';
243a9643ea8Slogwang width = 0;
244a9643ea8Slogwang while ((ch = (u_char)*fmt++) != '%' || stop) {
245a9643ea8Slogwang if (ch == '\0')
246a9643ea8Slogwang return (retval);
247a9643ea8Slogwang PCHAR(ch);
248a9643ea8Slogwang }
249a9643ea8Slogwang percent = fmt - 1;
250a9643ea8Slogwang qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
251a9643ea8Slogwang sign = 0; dot = 0; dwidth = 0; upper = 0;
252a9643ea8Slogwang cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
253a9643ea8Slogwang reswitch: switch (ch = (u_char)*fmt++) {
254a9643ea8Slogwang case '.':
255a9643ea8Slogwang dot = 1;
256a9643ea8Slogwang goto reswitch;
257a9643ea8Slogwang case '#':
258a9643ea8Slogwang sharpflag = 1;
259a9643ea8Slogwang goto reswitch;
260a9643ea8Slogwang case '+':
261a9643ea8Slogwang sign = 1;
262a9643ea8Slogwang goto reswitch;
263a9643ea8Slogwang case '-':
264a9643ea8Slogwang ladjust = 1;
265a9643ea8Slogwang goto reswitch;
266a9643ea8Slogwang case '%':
267a9643ea8Slogwang PCHAR(ch);
268a9643ea8Slogwang break;
269a9643ea8Slogwang case '*':
270a9643ea8Slogwang if (!dot) {
271a9643ea8Slogwang width = va_arg(ap, int);
272a9643ea8Slogwang if (width < 0) {
273a9643ea8Slogwang ladjust = !ladjust;
274a9643ea8Slogwang width = -width;
275a9643ea8Slogwang }
276a9643ea8Slogwang } else {
277a9643ea8Slogwang dwidth = va_arg(ap, int);
278a9643ea8Slogwang }
279a9643ea8Slogwang goto reswitch;
280a9643ea8Slogwang case '0':
281a9643ea8Slogwang if (!dot) {
282a9643ea8Slogwang padc = '0';
283a9643ea8Slogwang goto reswitch;
284a9643ea8Slogwang }
285a9643ea8Slogwang case '1': case '2': case '3': case '4':
286a9643ea8Slogwang case '5': case '6': case '7': case '8': case '9':
287a9643ea8Slogwang for (n = 0;; ++fmt) {
288a9643ea8Slogwang n = n * 10 + ch - '0';
289a9643ea8Slogwang ch = *fmt;
290a9643ea8Slogwang if (ch < '0' || ch > '9')
291a9643ea8Slogwang break;
292a9643ea8Slogwang }
293a9643ea8Slogwang if (dot)
294a9643ea8Slogwang dwidth = n;
295a9643ea8Slogwang else
296a9643ea8Slogwang width = n;
297a9643ea8Slogwang goto reswitch;
298a9643ea8Slogwang case 'b':
299a9643ea8Slogwang num = (u_int)va_arg(ap, int);
300a9643ea8Slogwang p = va_arg(ap, char *);
301a9643ea8Slogwang for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
302a9643ea8Slogwang PCHAR(*q--);
303a9643ea8Slogwang
304a9643ea8Slogwang if (num == 0)
305a9643ea8Slogwang break;
306a9643ea8Slogwang
307a9643ea8Slogwang for (tmp = 0; *p;) {
308a9643ea8Slogwang n = *p++;
309a9643ea8Slogwang if (num & (1 << (n - 1))) {
310a9643ea8Slogwang PCHAR(tmp ? ',' : '<');
311a9643ea8Slogwang for (; (n = *p) > ' '; ++p)
312a9643ea8Slogwang PCHAR(n);
313a9643ea8Slogwang tmp = 1;
314a9643ea8Slogwang } else
315a9643ea8Slogwang for (; *p > ' '; ++p)
316a9643ea8Slogwang continue;
317a9643ea8Slogwang }
318a9643ea8Slogwang if (tmp)
319a9643ea8Slogwang PCHAR('>');
320a9643ea8Slogwang break;
321a9643ea8Slogwang case 'c':
322a9643ea8Slogwang PCHAR(va_arg(ap, int));
323a9643ea8Slogwang break;
324a9643ea8Slogwang case 'D':
325a9643ea8Slogwang up = va_arg(ap, u_char *);
326a9643ea8Slogwang p = va_arg(ap, char *);
327a9643ea8Slogwang if (!width)
328a9643ea8Slogwang width = 16;
329a9643ea8Slogwang while(width--) {
330a9643ea8Slogwang PCHAR(hex2ascii(*up >> 4));
331a9643ea8Slogwang PCHAR(hex2ascii(*up & 0x0f));
332a9643ea8Slogwang up++;
333a9643ea8Slogwang if (width)
334a9643ea8Slogwang for (q=p;*q;q++)
335a9643ea8Slogwang PCHAR(*q);
336a9643ea8Slogwang }
337a9643ea8Slogwang break;
338a9643ea8Slogwang case 'd':
339a9643ea8Slogwang case 'i':
340a9643ea8Slogwang base = 10;
341a9643ea8Slogwang sign = 1;
342a9643ea8Slogwang goto handle_sign;
343a9643ea8Slogwang case 'h':
344a9643ea8Slogwang if (hflag) {
345a9643ea8Slogwang hflag = 0;
346a9643ea8Slogwang cflag = 1;
347a9643ea8Slogwang } else
348a9643ea8Slogwang hflag = 1;
349a9643ea8Slogwang goto reswitch;
350a9643ea8Slogwang case 'j':
351a9643ea8Slogwang jflag = 1;
352a9643ea8Slogwang goto reswitch;
353a9643ea8Slogwang case 'l':
354a9643ea8Slogwang if (lflag) {
355a9643ea8Slogwang lflag = 0;
356a9643ea8Slogwang qflag = 1;
357a9643ea8Slogwang } else
358a9643ea8Slogwang lflag = 1;
359a9643ea8Slogwang goto reswitch;
360a9643ea8Slogwang case 'n':
361a9643ea8Slogwang if (jflag)
362a9643ea8Slogwang *(va_arg(ap, intmax_t *)) = retval;
363a9643ea8Slogwang else if (qflag)
364a9643ea8Slogwang *(va_arg(ap, quad_t *)) = retval;
365a9643ea8Slogwang else if (lflag)
366a9643ea8Slogwang *(va_arg(ap, long *)) = retval;
367a9643ea8Slogwang else if (zflag)
368a9643ea8Slogwang *(va_arg(ap, size_t *)) = retval;
369a9643ea8Slogwang else if (hflag)
370a9643ea8Slogwang *(va_arg(ap, short *)) = retval;
371a9643ea8Slogwang else if (cflag)
372a9643ea8Slogwang *(va_arg(ap, char *)) = retval;
373a9643ea8Slogwang else
374a9643ea8Slogwang *(va_arg(ap, int *)) = retval;
375a9643ea8Slogwang break;
376a9643ea8Slogwang case 'o':
377a9643ea8Slogwang base = 8;
378a9643ea8Slogwang goto handle_nosign;
379a9643ea8Slogwang case 'p':
380a9643ea8Slogwang base = 16;
381a9643ea8Slogwang sharpflag = (width == 0);
382a9643ea8Slogwang sign = 0;
383a9643ea8Slogwang num = (uintptr_t)va_arg(ap, void *);
384a9643ea8Slogwang goto number;
385a9643ea8Slogwang case 'q':
386a9643ea8Slogwang qflag = 1;
387a9643ea8Slogwang goto reswitch;
388a9643ea8Slogwang case 'r':
389a9643ea8Slogwang base = radix;
390a9643ea8Slogwang if (sign)
391a9643ea8Slogwang goto handle_sign;
392a9643ea8Slogwang goto handle_nosign;
393a9643ea8Slogwang case 's':
394a9643ea8Slogwang p = va_arg(ap, char *);
395a9643ea8Slogwang if (p == NULL)
396a9643ea8Slogwang p = "(null)";
397a9643ea8Slogwang if (!dot)
398a9643ea8Slogwang n = strlen (p);
399a9643ea8Slogwang else
400a9643ea8Slogwang for (n = 0; n < dwidth && p[n]; n++)
401a9643ea8Slogwang continue;
402a9643ea8Slogwang
403a9643ea8Slogwang width -= n;
404a9643ea8Slogwang
405a9643ea8Slogwang if (!ladjust && width > 0)
406a9643ea8Slogwang while (width--)
407a9643ea8Slogwang PCHAR(padc);
408a9643ea8Slogwang while (n--)
409a9643ea8Slogwang PCHAR(*p++);
410a9643ea8Slogwang if (ladjust && width > 0)
411a9643ea8Slogwang while (width--)
412a9643ea8Slogwang PCHAR(padc);
413a9643ea8Slogwang break;
414a9643ea8Slogwang case 't':
415a9643ea8Slogwang tflag = 1;
416a9643ea8Slogwang goto reswitch;
417a9643ea8Slogwang case 'u':
418a9643ea8Slogwang base = 10;
419a9643ea8Slogwang goto handle_nosign;
420a9643ea8Slogwang case 'X':
421a9643ea8Slogwang upper = 1;
422a9643ea8Slogwang case 'x':
423a9643ea8Slogwang base = 16;
424a9643ea8Slogwang goto handle_nosign;
425a9643ea8Slogwang case 'y':
426a9643ea8Slogwang base = 16;
427a9643ea8Slogwang sign = 1;
428a9643ea8Slogwang goto handle_sign;
429a9643ea8Slogwang case 'z':
430a9643ea8Slogwang zflag = 1;
431a9643ea8Slogwang goto reswitch;
432a9643ea8Slogwang handle_nosign:
433a9643ea8Slogwang sign = 0;
434a9643ea8Slogwang if (jflag)
435a9643ea8Slogwang num = va_arg(ap, uintmax_t);
436a9643ea8Slogwang else if (qflag)
437a9643ea8Slogwang num = va_arg(ap, u_quad_t);
438a9643ea8Slogwang else if (tflag)
439a9643ea8Slogwang num = va_arg(ap, ptrdiff_t);
440a9643ea8Slogwang else if (lflag)
441a9643ea8Slogwang num = va_arg(ap, u_long);
442a9643ea8Slogwang else if (zflag)
443a9643ea8Slogwang num = va_arg(ap, size_t);
444a9643ea8Slogwang else if (hflag)
445a9643ea8Slogwang num = (u_short)va_arg(ap, int);
446a9643ea8Slogwang else if (cflag)
447a9643ea8Slogwang num = (u_char)va_arg(ap, int);
448a9643ea8Slogwang else
449a9643ea8Slogwang num = va_arg(ap, u_int);
450a9643ea8Slogwang goto number;
451a9643ea8Slogwang handle_sign:
452a9643ea8Slogwang if (jflag)
453a9643ea8Slogwang num = va_arg(ap, intmax_t);
454a9643ea8Slogwang else if (qflag)
455a9643ea8Slogwang num = va_arg(ap, quad_t);
456a9643ea8Slogwang else if (tflag)
457a9643ea8Slogwang num = va_arg(ap, ptrdiff_t);
458a9643ea8Slogwang else if (lflag)
459a9643ea8Slogwang num = va_arg(ap, long);
460a9643ea8Slogwang else if (zflag)
461a9643ea8Slogwang num = va_arg(ap, ssize_t);
462a9643ea8Slogwang else if (hflag)
463a9643ea8Slogwang num = (short)va_arg(ap, int);
464a9643ea8Slogwang else if (cflag)
465a9643ea8Slogwang num = (char)va_arg(ap, int);
466a9643ea8Slogwang else
467a9643ea8Slogwang num = va_arg(ap, int);
468a9643ea8Slogwang number:
469a9643ea8Slogwang if (sign && (intmax_t)num < 0) {
470a9643ea8Slogwang neg = 1;
471a9643ea8Slogwang num = -(intmax_t)num;
472a9643ea8Slogwang }
473a9643ea8Slogwang p = ksprintn(nbuf, num, base, &n, upper);
474a9643ea8Slogwang tmp = 0;
475a9643ea8Slogwang if (sharpflag && num != 0) {
476a9643ea8Slogwang if (base == 8)
477a9643ea8Slogwang tmp++;
478a9643ea8Slogwang else if (base == 16)
479a9643ea8Slogwang tmp += 2;
480a9643ea8Slogwang }
481a9643ea8Slogwang if (neg)
482a9643ea8Slogwang tmp++;
483a9643ea8Slogwang
484a9643ea8Slogwang if (!ladjust && padc == '0')
485a9643ea8Slogwang dwidth = width - tmp;
486a9643ea8Slogwang width -= tmp + imax(dwidth, n);
487a9643ea8Slogwang dwidth -= n;
488a9643ea8Slogwang if (!ladjust)
489a9643ea8Slogwang while (width-- > 0)
490a9643ea8Slogwang PCHAR(' ');
491a9643ea8Slogwang if (neg)
492a9643ea8Slogwang PCHAR('-');
493a9643ea8Slogwang if (sharpflag && num != 0) {
494a9643ea8Slogwang if (base == 8) {
495a9643ea8Slogwang PCHAR('0');
496a9643ea8Slogwang } else if (base == 16) {
497a9643ea8Slogwang PCHAR('0');
498a9643ea8Slogwang PCHAR('x');
499a9643ea8Slogwang }
500a9643ea8Slogwang }
501a9643ea8Slogwang while (dwidth-- > 0)
502a9643ea8Slogwang PCHAR('0');
503a9643ea8Slogwang
504a9643ea8Slogwang while (*p)
505a9643ea8Slogwang PCHAR(*p--);
506a9643ea8Slogwang
507a9643ea8Slogwang if (ladjust)
508a9643ea8Slogwang while (width-- > 0)
509a9643ea8Slogwang PCHAR(' ');
510a9643ea8Slogwang
511a9643ea8Slogwang break;
512a9643ea8Slogwang default:
513a9643ea8Slogwang while (percent < fmt)
514a9643ea8Slogwang PCHAR(*percent++);
515a9643ea8Slogwang /*
516a9643ea8Slogwang * Since we ignore an formatting argument it is no
517a9643ea8Slogwang * longer safe to obey the remaining formatting
518a9643ea8Slogwang * arguments as the arguments will no longer match
519a9643ea8Slogwang * the format specs.
520a9643ea8Slogwang */
521a9643ea8Slogwang stop = 1;
522a9643ea8Slogwang break;
523a9643ea8Slogwang }
524a9643ea8Slogwang }
525a9643ea8Slogwang #undef PCHAR
526a9643ea8Slogwang }
527a9643ea8Slogwang
528a9643ea8Slogwang int
printf(const char * fmt,...)529a9643ea8Slogwang printf(const char *fmt, ...)
530a9643ea8Slogwang {
531a9643ea8Slogwang va_list ap;
532a9643ea8Slogwang int retval;
533a9643ea8Slogwang
534a9643ea8Slogwang va_start(ap, fmt);
535a9643ea8Slogwang retval = vprintf(fmt, ap);
536a9643ea8Slogwang va_end(ap);
537a9643ea8Slogwang
538a9643ea8Slogwang return (retval);
539a9643ea8Slogwang }
540a9643ea8Slogwang
541a9643ea8Slogwang int
vprintf(const char * fmt,va_list ap)542a9643ea8Slogwang vprintf(const char *fmt, va_list ap)
543a9643ea8Slogwang {
544a9643ea8Slogwang struct putchar_arg pca;
545a9643ea8Slogwang int retval;
546a9643ea8Slogwang #ifdef PRINTF_BUFR_SIZE
547a9643ea8Slogwang char bufr[PRINTF_BUFR_SIZE];
548a9643ea8Slogwang #endif
549a9643ea8Slogwang
550a9643ea8Slogwang pca.tty = NULL;
551a9643ea8Slogwang pca.flags = TOCONS | TOLOG;
552a9643ea8Slogwang pca.pri = -1;
553a9643ea8Slogwang #ifdef PRINTF_BUFR_SIZE
554a9643ea8Slogwang pca.p_bufr = bufr;
555a9643ea8Slogwang pca.p_next = pca.p_bufr;
556a9643ea8Slogwang pca.n_bufr = sizeof(bufr);
557a9643ea8Slogwang pca.remain = sizeof(bufr);
558a9643ea8Slogwang *pca.p_next = '\0';
559a9643ea8Slogwang #else
560a9643ea8Slogwang /* Don't buffer console output. */
561a9643ea8Slogwang pca.p_bufr = NULL;
562a9643ea8Slogwang #endif
563a9643ea8Slogwang
564a9643ea8Slogwang retval = kvprintf(fmt, kputchar, &pca, 10, ap);
565a9643ea8Slogwang
566a9643ea8Slogwang #ifdef PRINTF_BUFR_SIZE
567a9643ea8Slogwang /* Write any buffered console/log output: */
568a9643ea8Slogwang if (*pca.p_bufr != '\0') {
569a9643ea8Slogwang cnputs(pca.p_bufr);
570a9643ea8Slogwang msglogstr(pca.p_bufr, pca.pri, /*filter_cr*/ 1);
571a9643ea8Slogwang }
572a9643ea8Slogwang #endif
573a9643ea8Slogwang
574a9643ea8Slogwang return (retval);
575a9643ea8Slogwang }
576*22ce4affSfengbojiang
577*22ce4affSfengbojiang void
vlog(int level,const char * fmt,va_list ap)578*22ce4affSfengbojiang vlog(int level, const char *fmt, va_list ap)
579*22ce4affSfengbojiang {
580*22ce4affSfengbojiang (void)vprintf(fmt, ap);
581*22ce4affSfengbojiang }
582*22ce4affSfengbojiang
583*22ce4affSfengbojiang int
sbuf_printf_drain(void * arg,const char * data,int len)584*22ce4affSfengbojiang sbuf_printf_drain(void *arg, const char *data, int len)
585*22ce4affSfengbojiang {
586*22ce4affSfengbojiang return 0;
587*22ce4affSfengbojiang }
588*22ce4affSfengbojiang
589