1 /* $NetBSD: subr_prf.c,v 1.12 2005/05/23 19:05:00 jmc Exp $ */ 2 3 /*- 4 * Copyright (c) 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)printf.c 8.1 (Berkeley) 6/11/93 32 */ 33 34 /* 35 * Scaled down version of printf(3). 36 */ 37 38 #include <sys/cdefs.h> 39 #include <sys/types.h> 40 #include <machine/stdarg.h> 41 42 #include "stand.h" 43 44 static void kprintn(void (*)(int), u_long, int); 45 static void sputchar(int); 46 static void kdoprnt(void (*)(int), const char *, va_list); 47 48 static char *sbuf, *ebuf; 49 50 const char HEXDIGITS[] = "0123456789ABCDEF"; 51 const char hexdigits[] = "0123456789abcdef"; 52 53 static void 54 sputchar(int c) 55 { 56 57 if (sbuf < ebuf) 58 *sbuf++ = c; 59 } 60 61 void 62 vprintf(const char *fmt, va_list ap) 63 { 64 65 kdoprnt(putchar, fmt, ap); 66 } 67 68 int 69 vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) 70 { 71 72 sbuf = buf; 73 ebuf = buf + size - 1; 74 kdoprnt(sputchar, fmt, ap); 75 *sbuf = '\0'; 76 return (sbuf - buf); 77 } 78 79 static void 80 kdoprnt(void (*put)(int), const char *fmt, va_list ap) 81 { 82 char *p; 83 int ch; 84 unsigned long ul; 85 int lflag; 86 87 for (;;) { 88 while ((ch = *fmt++) != '%') { 89 if (ch == '\0') 90 return; 91 put(ch); 92 } 93 lflag = 0; 94 reswitch: switch (ch = *fmt++) { 95 case 'l': 96 lflag = 1; 97 goto reswitch; 98 case 'c': 99 ch = va_arg(ap, int); 100 put(ch & 0x7f); 101 break; 102 case 's': 103 p = va_arg(ap, char *); 104 while ((ch = *p++)) 105 put(ch); 106 break; 107 case 'd': 108 ul = lflag ? 109 va_arg(ap, long) : va_arg(ap, int); 110 if ((long)ul < 0) { 111 put('-'); 112 ul = -(long)ul; 113 } 114 kprintn(put, ul, 10); 115 break; 116 case 'o': 117 ul = lflag ? 118 va_arg(ap, u_long) : va_arg(ap, u_int); 119 kprintn(put, ul, 8); 120 break; 121 case 'u': 122 ul = lflag ? 123 va_arg(ap, u_long) : va_arg(ap, u_int); 124 kprintn(put, ul, 10); 125 break; 126 case 'p': 127 put('0'); 128 put('x'); 129 lflag = 1; 130 /* fall through */ 131 case 'x': 132 ul = lflag ? 133 va_arg(ap, u_long) : va_arg(ap, u_int); 134 kprintn(put, ul, 16); 135 break; 136 default: 137 put('%'); 138 if (lflag) 139 put('l'); 140 if (ch == '\0') 141 return; 142 put(ch); 143 } 144 } 145 } 146 147 static void 148 kprintn(void (*put)(int), unsigned long ul, int base) 149 { 150 /* hold a long in base 8 */ 151 char *p, buf[(sizeof(long) * NBBY / 3) + 1]; 152 153 p = buf; 154 do { 155 *p++ = hexdigits[ul % base]; 156 } while (ul /= base); 157 do { 158 put(*--p); 159 } while (p > buf); 160 } 161