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