1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/promif.h> 30 #include <sys/promimpl.h> 31 #include <sys/varargs.h> 32 33 static void _doprint(const char *, va_list, void (*)(char, char **), char **); 34 static void _printn(uint64_t, int, int, int, void (*)(char, char **), char **); 35 36 /* 37 * Emit character functions... 38 */ 39 40 /*ARGSUSED*/ 41 static void 42 _pput(char c, char **p) 43 { 44 (void) prom_putchar(c); 45 } 46 47 static void 48 _sput(char c, char **p) 49 { 50 **p = c; 51 *p += 1; 52 } 53 54 /*VARARGS1*/ 55 void 56 prom_printf(const char *fmt, ...) 57 { 58 va_list adx; 59 60 va_start(adx, fmt); 61 (void) _doprint(fmt, adx, _pput, (char **)0); 62 va_end(adx); 63 } 64 65 void 66 prom_vprintf(const char *fmt, va_list adx) 67 { 68 va_list tadx; 69 70 va_copy(tadx, adx); 71 (void) _doprint(fmt, tadx, _pput, (char **)0); 72 va_end(tadx); 73 } 74 75 /*VARARGS2*/ 76 char * 77 prom_sprintf(char *s, const char *fmt, ...) 78 { 79 char *bp = s; 80 va_list adx; 81 82 va_start(adx, fmt); 83 (void) _doprint(fmt, adx, _sput, &bp); 84 *bp++ = (char)0; 85 va_end(adx); 86 return (s); 87 } 88 89 char * 90 prom_vsprintf(char *s, const char *fmt, va_list adx) 91 { 92 char *bp = s; 93 94 (void) _doprint(fmt, adx, _sput, &bp); 95 *bp++ = (char)0; 96 return (s); 97 } 98 99 static void 100 _doprint(const char *fmt, va_list adx, void (*emit)(char, char **), char **bp) 101 { 102 int b, c, i, pad, width, ells; 103 register char *s; 104 int64_t l; 105 uint64_t ul; 106 107 loop: 108 width = 0; 109 while ((c = *fmt++) != '%') { 110 if (c == '\0') 111 return; 112 if (c == '\n') 113 (*emit)('\r', bp); 114 (*emit)(c, bp); 115 } 116 117 c = *fmt++; 118 119 for (pad = ' '; c == '0'; c = *fmt++) 120 pad = '0'; 121 122 for (width = 0; c >= '0' && c <= '9'; c = *fmt++) 123 width = (width * 10) + (c - '0'); 124 125 for (ells = 0; c == 'l'; c = *fmt++) 126 ells++; 127 128 switch (c) { 129 130 case 'd': 131 case 'D': 132 b = 10; 133 if (ells == 0) 134 l = (int64_t)va_arg(adx, int); 135 else if (ells == 1) 136 l = (int64_t)va_arg(adx, long); 137 else 138 l = (int64_t)va_arg(adx, int64_t); 139 if (l < 0) { 140 (*emit)('-', bp); 141 width--; 142 ul = -l; 143 } else 144 ul = l; 145 goto number; 146 147 case 'p': 148 ells = 1; 149 /* FALLTHROUGH */ 150 case 'x': 151 case 'X': 152 b = 16; 153 goto u_number; 154 155 case 'u': 156 b = 10; 157 goto u_number; 158 159 case 'o': 160 case 'O': 161 b = 8; 162 u_number: 163 if (ells == 0) 164 ul = (uint64_t)va_arg(adx, uint_t); 165 else if (ells == 1) 166 ul = (uint64_t)va_arg(adx, ulong_t); 167 else 168 ul = (uint64_t)va_arg(adx, uint64_t); 169 number: 170 _printn(ul, b, width, pad, emit, bp); 171 break; 172 173 case 'c': 174 b = va_arg(adx, int); 175 for (i = 24; i >= 0; i -= 8) 176 if ((c = ((b >> i) & 0x7f)) != 0) { 177 if (c == '\n') 178 (*emit)('\r', bp); 179 (*emit)(c, bp); 180 } 181 break; 182 case 's': 183 s = va_arg(adx, char *); 184 while ((c = *s++) != 0) { 185 if (c == '\n') 186 (*emit)('\r', bp); 187 (*emit)(c, bp); 188 } 189 break; 190 191 case '%': 192 (*emit)('%', bp); 193 break; 194 } 195 goto loop; 196 } 197 198 /* 199 * Printn prints a number n in base b. 200 * We don't use recursion to avoid deep kernel stacks. 201 */ 202 static void 203 _printn(uint64_t n, int b, int width, int pad, void (*emit)(char, char **), 204 char **bp) 205 { 206 char prbuf[40]; 207 register char *cp; 208 209 cp = prbuf; 210 do { 211 *cp++ = "0123456789abcdef"[n%b]; 212 n /= b; 213 width--; 214 } while (n); 215 while (width-- > 0) 216 *cp++ = (char)pad; 217 do { 218 (*emit)(*--cp, bp); 219 } while (cp > prbuf); 220 } 221