|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23: /*-
24: * Copyright (c) 1986, 1988, 1991, 1993
25: * The Regents of the University of California. All rights reserved.
26: * (c) UNIX System Laboratories, Inc.
27: * All or some portions of this file are derived from material licensed
28: * to the University of California by American Telephone and Telegraph
29: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30: * the permission of UNIX System Laboratories, Inc.
31: *
32: * Redistribution and use in source and binary forms, with or without
33: * modification, are permitted provided that the following conditions
34: * are met:
35: * 1. Redistributions of source code must retain the above copyright
36: * notice, this list of conditions and the following disclaimer.
37: * 2. Redistributions in binary form must reproduce the above copyright
38: * notice, this list of conditions and the following disclaimer in the
39: * documentation and/or other materials provided with the distribution.
40: * 3. All advertising materials mentioning features or use of this software
41: * must display the following acknowledgement:
42: * This product includes software developed by the University of
43: * California, Berkeley and its contributors.
44: * 4. Neither the name of the University nor the names of its contributors
45: * may be used to endorse or promote products derived from this software
46: * without specific prior written permission.
47: *
48: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58: * SUCH DAMAGE.
59: *
60: * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95
61: */
62: /* HISTORY
63: * 22-Sep-1997 Umesh Vaishampayan ([email protected])
64: * Cleaned up m68k crud. Fixed vlog() to do logpri() for ppc, too.
65: *
66: * 17-July-97 Umesh Vaishampayan ([email protected])
67: * Eliminated multiple definition of constty which is defined
68: * in bsd/dev/XXX/cons.c
69: *
70: * 26-MAR-1997 Umesh Vaishampayan ([email protected]
71: * Fixed tharshing format in many functions. Cleanup.
72: *
73: * 17-Jun-1995 Mac Gillon (mgillon) at NeXT
74: * Purged old history
75: * New version based on 4.4 and NS3.3
76: */
77:
78: #include <sys/param.h>
79: #include <sys/systm.h>
80: #include <sys/buf.h>
81: #include <sys/conf.h>
82: #include <sys/reboot.h>
83: #include <sys/msgbuf.h>
84: #include <sys/proc.h>
85: #include <sys/ioctl.h>
86: #include <sys/tty.h>
87: #include <sys/file.h>
88: #include <sys/tprintf.h>
89: #include <sys/syslog.h>
90: #include <stdarg.h>
91: #include <sys/malloc.h>
92: #include <sys/lock.h>
93: #include <kern/parallel.h>
94: #import <sys/subr_prf.h>
95:
96: #include <kern/cpu_number.h> /* for cpu_number() */
97: #include <machine/spl.h>
98: #include <libkern/libkern.h>
99:
100: struct snprintf_arg {
101: char *str;
102: size_t remain;
103: };
104:
105:
106: /*
107: * In case console is off,
108: * panicstr contains argument to last
109: * call to panic.
110: */
111: extern const char *panicstr;
112:
113: extern cnputc(); /* standard console putc */
114: int (*v_putc)() = cnputc; /* routine to putc on virtual console */
115:
116: extern struct tty cons; /* standard console tty */
117: extern struct tty *constty; /* pointer to console "window" tty */
118:
119: /*
120: * Record cpu that panic'd and lock around panic data
121: */
122:
123: static void puts(const char *s, int flags, struct tty *ttyp);
124: static void printn(u_long n, int b, int flags, struct tty *ttyp, int zf, int fld_size);
125:
126: /* MP printf stuff */
127: decl_simple_lock_data(,printf_lock)
128: #if NCPUS > 1
129: boolean_t new_printf_cpu_number; /* do we need to output who we are */
130: #endif
131:
132: extern void logwakeup();
133: extern void halt_cpu();
134: #if NeXT
135: extern void mini_mon();
136: #endif /* NeXT */
137: extern boot();
138: int putchar();
139:
140: static void
141: snprintf_func(int ch, void *arg);
142:
143:
144:
145: /*
146: * Uprintf prints to the controlling terminal for the current process.
147: * It may block if the tty queue is overfull. No message is printed if
148: * the queue does not clear in a reasonable time.
149: */
150: void
151: uprintf(const char *fmt, ...)
152: {
153: register struct proc *p = current_proc();
154: va_list ap;
155:
156: unix_master(); /* sessions, sigh */
157: if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
158: va_start(ap, fmt);
159: prf(fmt, ap, TOTTY, (struct tty *)p->p_session->s_ttyvp);
160: va_end(ap);
161: }
162: unix_release();
163: }
164:
165: tpr_t
166: tprintf_open(p)
167: register struct proc *p;
168: {
169: unix_master(); /* sessions, sigh */
170: if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
171: SESSHOLD(p->p_session);
172: unix_release();
173: return ((tpr_t) p->p_session);
174: }
175: unix_release();
176: return ((tpr_t) NULL);
177: }
178:
179: void
180: tprintf_close(sess)
181: tpr_t sess;
182: {
183: unix_master(); /* sessions, sigh */
184: if (sess)
185: SESSRELE((struct session *) sess);
186: unix_release();
187: }
188:
189: /*
190: * tprintf prints on the controlling terminal associated
191: * with the given session.
192: */
193: void
194: tprintf(tpr_t tpr, const char *fmt, ...)
195: {
196: register struct session *sess = (struct session *)tpr;
197: struct tty *tp = NULL;
198: int flags = TOLOG;
199: va_list ap;
200:
201: logpri(LOG_INFO);
202: unix_master(); /* sessions, sigh */
203: if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
204: flags |= TOTTY;
205: tp = sess->s_ttyp;
206: }
207: if (tp != NULL) {
208: va_start(ap, fmt);
209: prf(fmt, ap, TOTTY, tp);
210: va_end(ap);
211: }
212: unix_release();
213: logwakeup();
214: }
215:
216: /*
217: * Ttyprintf displays a message on a tty; it should be used only by
218: * the tty driver, or anything that knows the underlying tty will not
219: * be revoke(2)'d away. Other callers should use tprintf.
220: */
221: void
222: ttyprintf(struct tty *tp, const char *fmt, ...)
223: {
224: va_list ap;
225:
226: if (tp != NULL) {
227: va_start(ap, fmt);
228: prf(fmt, ap, TOTTY, tp);
229: va_end(ap);
230: }
231: }
232:
233: extern int log_open;
234:
235:
236: void
237: logpri(level)
238: int level;
239: {
240:
241: putchar('<', TOLOG, (struct tty *)0);
242: printn((u_long)level, 10, TOLOG, (struct tty *)0, 0, 0);
243: putchar('>', TOLOG, (struct tty *)0);
244: }
245:
246: void
247: addlog(const char *fmt, ...)
248: {
249: register s = splhigh();
250: va_list ap;
251:
252: va_start(ap, fmt);
253: prf(fmt, ap, TOLOG, (struct tty *)0);
254: splx(s);
255: if (!log_open)
256: prf(fmt, ap, TOCONS, (struct tty *)0);
257: va_end(ap);
258: logwakeup();
259: }
260: void _printf(int flags, struct tty *ttyp, const char *format, ...)
261: {
262: va_list ap;
263:
264: va_start(ap, format);
265: prf(format, ap, flags, ttyp);
266: va_end(ap);
267: }
268:
269: int prf(const char *fmt, va_list ap, int flags, struct tty *ttyp)
270: {
271: register int b, c, i;
272: char *s;
273: int any;
274: int zf = 0, fld_size;
275:
276: #if NCPUS > 1
277: int cpun = cpu_number();
278:
279: if(ttyp == 0) {
280: simple_lock(&printf_lock);
281: } else
282: TTY_LOCK(ttyp);
283:
284: if (cpun != master_cpu)
285: new_printf_cpu_number = TRUE;
286:
287: if (new_printf_cpu_number) {
288: putchar('{', flags, ttyp);
289: printn((u_long)cpun, 10, flags, ttyp, 0, 0);
290: putchar('}', flags, ttyp);
291: }
292: #endif /* NCPUS > 1 */
293: loop:
294: while ((c = *fmt++) != '%') {
295: if (c == '\0') {
296: #if NCPUS > 1
297: if(ttyp == 0) {
298: simple_unlock(&printf_lock);
299: } else
300: TTY_UNLOCK(ttyp);
301: #endif
302: return 0;
303: }
304: putchar(c, flags, ttyp);
305: }
306: again:
307: zf = 0;
308: fld_size = 0;
309: c = *fmt++;
310: if (c == '0')
311: zf = '0';
312: fld_size = 0;
313: for (;c <= '9' && c >= '0'; c = *fmt++)
314: fld_size = fld_size * 10 + c - '0';
315:
316: /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
317: switch (c) {
318:
319: case 'l':
320: goto again;
321: case 'x': case 'X':
322: b = 16;
323: goto number;
324: case 'd': case 'D':
325: case 'u': /* what a joke */
326: b = 10;
327: goto number;
328: case 'o': case 'O':
329: b = 8;
330: number:
331: printn(va_arg(ap, unsigned), b, flags, ttyp, zf, fld_size);
332: break;
333: case 'c':
334: b = va_arg(ap, unsigned);
335: #if BYTE_ORDER == LITTLE_ENDIAN
336: for (i = 24; i >= 0; i -= 8)
337: if (c = (b >> i) & 0x7f)
338: putchar(c, flags, ttyp);
339: #endif
340: #if BYTE_ORDER == BIG_ENDIAN
341: if ((c = (b & 0x7f)))
342: putchar(c, flags, ttyp);
343: #endif
344: break;
345: case 'b':
346: b = va_arg(ap, unsigned);
347: s = va_arg(ap, char *);
348: printn((u_long)b, *s++, flags, ttyp, 0, 0);
349: any = 0;
350: if (b) {
351: while ((i = *s++)) {
352: if (*s <= 32) {
353: register int j;
354:
355: if (any++)
356: putchar(',', flags, ttyp);
357: j = *s++ ;
358: for (; (c = *s) > 32 ; s++)
359: putchar(c, flags, ttyp);
360: printn( (u_long)( (b >> (j-1)) &
361: ( (2 << (i-j)) -1)),
362: 8, flags, ttyp, 0, 0);
363: } else if (b & (1 << (i-1))) {
364: putchar(any? ',' : '<', flags, ttyp);
365: any = 1;
366: for (; (c = *s) > 32; s++)
367: putchar(c, flags, ttyp);
368: } else
369: for (; *s > 32; s++)
370: ;
371: }
372: putchar('>', flags, ttyp);
373: }
374: break;
375:
376: case 's':
377: s = va_arg(ap, char *);
378: #ifdef DEBUG
379: if (fld_size) {
380: while (fld_size-- > 0)
381: putchar((c = *s++)? c : '_', flags, ttyp);
382: } else {
383: while ((c = *s++))
384: putchar(c, flags, ttyp);
385: }
386: #else
387: while (c = *s++)
388: putchar(c, flags, ttyp);
389: #endif
390: break;
391:
392: case '%':
393: putchar('%', flags, ttyp);
394: goto loop;
395: case 'C':
396: b = va_arg(ap, unsigned);
397: #if BYTE_ORDER == LITTLE_ENDIAN
398: for (i = 24; i >= 0; i -= 8)
399: if (c = (b >> i) & 0x7f)
400: putchar(c, flags, ttyp);
401: #endif
402: #if BYTE_ORDER == BIG_ENDIAN
403: if ((c = (b & 0x7f)))
404: putchar(c, flags, ttyp);
405: #endif
406:
407: case 'r':
408: case 'R':
409: b = va_arg(ap, unsigned);
410: s = va_arg(ap, char *);
411: if (c == 'R') {
412: puts("0x", flags, ttyp);
413: printn((u_long)b, 16, flags, ttyp, 0, 0);
414: }
415: any = 0;
416: if (c == 'r' || b) {
417: register struct reg_desc *rd;
418: register struct reg_values *rv;
419: unsigned field;
420:
421: putchar('<', flags, ttyp);
422: for (rd = (struct reg_desc *)s; rd->rd_mask; rd++) {
423: field = b & rd->rd_mask;
424: field = (rd->rd_shift > 0)
425: ? field << rd->rd_shift
426: : field >> -rd->rd_shift;
427: if (any &&
428: (rd->rd_format || rd->rd_values
429: || (rd->rd_name && field)
430: )
431: )
432: putchar(',', flags, ttyp);
433: if (rd->rd_name) {
434: if (rd->rd_format || rd->rd_values
435: || field) {
436: puts(rd->rd_name, flags, ttyp);
437: any = 1;
438: }
439: if (rd->rd_format || rd->rd_values) {
440: putchar('=', flags, ttyp);
441: any = 1;
442: }
443: }
444: if (rd->rd_format) {
445: _printf(flags, ttyp, rd->rd_format,
446: field);
447: any = 1;
448: if (rd->rd_values)
449: putchar(':', flags, ttyp);
450: }
451: if (rd->rd_values) {
452: any = 1;
453: for (rv = rd->rd_values;
454: rv->rv_name;
455: rv++) {
456: if (field == rv->rv_value) {
457: puts(rv->rv_name, flags,
458: ttyp);
459: break;
460: }
461: }
462: if (rv->rv_name == NULL)
463: puts("???", flags, ttyp);
464: }
465: }
466: putchar('>', flags, ttyp);
467: }
468: break;
469:
470: case 'n':
471: case 'N':
472: {
473: register struct reg_values *rv;
474:
475: b = va_arg(ap, unsigned);
476: s = va_arg(ap,char *);
477: for (rv = (struct reg_values *)s; rv->rv_name; rv++) {
478: if (b == rv->rv_value) {
479: puts(rv->rv_name, flags, ttyp);
480: break;
481: }
482: }
483: if (rv->rv_name == NULL)
484: puts("???", flags, ttyp);
485: if (c == 'N' || rv->rv_name == NULL) {
486: putchar(':', flags, ttyp);
487: printn((u_long)b, 10, flags, ttyp, 0, 0);
488: }
489: }
490: break;
491: }
492: goto loop;
493: }
494:
495: static void puts(const char *s, int flags, struct tty *ttyp)
496: {
497: register char c;
498:
499: while ((c = *s++))
500: putchar(c, flags, ttyp);
501: }
502:
503: /*
504: * Printn prints a number n in base b.
505: * We don't use recursion to avoid deep kernel stacks.
506: */
507: static void printn(u_long n, int b, int flags, struct tty *ttyp, int zf, int fld_size)
508: {
509: char prbuf[11];
510: register char *cp;
511:
512: if (b == 10 && (int)n < 0) {
513: putchar('-', flags, ttyp);
514: n = (unsigned)(-(int)n);
515: }
516: cp = prbuf;
517: do {
518: *cp++ = "0123456789abcdef"[n%b];
519: n /= b;
520: } while (n);
521: if (fld_size) {
522: for (fld_size -= cp - prbuf; fld_size > 0; fld_size--)
523: if (zf)
524: putchar('0', flags, ttyp);
525: else
526: putchar(' ', flags, ttyp);
527: }
528: do
529: putchar(*--cp, flags, ttyp);
530: while (cp > prbuf);
531: }
532:
533:
534:
535: /*
536: * Warn that a system table is full.
537: */
538: void tablefull(const char *tab)
539: {
540: log(LOG_ERR, "%s: table is full\n", tab);
541: }
542:
543: /*
544: * Print a character on console or users terminal.
545: * If destination is console then the last MSGBUFS characters
546: * are saved in msgbuf for inspection later.
547: */
548: /*ARGSUSED*/
549: int
550: putchar(c, flags, tp)
551: register int c;
552: struct tty *tp;
553: {
554: register struct msgbuf *mbp;
555: char **sp = (char**) tp;
556:
557: if (panicstr)
558: constty = 0;
559: if ((flags & TOCONS) && tp == NULL && constty) {
560: tp = constty;
561: flags |= TOTTY;
562: }
563: if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
564: (flags & TOCONS) && tp == constty)
565: constty = 0;
566: if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177)
567: log_putc(c);
568: if ((flags & TOCONS) && constty == 0 && c != '\0')
569: (*v_putc)(c);
570: if (flags & TOSTR) {
571: **sp = c;
572: (*sp)++;
573: }
574: return 0;
575: }
576:
577:
578:
579: /*
580: * Scaled down version of vsprintf(3).
581: */
582: int
583: vsprintf(char *buf, const char *cfmt, va_list ap)
584: {
585: int retval;
586:
587: retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
588: buf[retval] = '\0';
589: return retval;
590: }
591:
592: /*
593: * Scaled down version of snprintf(3).
594: */
595: int
596: snprintf(char *str, size_t size, const char *format, ...)
597: {
598: int retval;
599: va_list ap;
600:
601: va_start(ap, format);
602: retval = vsnprintf(str, size, format, ap);
603: va_end(ap);
604: return(retval);
605: }
606:
607: /*
608: * Scaled down version of vsnprintf(3).
609: */
610: int
611: vsnprintf(char *str, size_t size, const char *format, va_list ap)
612: {
613: struct snprintf_arg info;
614: int retval;
615:
616: info.str = str;
617: info.remain = size;
618: retval = kvprintf(format, snprintf_func, &info, 10, ap);
619: if (info.remain >= 1)
620: *info.str++ = '\0';
621: return retval;
622: }
623:
624: static void
625: snprintf_func(int ch, void *arg)
626: {
627: struct snprintf_arg *const info = arg;
628:
629: if (info->remain >= 2) {
630: *info->str++ = ch;
631: info->remain--;
632: }
633: }
634:
635: /*
636: * Put a number (base <= 16) in a buffer in reverse order; return an
637: * optional length and a pointer to the NULL terminated (preceded?)
638: * buffer.
639: */
640: static char *
641: ksprintn(ul, base, lenp)
642: register u_long ul;
643: register int base, *lenp;
644: { /* A long in base 8, plus NULL. */
645: static char buf[sizeof(long) * NBBY / 3 + 2];
646: register char *p;
647:
648: p = buf;
649: do {
650: *++p = hex2ascii(ul % base);
651: } while (ul /= base);
652: if (lenp)
653: *lenp = p - buf;
654: return (p);
655: }
656:
657: /*
658: * Scaled down version of printf(3).
659: *
660: * Two additional formats:
661: *
662: * The format %b is supported to decode error registers.
663: * Its usage is:
664: *
665: * printf("reg=%b\n", regval, "<base><arg>*");
666: *
667: * where <base> is the output base expressed as a control character, e.g.
668: * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
669: * the first of which gives the bit number to be inspected (origin 1), and
670: * the next characters (up to a control character, i.e. a character <= 32),
671: * give the name of the register. Thus:
672: *
673: * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
674: *
675: * would produce output:
676: *
677: * reg=3<BITTWO,BITONE>
678: *
679: * XXX: %D -- Hexdump, takes pointer and separator string:
680: * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
681: * ("%*D", len, ptr, " " -> XX XX XX XX ...
682: */
683: int
684: kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
685: {
686: #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
687: char *p, *q, *d;
688: u_char *up;
689: int ch, n;
690: u_long ul;
691: int base, lflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
692: int dwidth;
693: char padc;
694: int retval = 0;
695:
696: if (!func)
697: d = (char *) arg;
698: else
699: d = NULL;
700:
701: if (fmt == NULL)
702: fmt = "(fmt null)\n";
703:
704: if (radix < 2 || radix > 36)
705: radix = 10;
706:
707: for (;;) {
708: padc = ' ';
709: width = 0;
710: while ((ch = (u_char)*fmt++) != '%') {
711: if (ch == '\0')
712: return retval;
713: PCHAR(ch);
714: }
715: lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
716: sign = 0; dot = 0; dwidth = 0;
717: reswitch: switch (ch = (u_char)*fmt++) {
718: case '.':
719: dot = 1;
720: goto reswitch;
721: case '#':
722: sharpflag = 1;
723: goto reswitch;
724: case '+':
725: sign = 1;
726: goto reswitch;
727: case '-':
728: ladjust = 1;
729: goto reswitch;
730: case '%':
731: PCHAR(ch);
732: break;
733: case '*':
734: if (!dot) {
735: width = va_arg(ap, int);
736: if (width < 0) {
737: ladjust = !ladjust;
738: width = -width;
739: }
740: } else {
741: dwidth = va_arg(ap, int);
742: }
743: goto reswitch;
744: case '0':
745: if (!dot) {
746: padc = '0';
747: goto reswitch;
748: }
749: case '1': case '2': case '3': case '4':
750: case '5': case '6': case '7': case '8': case '9':
751: for (n = 0;; ++fmt) {
752: n = n * 10 + ch - '0';
753: ch = *fmt;
754: if (ch < '0' || ch > '9')
755: break;
756: }
757: if (dot)
758: dwidth = n;
759: else
760: width = n;
761: goto reswitch;
762: case 'b':
763: ul = va_arg(ap, int);
764: p = va_arg(ap, char *);
765: for (q = ksprintn(ul, *p++, NULL); *q;)
766: PCHAR(*q--);
767:
768: if (!ul)
769: break;
770:
771: for (tmp = 0; *p;) {
772: n = *p++;
773: if (ul & (1 << (n - 1))) {
774: PCHAR(tmp ? ',' : '<');
775: for (; (n = *p) > ' '; ++p)
776: PCHAR(n);
777: tmp = 1;
778: } else
779: for (; *p > ' '; ++p)
780: continue;
781: }
782: if (tmp)
783: PCHAR('>');
784: break;
785: case 'c':
786: PCHAR(va_arg(ap, int));
787: break;
788: case 'D':
789: up = va_arg(ap, u_char *);
790: p = va_arg(ap, char *);
791: if (!width)
792: width = 16;
793: while(width--) {
794: PCHAR(hex2ascii(*up >> 4));
795: PCHAR(hex2ascii(*up & 0x0f));
796: up++;
797: if (width)
798: for (q=p;*q;q++)
799: PCHAR(*q);
800: }
801: break;
802: case 'd':
803: ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
804: sign = 1;
805: base = 10;
806: goto number;
807: case 'l':
808: lflag = 1;
809: goto reswitch;
810: case 'o':
811: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
812: base = 8;
813: goto nosign;
814: case 'p':
815: ul = (uintptr_t)va_arg(ap, void *);
816: base = 16;
817: sharpflag = (width == 0);
818: goto nosign;
819: case 'n':
820: case 'r':
821: ul = lflag ? va_arg(ap, u_long) :
822: sign ? (u_long)va_arg(ap, int) : va_arg(ap, u_int);
823: base = radix;
824: goto number;
825: case 's':
826: p = va_arg(ap, char *);
827: if (p == NULL)
828: p = "(null)";
829: if (!dot)
830: n = strlen (p);
831: else
832: for (n = 0; n < dwidth && p[n]; n++)
833: continue;
834:
835: width -= n;
836:
837: if (!ladjust && width > 0)
838: while (width--)
839: PCHAR(padc);
840: while (n--)
841: PCHAR(*p++);
842: if (ladjust && width > 0)
843: while (width--)
844: PCHAR(padc);
845: break;
846: case 'u':
847: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
848: base = 10;
849: goto nosign;
850: case 'x':
851: ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
852: base = 16;
853: goto nosign;
854: case 'z':
855: ul = lflag ? va_arg(ap, u_long) :
856: sign ? (u_long)va_arg(ap, int) : va_arg(ap, u_int);
857: base = 16;
858: goto number;
859: nosign: sign = 0;
860: number: if (sign && (long)ul < 0L) {
861: neg = 1;
862: ul = -(long)ul;
863: }
864: p = ksprintn(ul, base, &tmp);
865: if (sharpflag && ul != 0) {
866: if (base == 8)
867: tmp++;
868: else if (base == 16)
869: tmp += 2;
870: }
871: if (neg)
872: tmp++;
873:
874: if (!ladjust && width && (width -= tmp) > 0)
875: while (width--)
876: PCHAR(padc);
877: if (neg)
878: PCHAR('-');
879: if (sharpflag && ul != 0) {
880: if (base == 8) {
881: PCHAR('0');
882: } else if (base == 16) {
883: PCHAR('0');
884: PCHAR('x');
885: }
886: }
887:
888: while (*p)
889: PCHAR(*p--);
890:
891: if (ladjust && width && (width -= tmp) > 0)
892: while (width--)
893: PCHAR(padc);
894:
895: break;
896: default:
897: PCHAR('%');
898: if (lflag)
899: PCHAR('l');
900: PCHAR(ch);
901: break;
902: }
903: }
904: #undef PCHAR
905: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.