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 #include <sys/promif.h> 28 #include <sys/promimpl.h> 29 #include <sys/varargs.h> 30 31 static void _doprint(const char *, va_list, void (*)(char, char **), char **); 32 static void _printn(uint64_t, int, int, int, void (*)(char, char **), char **); 33 34 /* 35 * Emit character functions... 36 */ 37 38 /*ARGSUSED*/ 39 static void 40 _pput(char c, char **p) 41 { 42 (void) prom_putchar(c); 43 } 44 45 static void 46 _sput(char c, char **p) 47 { 48 **p = c; 49 *p += 1; 50 } 51 52 /*VARARGS1*/ 53 void 54 prom_printf(const char *fmt, ...) 55 { 56 va_list adx; 57 58 va_start(adx, fmt); 59 (void) _doprint(fmt, adx, _pput, (char **)0); 60 va_end(adx); 61 } 62 63 void 64 prom_vprintf(const char *fmt, va_list adx) 65 { 66 va_list tadx; 67 68 va_copy(tadx, adx); 69 (void) _doprint(fmt, tadx, _pput, (char **)0); 70 va_end(tadx); 71 } 72 73 /*VARARGS2*/ 74 char * 75 prom_sprintf(char *s, const char *fmt, ...) 76 { 77 char *bp = s; 78 va_list adx; 79 80 va_start(adx, fmt); 81 (void) _doprint(fmt, adx, _sput, &bp); 82 *bp++ = (char)0; 83 va_end(adx); 84 return (s); 85 } 86 87 char * 88 prom_vsprintf(char *s, const char *fmt, va_list adx) 89 { 90 char *bp = s; 91 92 (void) _doprint(fmt, adx, _sput, &bp); 93 *bp++ = (char)0; 94 return (s); 95 } 96 97 static void 98 _doprint(const char *fmt, va_list adx, void (*emit)(char, char **), char **bp) 99 { 100 int b, c, i, pad, width, ells; 101 register char *s; 102 int64_t l; 103 uint64_t ul; 104 105 loop: 106 width = 0; 107 while ((c = *fmt++) != '%') { 108 if (c == '\0') 109 return; 110 if (c == '\n') 111 (*emit)('\r', bp); 112 (*emit)(c, bp); 113 } 114 115 c = *fmt++; 116 117 for (pad = ' '; c == '0'; c = *fmt++) 118 pad = '0'; 119 120 for (width = 0; c >= '0' && c <= '9'; c = *fmt++) 121 width = (width * 10) + (c - '0'); 122 123 for (ells = 0; c == 'l'; c = *fmt++) 124 ells++; 125 126 switch (c) { 127 128 case 'd': 129 case 'D': 130 b = 10; 131 if (ells == 0) 132 l = (int64_t)va_arg(adx, int); 133 else if (ells == 1) 134 l = (int64_t)va_arg(adx, long); 135 else 136 l = (int64_t)va_arg(adx, int64_t); 137 if (l < 0) { 138 (*emit)('-', bp); 139 width--; 140 ul = -l; 141 } else 142 ul = l; 143 goto number; 144 145 case 'p': 146 ells = 1; 147 /* FALLTHROUGH */ 148 case 'x': 149 case 'X': 150 b = 16; 151 goto u_number; 152 153 case 'u': 154 b = 10; 155 goto u_number; 156 157 case 'o': 158 case 'O': 159 b = 8; 160 u_number: 161 if (ells == 0) 162 ul = (uint64_t)va_arg(adx, uint_t); 163 else if (ells == 1) 164 ul = (uint64_t)va_arg(adx, ulong_t); 165 else 166 ul = (uint64_t)va_arg(adx, uint64_t); 167 number: 168 _printn(ul, b, width, pad, emit, bp); 169 break; 170 171 case 'c': 172 b = va_arg(adx, int); 173 for (i = 24; i >= 0; i -= 8) 174 if ((c = ((b >> i) & 0x7f)) != 0) { 175 if (c == '\n') 176 (*emit)('\r', bp); 177 (*emit)(c, bp); 178 } 179 break; 180 case 's': 181 s = va_arg(adx, char *); 182 while ((c = *s++) != 0) { 183 if (c == '\n') 184 (*emit)('\r', bp); 185 (*emit)(c, bp); 186 } 187 break; 188 189 case '%': 190 (*emit)('%', bp); 191 break; 192 } 193 goto loop; 194 } 195 196 /* 197 * Printn prints a number n in base b. 198 * We don't use recursion to avoid deep kernel stacks. 199 */ 200 static void 201 _printn(uint64_t n, int b, int width, int pad, void (*emit)(char, char **), 202 char **bp) 203 { 204 char prbuf[40]; 205 register char *cp; 206 207 cp = prbuf; 208 do { 209 *cp++ = "0123456789abcdef"[n%b]; 210 n /= b; 211 width--; 212 } while (n); 213 while (width-- > 0) 214 *cp++ = (char)pad; 215 do { 216 (*emit)(*--cp, bp); 217 } while (cp > prbuf); 218 } 219