1 | /*␊ |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.␊ |
7 | * ␊ |
8 | * This file contains Original Code and/or Modifications of Original Code␊ |
9 | * as defined in and that are subject to the Apple Public Source License␊ |
10 | * Version 2.0 (the 'License'). You may not use this file except in␊ |
11 | * compliance with the License. Please obtain a copy of the License at␊ |
12 | * http://www.opensource.apple.com/apsl/ and read it before using this␊ |
13 | * file.␊ |
14 | * ␊ |
15 | * The Original Code and all software distributed under the License are␊ |
16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
19 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.␊ |
20 | * Please see the License for the specific language governing rights and␊ |
21 | * limitations under the License.␊ |
22 | * ␊ |
23 | * @APPLE_LICENSE_HEADER_END@␊ |
24 | */␊ |
25 | /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */␊ |
26 | /*-␊ |
27 | * Copyright (c) 1986, 1988, 1991, 1993␊ |
28 | * The Regents of the University of California. All rights reserved.␊ |
29 | * (c) UNIX System Laboratories, Inc.␊ |
30 | * All or some portions of this file are derived from material licensed␊ |
31 | * to the University of California by American Telephone and Telegraph␊ |
32 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with␊ |
33 | * the permission of UNIX System Laboratories, Inc.␊ |
34 | *␊ |
35 | * Redistribution and use in source and binary forms, with or without␊ |
36 | * modification, are permitted provided that the following conditions␊ |
37 | * are met:␊ |
38 | * 1. Redistributions of source code must retain the above copyright␊ |
39 | * notice, this list of conditions and the following disclaimer.␊ |
40 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
41 | * notice, this list of conditions and the following disclaimer in the␊ |
42 | * documentation and/or other materials provided with the distribution.␊ |
43 | * 3. All advertising materials mentioning features or use of this software␊ |
44 | * must display the following acknowledgement:␊ |
45 | * This product includes software developed by the University of␊ |
46 | * California, Berkeley and its contributors.␊ |
47 | * 4. Neither the name of the University nor the names of its contributors␊ |
48 | * may be used to endorse or promote products derived from this software␊ |
49 | * without specific prior written permission.␊ |
50 | *␊ |
51 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND␊ |
52 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE␊ |
53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE␊ |
54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE␊ |
55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL␊ |
56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS␊ |
57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)␊ |
58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT␊ |
59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY␊ |
60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF␊ |
61 | * SUCH DAMAGE.␊ |
62 | *␊ |
63 | * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95␊ |
64 | */␊ |
65 | /*␊ |
66 | * @OSF_COPYRIGHT@␊ |
67 | */␊ |
68 | ␊ |
69 | /* ␊ |
70 | * Mach Operating System␊ |
71 | * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University␊ |
72 | * All Rights Reserved.␊ |
73 | * ␊ |
74 | * Permission to use, copy, modify and distribute this software and its␊ |
75 | * documentation is hereby granted, provided that both the copyright␊ |
76 | * notice and this permission notice appear in all copies of the␊ |
77 | * software, derivative works or modified versions, and any portions␊ |
78 | * thereof, and that both notices appear in supporting documentation.␊ |
79 | * ␊ |
80 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"␊ |
81 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR␊ |
82 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.␊ |
83 | * ␊ |
84 | * Carnegie Mellon requests users of this software to return to␊ |
85 | * ␊ |
86 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU␊ |
87 | * School of Computer Science␊ |
88 | * Carnegie Mellon University␊ |
89 | * Pittsburgh PA 15213-3890␊ |
90 | * ␊ |
91 | * any improvements or extensions that they make and grant Carnegie Mellon␊ |
92 | * the rights to redistribute these changes.␊ |
93 | */␊ |
94 | ␊ |
95 | ␊ |
96 | #include "libsa.h"␊ |
97 | ␊ |
98 | struct snprintf_arg {␊ |
99 | char *str;␊ |
100 | size_t remain;␊ |
101 | };␊ |
102 | ␊ |
103 | static void␊ |
104 | dummy_putc(int ch, void *arg)␊ |
105 | {␊ |
106 | void (*real_putc)() = arg;␊ |
107 | ␊ |
108 | if (real_putc) real_putc(ch);␊ |
109 | }␊ |
110 | ␊ |
111 | #if 0␊ |
112 | void ␊ |
113 | _doprnt(␊ |
114 | register const char *fmt,␊ |
115 | va_list argp,␊ |
116 | /* character output routine */␊ |
117 | void (*putc)(),␊ |
118 | int radix) /* default radix - for '%r' */␊ |
119 | {␊ |
120 | __doprnt(fmt, argp, dummy_putc, putc, radix);␊ |
121 | }␊ |
122 | #define Ctod(c) ((c) - '0')␊ |
123 | ␊ |
124 | #define MAXBUF (sizeof(long long int) * 8)␉/* enough for binary */␊ |
125 | static char digs[] = "0123456789abcdef";␊ |
126 | static int␊ |
127 | printnum(␊ |
128 | unsigned long long int␉u,␉/* number to print */␊ |
129 | int␉␉base,␊ |
130 | void␉␉␉(*putc)(int, void *),␊ |
131 | void *arg)␊ |
132 | {␊ |
133 | ␉char␉buf[MAXBUF];␉/* build number here */␊ |
134 | ␉char *␉p = &buf[MAXBUF-1];␊ |
135 | ␉int nprinted = 0;␊ |
136 | ␊ |
137 | ␉do {␊ |
138 | ␉ *p-- = digs[u % base];␊ |
139 | ␉ u /= base;␊ |
140 | ␉} while (u != 0);␊ |
141 | ␊ |
142 | ␉while (++p != &buf[MAXBUF]) {␊ |
143 | ␉ if (putc) (*putc)(*p, arg);␊ |
144 | ␉ nprinted++;␊ |
145 | ␉}␊ |
146 | ␊ |
147 | ␉return nprinted;␊ |
148 | }␊ |
149 | ␊ |
150 | bool␉_doprnt_truncates = false;␊ |
151 | ␊ |
152 | int␊ |
153 | __doprnt(␊ |
154 | const char␉*fmt,␊ |
155 | va_list␉␉␉argp,␊ |
156 | /* character output routine */␊ |
157 | void␉␉␉(*putc)(int ch, void *arg),␊ |
158 | void *arg,␊ |
159 | int␉␉␉radix)␉␉/* default radix - for '%r' */␊ |
160 | {␊ |
161 | ␉int␉␉length;␊ |
162 | ␉int␉␉prec;␊ |
163 | ␉bool␉ladjust;␊ |
164 | ␉char␉␉padc;␊ |
165 | ␉long long␉␉n;␊ |
166 | ␉unsigned long long␉u;␊ |
167 | ␉int␉␉plus_sign;␊ |
168 | ␉int␉␉sign_char;␊ |
169 | ␉bool␉altfmt, truncate;␊ |
170 | ␉int␉␉base;␊ |
171 | ␉char␉c;␊ |
172 | ␉int␉␉capitals;␊ |
173 | ␉int␉␉long_long;␊ |
174 | ␉int nprinted = 0;␊ |
175 | ␊ |
176 | ␉while ((c = *fmt) != '\0') {␊ |
177 | ␉ if (c != '%') {␊ |
178 | if (putc) {␊ |
179 | (*putc)(c, arg);␊ |
180 | }␊ |
181 | nprinted++;␊ |
182 | fmt++;␊ |
183 | continue;␊ |
184 | ␉ }␊ |
185 | ␊ |
186 | ␉ fmt++;␊ |
187 | ␊ |
188 | ␉ long_long = 0;␊ |
189 | ␉ length = 0;␊ |
190 | ␉ prec = -1;␊ |
191 | ␉ ladjust = false;␊ |
192 | ␉ padc = ' ';␊ |
193 | ␉ plus_sign = 0;␊ |
194 | ␉ sign_char = 0;␊ |
195 | ␉ altfmt = false;␊ |
196 | ␊ |
197 | ␉ while (true) {␊ |
198 | c = *fmt;␊ |
199 | if (c == '#') {␊ |
200 | altfmt = true;␊ |
201 | }␊ |
202 | else if (c == '-') {␊ |
203 | ladjust = true;␊ |
204 | }␊ |
205 | else if (c == '+') {␊ |
206 | plus_sign = '+';␊ |
207 | }␊ |
208 | else if (c == ' ') {␊ |
209 | if (plus_sign == 0)␊ |
210 | plus_sign = ' ';␊ |
211 | }␊ |
212 | else␊ |
213 | break;␊ |
214 | fmt++;␊ |
215 | ␉ }␊ |
216 | ␊ |
217 | ␉ if (c == '0') {␊ |
218 | padc = '0';␊ |
219 | c = *++fmt;␊ |
220 | ␉ }␊ |
221 | ␊ |
222 | ␉ if (isdigit(c)) {␊ |
223 | while(isdigit(c)) {␊ |
224 | length = 10 * length + Ctod(c);␊ |
225 | c = *++fmt;␊ |
226 | }␊ |
227 | ␉ }␊ |
228 | ␉ else if (c == '*') {␊ |
229 | length = va_arg(argp, int);␊ |
230 | c = *++fmt;␊ |
231 | if (length < 0) {␊ |
232 | ladjust = !ladjust;␊ |
233 | length = -length;␊ |
234 | }␊ |
235 | ␉ }␊ |
236 | ␊ |
237 | ␉ if (c == '.') {␊ |
238 | c = *++fmt;␊ |
239 | if (isdigit(c)) {␊ |
240 | prec = 0;␊ |
241 | while(isdigit(c)) {␊ |
242 | prec = 10 * prec + Ctod(c);␊ |
243 | c = *++fmt;␊ |
244 | }␊ |
245 | }␊ |
246 | else if (c == '*') {␊ |
247 | prec = va_arg(argp, int);␊ |
248 | c = *++fmt;␊ |
249 | }␊ |
250 | ␉ }␊ |
251 | ␊ |
252 | ␉ if (c == 'l') {␊ |
253 | c = *++fmt;␉/* need it if sizeof(int) < sizeof(long) */␊ |
254 | if (sizeof(int)<sizeof(long))␊ |
255 | long_long = 1;␊ |
256 | if (c == 'l') {␊ |
257 | long_long = 1;␊ |
258 | c = *++fmt;␊ |
259 | }␉␊ |
260 | ␉ } else if (c == 'q' || c == 'L') {␊ |
261 | ␉ ␉long_long = 1;␊ |
262 | c = *++fmt;␊ |
263 | ␉ } ␊ |
264 | ␊ |
265 | ␉ truncate = false;␊ |
266 | ␉ capitals=0;␉␉/* Assume lower case printing */␊ |
267 | ␊ |
268 | ␉ switch(c) {␊ |
269 | case 'b':␊ |
270 | case 'B':␊ |
271 | {␊ |
272 | register char *p;␊ |
273 | boolean_t␉ any;␊ |
274 | register int i;␊ |
275 | ␊ |
276 | if (long_long) {␊ |
277 | u = va_arg(argp, unsigned long long);␊ |
278 | } else {␊ |
279 | u = va_arg(argp, unsigned int);␊ |
280 | }␊ |
281 | p = va_arg(argp, char *);␊ |
282 | base = *p++;␊ |
283 | nprinted += printnum(u, base, putc, arg);␊ |
284 | ␊ |
285 | if (u == 0)␊ |
286 | break;␊ |
287 | ␊ |
288 | any = false;␊ |
289 | while ((i = *p++) != '\0') {␊ |
290 | if (*fmt == 'B')␊ |
291 | i = 33 - i;␊ |
292 | if (*p <= 32) {␊ |
293 | /*␊ |
294 | * Bit field␊ |
295 | */␊ |
296 | register int j;␊ |
297 | if (any)␊ |
298 | if (putc) (*putc)(',', arg);␊ |
299 | else {␊ |
300 | if (putc) (*putc)('<', arg);␊ |
301 | any = true;␊ |
302 | }␊ |
303 | nprinted++;␊ |
304 | j = *p++;␊ |
305 | if (*fmt == 'B')␊ |
306 | j = 32 - j;␊ |
307 | for (; (c = *p) > 32; p++) {␊ |
308 | if (putc) (*putc)(c, arg);␊ |
309 | nprinted++;␊ |
310 | }␊ |
311 | nprinted += printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),␊ |
312 | base, putc, arg);␊ |
313 | }␊ |
314 | else if (u & (1<<(i-1))) {␊ |
315 | if (any)␊ |
316 | if (putc) (*putc)(',', arg);␊ |
317 | else {␊ |
318 | if (putc) (*putc)('<', arg);␊ |
319 | any = true;␊ |
320 | }␊ |
321 | nprinted++;␊ |
322 | for (; (c = *p) > 32; p++) {␊ |
323 | if (putc) (*putc)(c, arg);␊ |
324 | nprinted++;␊ |
325 | }␊ |
326 | }␊ |
327 | else {␊ |
328 | for (; *p > 32; p++)␊ |
329 | continue;␊ |
330 | }␊ |
331 | }␊ |
332 | if (any) {␊ |
333 | if (putc) (*putc)('>', arg);␊ |
334 | nprinted++;␊ |
335 | }␊ |
336 | break;␊ |
337 | }␊ |
338 | ␊ |
339 | case 'c':␊ |
340 | c = va_arg(argp, int);␊ |
341 | if (putc) (*putc)(c, arg);␊ |
342 | nprinted++;␊ |
343 | break;␊ |
344 | ␊ |
345 | case 's':␊ |
346 | {␊ |
347 | register const char *p;␊ |
348 | register const char *p2;␊ |
349 | ␊ |
350 | if (prec == -1)␊ |
351 | prec = 0x7fffffff;␉/* MAXINT */␊ |
352 | ␊ |
353 | p = va_arg(argp, char *);␊ |
354 | ␊ |
355 | if (p == NULL)␊ |
356 | p = "";␊ |
357 | ␊ |
358 | if (length > 0 && !ladjust) {␊ |
359 | n = 0;␊ |
360 | p2 = p;␊ |
361 | ␊ |
362 | for (; *p != '\0' && n < prec; p++)␊ |
363 | n++;␊ |
364 | ␊ |
365 | p = p2;␊ |
366 | ␊ |
367 | while (n < length) {␊ |
368 | if (putc) (*putc)(' ', arg);␊ |
369 | n++;␊ |
370 | nprinted++;␊ |
371 | }␊ |
372 | }␊ |
373 | ␊ |
374 | n = 0;␊ |
375 | ␊ |
376 | while ((n < prec) && (!(length > 0 && n >= length))) {␊ |
377 | if (*p == '\0') {␊ |
378 | break;␊ |
379 | }␊ |
380 | if (putc) (*putc)(*p++, arg);␊ |
381 | nprinted++;␊ |
382 | n++;␊ |
383 | }␊ |
384 | ␊ |
385 | if (n < length && ladjust) {␊ |
386 | while (n < length) {␊ |
387 | if (putc) (*putc)(' ', arg);␊ |
388 | n++;␊ |
389 | nprinted++;␊ |
390 | }␊ |
391 | }␊ |
392 | ␊ |
393 | break;␊ |
394 | }␊ |
395 | ␊ |
396 | case 'o':␊ |
397 | truncate = _doprnt_truncates;␊ |
398 | case 'O':␊ |
399 | base = 8;␊ |
400 | goto print_unsigned;␊ |
401 | ␊ |
402 | case 'D': {␊ |
403 | unsigned char *up;␊ |
404 | char *q, *p;␊ |
405 | ␊ |
406 | up = (unsigned char *)va_arg(argp, unsigned char *);␊ |
407 | p = (char *)va_arg(argp, char *);␊ |
408 | if (length == -1)␊ |
409 | length = 16;␊ |
410 | while(length--) {␊ |
411 | if (putc) (*putc)(digs[(*up >> 4)], arg);␊ |
412 | if (putc) (*putc)(digs[(*up & 0x0f)], arg);␊ |
413 | nprinted += 2;␊ |
414 | up++;␊ |
415 | if (length) {␊ |
416 | for (q=p;*q;q++) {␊ |
417 | if (putc) (*putc)(*q, arg);␊ |
418 | nprinted++;␊ |
419 | }␊ |
420 | }␊ |
421 | }␊ |
422 | break;␊ |
423 | }␊ |
424 | ␊ |
425 | case 'd':␊ |
426 | truncate = _doprnt_truncates;␊ |
427 | base = 10;␊ |
428 | goto print_signed;␊ |
429 | ␊ |
430 | case 'u':␊ |
431 | truncate = _doprnt_truncates;␊ |
432 | case 'U':␊ |
433 | base = 10;␊ |
434 | goto print_unsigned;␊ |
435 | ␊ |
436 | case 'p':␊ |
437 | altfmt = true;␊ |
438 | if (sizeof(int)<sizeof(void *)) {␊ |
439 | long_long = 1;␊ |
440 | }␊ |
441 | case 'x':␊ |
442 | truncate = _doprnt_truncates;␊ |
443 | base = 16;␊ |
444 | goto print_unsigned;␊ |
445 | ␊ |
446 | case 'X':␊ |
447 | base = 16;␊ |
448 | capitals=16;␉/* Print in upper case */␊ |
449 | goto print_unsigned;␊ |
450 | ␊ |
451 | case 'z':␊ |
452 | truncate = _doprnt_truncates;␊ |
453 | base = 16;␊ |
454 | goto print_signed;␊ |
455 | ␊ |
456 | case 'Z':␊ |
457 | base = 16;␊ |
458 | capitals=16;␉/* Print in upper case */␊ |
459 | goto print_signed;␊ |
460 | ␊ |
461 | case 'r':␊ |
462 | truncate = _doprnt_truncates;␊ |
463 | case 'R':␊ |
464 | base = radix;␊ |
465 | goto print_signed;␊ |
466 | ␊ |
467 | case 'n':␊ |
468 | truncate = _doprnt_truncates;␊ |
469 | case 'N':␊ |
470 | base = radix;␊ |
471 | goto print_unsigned;␊ |
472 | ␊ |
473 | print_signed:␊ |
474 | if (long_long) {␊ |
475 | n = va_arg(argp, long long);␊ |
476 | } else {␊ |
477 | n = va_arg(argp, int);␊ |
478 | }␊ |
479 | if (n >= 0) {␊ |
480 | u = n;␊ |
481 | sign_char = plus_sign;␊ |
482 | }␊ |
483 | else {␊ |
484 | u = -n;␊ |
485 | sign_char = '-';␊ |
486 | }␊ |
487 | goto print_num;␊ |
488 | ␊ |
489 | print_unsigned:␊ |
490 | if (long_long) {␊ |
491 | u = va_arg(argp, unsigned long long);␊ |
492 | } else { ␊ |
493 | u = va_arg(argp, unsigned int);␊ |
494 | }␊ |
495 | goto print_num;␊ |
496 | ␊ |
497 | print_num:␊ |
498 | {␊ |
499 | char␉buf[MAXBUF];␉/* build number here */␊ |
500 | register char *␉p = &buf[MAXBUF-1];␊ |
501 | static char digits[] = "0123456789abcdef0123456789ABCDEF";␊ |
502 | const char *prefix = NULL;␊ |
503 | ␊ |
504 | if (truncate) u = (long long)((int)(u));␊ |
505 | ␊ |
506 | if (u != 0 && altfmt) {␊ |
507 | if (base == 8)␊ |
508 | prefix = "0";␊ |
509 | else if (base == 16)␊ |
510 | prefix = "0x";␊ |
511 | }␊ |
512 | ␊ |
513 | do {␊ |
514 | /* Print in the correct case */␊ |
515 | *p-- = digits[(u % base)+capitals];␊ |
516 | u /= base;␊ |
517 | } while (u != 0);␊ |
518 | ␊ |
519 | length -= (int)(&buf[MAXBUF-1] - p);␊ |
520 | if (sign_char)␊ |
521 | length--;␊ |
522 | if (prefix)␊ |
523 | length -= (int)strlen(prefix);␊ |
524 | ␊ |
525 | if (padc == ' ' && !ladjust) {␊ |
526 | /* blank padding goes before prefix */␊ |
527 | while (--length >= 0) {␊ |
528 | if (putc) (*putc)(' ', arg);␊ |
529 | nprinted++;␊ |
530 | }␉␉␉ ␊ |
531 | }␊ |
532 | if (sign_char) {␊ |
533 | if (putc) (*putc)(sign_char, arg);␊ |
534 | nprinted++;␊ |
535 | }␊ |
536 | if (prefix) {␊ |
537 | while (*prefix) {␊ |
538 | if (putc) (*putc)(*prefix++, arg);␊ |
539 | nprinted++;␊ |
540 | }␊ |
541 | }␊ |
542 | if (padc == '0') {␊ |
543 | /* zero padding goes after sign and prefix */␊ |
544 | while (--length >= 0) {␊ |
545 | if (putc) (*putc)('0', arg);␊ |
546 | nprinted++;␊ |
547 | }␉␉␉ ␊ |
548 | }␊ |
549 | while (++p != &buf[MAXBUF]) {␊ |
550 | (*putc)(*p, arg);␊ |
551 | nprinted++;␊ |
552 | }␊ |
553 | ␊ |
554 | if (ladjust) {␊ |
555 | while (--length >= 0) {␊ |
556 | if (putc) (*putc)(' ', arg);␊ |
557 | nprinted++;␊ |
558 | }␊ |
559 | }␊ |
560 | break;␊ |
561 | }␊ |
562 | ␊ |
563 | case '\0':␊ |
564 | fmt--;␊ |
565 | break;␊ |
566 | ␊ |
567 | default:␊ |
568 | if (putc) (*putc)(c, arg);␊ |
569 | nprinted++;␊ |
570 | ␉ }␊ |
571 | fmt++;␊ |
572 | ␉}␊ |
573 | ␊ |
574 | ␉return nprinted;␊ |
575 | }␊ |
576 | #endif␊ |
577 | ␊ |
578 | int␊ |
579 | prf(␊ |
580 | const char␉*fmt,␊ |
581 | va_list␉␉␉ap,␊ |
582 | /* character output routine */␊ |
583 | void␉␉␉(*putc)(char))␉␉␊ |
584 | {␊ |
585 | return __doprnt(fmt, ap, dummy_putc, putc, 10); ␊ |
586 | }␊ |
587 | ␊ |
588 | ␊ |
589 | static char *copybyte_str;␊ |
590 | ␊ |
591 | static void␊ |
592 | copybyte(␊ |
593 | char byte)␊ |
594 | {␊ |
595 | *copybyte_str++ = byte;␊ |
596 | *copybyte_str = '\0';␊ |
597 | }␊ |
598 | ␊ |
599 | int␊ |
600 | sprintf(char *buf, const char *fmt, ...)␊ |
601 | {␊ |
602 | va_list listp;␊ |
603 | ␊ |
604 | va_start(listp, fmt);␊ |
605 | copybyte_str = buf;␊ |
606 | prf(fmt, listp, copybyte);␊ |
607 | va_end(listp);␊ |
608 | return strlen(buf);␊ |
609 | }␊ |
610 | ␊ |
611 | static void␊ |
612 | snprintf_func(int ch, void *arg)␊ |
613 | {␊ |
614 | struct snprintf_arg *const info = arg;␊ |
615 | ␊ |
616 | if (info->remain >= 2) {␊ |
617 | *info->str++ = ch;␊ |
618 | info->remain--;␊ |
619 | }␊ |
620 | }␊ |
621 | ␊ |
622 | /*␊ |
623 | * Scaled down version of vsnprintf(3).␊ |
624 | */␊ |
625 | int␊ |
626 | vsnprintf(char *str, size_t size, const char *format, va_list ap)␊ |
627 | {␊ |
628 | struct snprintf_arg info;␊ |
629 | int retval;␊ |
630 | ␊ |
631 | info.str = str;␊ |
632 | info.remain = size;␊ |
633 | retval = __doprnt(format, ap, snprintf_func, &info, 10);␊ |
634 | if (info.remain >= 1)␊ |
635 | *info.str++ = '\0';␊ |
636 | return retval;␊ |
637 | }␊ |
638 | ␊ |
639 | /*␊ |
640 | * Scaled down version of snprintf(3).␊ |
641 | */␊ |
642 | int␊ |
643 | snprintf(char *str, size_t size, const char *format, ...)␊ |
644 | {␊ |
645 | int retval;␊ |
646 | va_list ap;␊ |
647 | ␊ |
648 | va_start(ap, format);␊ |
649 | retval = vsnprintf(str, size, format, ap);␊ |
650 | va_end(ap);␊ |
651 | return(retval);␊ |
652 | }␊ |
653 | ␊ |
654 | #if 1␊ |
655 | /*␊ |
656 | * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.␊ |
657 | *␊ |
658 | * @APPLE_LICENSE_HEADER_START@␊ |
659 | * ␊ |
660 | * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights␊ |
661 | * Reserved. This file contains Original Code and/or Modifications of␊ |
662 | * Original Code as defined in and that are subject to the Apple Public␊ |
663 | * Source License Version 2.0 (the "License"). You may not use this file␊ |
664 | * except in compliance with the License. Please obtain a copy of the␊ |
665 | * License at http://www.apple.com/publicsource and read it before using␊ |
666 | * this file.␊ |
667 | * ␊ |
668 | * The Original Code and all software distributed under the License are␊ |
669 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
670 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
671 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
672 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the␊ |
673 | * License for the specific language governing rights and limitations␊ |
674 | * under the License.␊ |
675 | * ␊ |
676 | * @APPLE_LICENSE_HEADER_END@␊ |
677 | */␊ |
678 | /* ␊ |
679 | * Mach Operating System␊ |
680 | * Copyright (c) 1990 Carnegie-Mellon University␊ |
681 | * Copyright (c) 1989 Carnegie-Mellon University␊ |
682 | * Copyright (c) 1988 Carnegie-Mellon University␊ |
683 | * Copyright (c) 1987 Carnegie-Mellon University␊ |
684 | * All rights reserved. The CMU software License Agreement specifies␊ |
685 | * the terms and conditions for use and redistribution.␊ |
686 | */␊ |
687 | /*␊ |
688 | * Copyright (c) 1982, 1986 Regents of the University of California.␊ |
689 | * All rights reserved. The Berkeley software License Agreement␊ |
690 | * specifies the terms and conditions for redistribution.␊ |
691 | *␊ |
692 | *␉@(#)prf.c␉7.1 (Berkeley) 6/5/86␊ |
693 | */␊ |
694 | #include <sys/param.h>␊ |
695 | ␊ |
696 | #define SPACE␉1␊ |
697 | #define ZERO␉2␊ |
698 | #define UCASE 16␊ |
699 | ␊ |
700 | /*␊ |
701 | * Scaled down version of C Library printf.␊ |
702 | * Used to print diagnostic information directly on console tty.␊ |
703 | * Since it is not interrupt driven, all system activities are␊ |
704 | * suspended.␊ |
705 | *␊ |
706 | */␊ |
707 | ␊ |
708 | /*␊ |
709 | * Printn prints a number n in base b.␊ |
710 | * We don't use recursion to avoid deep kernel stacks.␊ |
711 | */␊ |
712 | static int␊ |
713 | printn(u_long n, int b, int flag, int minwidth, void (*putfn_p)(int ch, void *arg), void *putfn_arg)␊ |
714 | {␊ |
715 | ␉char prbuf[11];␊ |
716 | ␉register char *cp;␊ |
717 | ␉int width = 0, neg = 0, len = 0;␊ |
718 | ␉␊ |
719 | ␉if (b == 10 && (int)n < 0) {␊ |
720 | ␉␉neg = 1;␊ |
721 | ␉␉n = (unsigned)(-(int)n);␊ |
722 | ␉}␊ |
723 | ␉cp = prbuf;␊ |
724 | ␉do {␊ |
725 | ␉␉*cp++ = "0123456789abcdef0123456789ABCDEF"[(flag & UCASE) + n%b];␊ |
726 | ␉␉n /= b;␊ |
727 | ␉␉width++;␊ |
728 | ␉} while (n);␊ |
729 | ␉␊ |
730 | ␉if (neg) {␊ |
731 | ␉␉(*putfn_p)('-', putfn_arg);␊ |
732 | ␉␉width++;␊ |
733 | len++;␊ |
734 | ␉}␊ |
735 | ␉while (width++ < minwidth)␊ |
736 | {␊ |
737 | ␉␉(*putfn_p)( (flag & ZERO) ? '0' : ' ', putfn_arg);␊ |
738 | len++;␊ |
739 | }␊ |
740 | ␉␊ |
741 | ␉do␊ |
742 | {␊ |
743 | ␉␉(*putfn_p)(*--cp, putfn_arg);␊ |
744 | len++;␊ |
745 | ␊ |
746 | } while (cp > prbuf);␊ |
747 | ␊ |
748 | return len;␊ |
749 | }␊ |
750 | ␊ |
751 | int __doprnt(␊ |
752 | const char *fmt,␊ |
753 | va_list argp,␊ |
754 | void (*putfn_p)(int ch, void *arg),␊ |
755 | void *putfn_arg,␊ |
756 | int radix␊ |
757 | )␊ |
758 | {␊ |
759 | ␉int b, c, len =0;␊ |
760 | ␉char *s;␊ |
761 | ␉int flag = 0, width = 0;␊ |
762 | ␉int minwidth;␊ |
763 | unsigned int *adx = (unsigned int*)argp;␊ |
764 | loop:␊ |
765 | ␉while ((c = *fmt++) != '%') {␊ |
766 | ␉␉if(c == '\0')␊ |
767 | ␉␉␉return len;␊ |
768 | ␉␉if (putfn_p) {␊ |
769 | ␉␉␉(*putfn_p)(c, putfn_arg);␊ |
770 | ␉␉}␊ |
771 | ␉␉len++;␊ |
772 | ␉}␊ |
773 | ␉minwidth = 0;␊ |
774 | again:␊ |
775 | ␉c = *fmt++;␊ |
776 | ␉switch (c) {␊ |
777 | ␉␉case 'l':␊ |
778 | ␉␉␉goto again;␊ |
779 | ␉␉case ' ':␊ |
780 | ␉␉␉flag |= SPACE;␊ |
781 | ␉␉␉goto again;␊ |
782 | ␉␉case '0':␊ |
783 | ␉␉␉if (minwidth == 0) {␊ |
784 | ␉␉␉␉/* this is a flag */␊ |
785 | ␉␉␉␉flag |= ZERO;␊ |
786 | ␉␉␉␉goto again;␊ |
787 | ␉␉␉} /* fall through */␊ |
788 | ␉␉case '1':␊ |
789 | ␉␉case '2':␊ |
790 | ␉␉case '3':␊ |
791 | ␉␉case '4':␊ |
792 | ␉␉case '5':␊ |
793 | ␉␉case '6':␊ |
794 | ␉␉case '7':␊ |
795 | ␉␉case '8':␊ |
796 | ␉␉case '9':␊ |
797 | ␉␉␉minwidth *= 10;␊ |
798 | ␉␉␉minwidth += c - '0';␊ |
799 | ␉␉␉goto again;␊ |
800 | case 'X':␊ |
801 | ␉␉␉flag |= UCASE;␊ |
802 | ␉␉␉/* fall through */␊ |
803 | ␉␉case 'x':␊ |
804 | ␉␉␉b = 16;␊ |
805 | ␉␉␉goto number;␊ |
806 | ␉␉case 'd':␊ |
807 | ␉␉␉b = 10;␊ |
808 | ␉␉␉goto number;␊ |
809 | ␉␉case 'o': case 'O':␊ |
810 | ␉␉␉b = 8;␊ |
811 | ␉␉number:␊ |
812 | ␉␉␉len += printn((u_long)*adx, b, flag, minwidth, putfn_p, putfn_arg);␉␉␉␊ |
813 | ␉␉␉break;␊ |
814 | ␉␉case 's':␊ |
815 | ␉␉␉s = (char *)*adx;␊ |
816 | ␉␉␉while ((c = *s++)) {␊ |
817 | ␉␉␉␉if (putfn_p) {␊ |
818 | ␉␉␉␉␉(*putfn_p)(c, putfn_arg);␊ |
819 | ␉␉␉␉}␊ |
820 | ␉␉␉␉len++;␊ |
821 | ␉␉␉␉width++;␊ |
822 | ␉␉␉}␊ |
823 | ␉␉␉while (width++ < minwidth) {␊ |
824 | ␉␉␉␉if (putfn_p) {␊ |
825 | ␉␉␉␉␉(*putfn_p)(' ', putfn_arg);␊ |
826 | ␉␉␉␉}␊ |
827 | ␉␉␉␉len++;␊ |
828 | ␉␉␉}␊ |
829 | ␉␉␉break;␊ |
830 | ␉␉case 'c':␊ |
831 | ␉␉␉if (putfn_p) {␊ |
832 | ␉␉␉␉(*putfn_p)((char)*adx, putfn_arg);␊ |
833 | ␉␉␉}␊ |
834 | ␉␉␉len++;␊ |
835 | ␉␉␉break;␊ |
836 | ␉␉default:␊ |
837 | ␉␉␉break;␊ |
838 | ␉}␊ |
839 | ␉adx++;␊ |
840 | ␉goto loop;␊ |
841 | }␊ |
842 | #endif |