xref: /f-stack/lib/ff_subr_prf.c (revision 22ce4aff)
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