Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsa/printf.c

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
98struct snprintf_arg {
99 char *str;
100 size_t remain;
101};
102
103static void
104dummy_putc(int ch, void *arg)
105{
106 void (*real_putc)() = arg;
107
108 if (real_putc) real_putc(ch);
109}
110
111#if 0
112void
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#endif
123#if 1
124#define Ctod(c) ((c) - '0')
125
126#define MAXBUF (sizeof(long long int) * 8)/* enough for binary */
127static char digs[] = "0123456789abcdef";
128static int
129printnum(
130 unsigned long long intu,/* number to print */
131 intbase,
132 void(*putc)(int, void *),
133 void *arg)
134{
135charbuf[MAXBUF];/* build number here */
136char *p = &buf[MAXBUF-1];
137int nprinted = 0;
138
139do {
140 *p-- = digs[u % base];
141 u /= base;
142} while (u != 0);
143
144while (++p != &buf[MAXBUF]) {
145 if (putc) (*putc)(*p, arg);
146 nprinted++;
147}
148
149return nprinted;
150}
151
152bool_doprnt_truncates = false;
153
154int
155__doprnt(
156 const char*fmt,
157 va_listargp,
158 /* character output routine */
159 void(*putc)(int ch, void *arg),
160 void *arg,
161 intradix)/* default radix - for '%r' */
162{
163intlength;
164intprec;
165boolladjust;
166charpadc;
167long longn;
168unsigned long longu;
169intplus_sign;
170intsign_char;
171boolaltfmt, truncate;
172intbase;
173charc;
174intcapitals;
175intlong_long;
176int nprinted = 0;
177
178while ((c = *fmt) != '\0') {
179 if (c != '%') {
180 if (putc) {
181 (*putc)(c, arg);
182 }
183 nprinted++;
184 fmt++;
185 continue;
186 }
187
188 fmt++;
189
190 long_long = 0;
191 length = 0;
192 prec = -1;
193 ladjust = false;
194 padc = ' ';
195 plus_sign = 0;
196 sign_char = 0;
197 altfmt = false;
198
199 while (true) {
200 c = *fmt;
201 if (c == '#') {
202 altfmt = true;
203 }
204 else if (c == '-') {
205 ladjust = true;
206 }
207 else if (c == '+') {
208 plus_sign = '+';
209 }
210 else if (c == ' ') {
211 if (plus_sign == 0)
212 plus_sign = ' ';
213 }
214 else
215 break;
216 fmt++;
217 }
218
219 if (c == '0') {
220 padc = '0';
221 c = *++fmt;
222 }
223
224 if (isdigit(c)) {
225 while(isdigit(c)) {
226 length = 10 * length + Ctod(c);
227 c = *++fmt;
228 }
229 }
230 else if (c == '*') {
231 length = va_arg(argp, int);
232 c = *++fmt;
233 if (length < 0) {
234 ladjust = !ladjust;
235 length = -length;
236 }
237 }
238
239 if (c == '.') {
240 c = *++fmt;
241 if (isdigit(c)) {
242 prec = 0;
243 while(isdigit(c)) {
244 prec = 10 * prec + Ctod(c);
245 c = *++fmt;
246 }
247 }
248 else if (c == '*') {
249 prec = va_arg(argp, int);
250 c = *++fmt;
251 }
252 }
253
254 if (c == 'l') {
255 c = *++fmt;/* need it if sizeof(int) < sizeof(long) */
256 if (sizeof(int)<sizeof(long))
257 long_long = 1;
258 if (c == 'l') {
259 long_long = 1;
260 c = *++fmt;
261 }
262 } else if (c == 'q' || c == 'L') {
263 long_long = 1;
264 c = *++fmt;
265 }
266
267 truncate = false;
268 capitals=0;/* Assume lower case printing */
269
270 switch(c) {
271 case 'b':
272 case 'B':
273 {
274 register char *p;
275 boolean_t any;
276 register int i;
277
278 if (long_long) {
279 u = va_arg(argp, unsigned long long);
280 } else {
281 u = va_arg(argp, unsigned int);
282 }
283 p = va_arg(argp, char *);
284 base = *p++;
285 nprinted += printnum(u, base, putc, arg);
286
287 if (u == 0)
288 break;
289
290 any = false;
291 while ((i = *p++) != '\0') {
292 if (*fmt == 'B')
293 i = 33 - i;
294 if (*p <= 32) {
295 /*
296 * Bit field
297 */
298 register int j;
299 if (any) {
300 if (putc) (*putc)(',', arg);
301 } else {
302 if (putc) (*putc)('<', arg);
303 any = true;
304 }
305 nprinted++;
306 j = *p++;
307 if (*fmt == 'B')
308 j = 32 - j;
309 for (; (c = *p) > 32; p++) {
310 if (putc) (*putc)(c, arg);
311 nprinted++;
312 }
313 nprinted += printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
314 base, putc, arg);
315 }
316 else if (u & (1<<(i-1))) {
317 if (any) {
318 if (putc) (*putc)(',', arg);
319 } else {
320 if (putc) (*putc)('<', arg);
321 any = true;
322 }
323 nprinted++;
324 for (; (c = *p) > 32; p++) {
325 if (putc) (*putc)(c, arg);
326 nprinted++;
327 }
328 }
329 else {
330 for (; *p > 32; p++)
331 continue;
332 }
333 }
334 if (any) {
335 if (putc) (*putc)('>', arg);
336 nprinted++;
337 }
338 break;
339 }
340
341 case 'c':
342 c = va_arg(argp, int);
343 if (putc) (*putc)(c, arg);
344 nprinted++;
345 break;
346
347 case 's':
348 {
349 register const char *p;
350 register const char *p2;
351
352 if (prec == -1)
353 prec = 0x7fffffff;/* MAXINT */
354
355 p = va_arg(argp, char *);
356
357 if (p == NULL)
358 p = "";
359
360 if (length > 0 && !ladjust) {
361 n = 0;
362 p2 = p;
363
364 for (; *p != '\0' && n < prec; p++)
365 n++;
366
367 p = p2;
368
369 while (n < length) {
370 if (putc) (*putc)(' ', arg);
371 n++;
372 nprinted++;
373 }
374 }
375
376 n = 0;
377
378 while ((n < prec) && (!(length > 0 && n >= length))) {
379 if (*p == '\0') {
380 break;
381 }
382 if (putc) (*putc)(*p++, arg);
383 nprinted++;
384 n++;
385 }
386
387 if (n < length && ladjust) {
388 while (n < length) {
389 if (putc) (*putc)(' ', arg);
390 n++;
391 nprinted++;
392 }
393 }
394
395 break;
396 }
397
398 case 'o':
399 truncate = _doprnt_truncates;
400 case 'O':
401 base = 8;
402 goto print_unsigned;
403
404 case 'D': {
405 unsigned char *up;
406 char *q, *p;
407
408 up = (unsigned char *)va_arg(argp, unsigned char *);
409 p = (char *)va_arg(argp, char *);
410 if (length == -1)
411 length = 16;
412 while(length--) {
413 if (putc) (*putc)(digs[(*up >> 4)], arg);
414 if (putc) (*putc)(digs[(*up & 0x0f)], arg);
415 nprinted += 2;
416 up++;
417 if (length) {
418 for (q=p;*q;q++) {
419 if (putc) (*putc)(*q, arg);
420 nprinted++;
421 }
422 }
423 }
424 break;
425 }
426
427 case 'd':
428 truncate = _doprnt_truncates;
429 base = 10;
430 goto print_signed;
431
432 case 'u':
433 truncate = _doprnt_truncates;
434 case 'U':
435 base = 10;
436 goto print_unsigned;
437
438 case 'p':
439 altfmt = true;
440 if (sizeof(int)<sizeof(void *)) {
441 long_long = 1;
442 }
443 case 'x':
444 truncate = _doprnt_truncates;
445 base = 16;
446 goto print_unsigned;
447
448 case 'X':
449 base = 16;
450 capitals=16;/* Print in upper case */
451 goto print_unsigned;
452
453 case 'z':
454 truncate = _doprnt_truncates;
455 base = 16;
456 goto print_signed;
457
458 case 'Z':
459 base = 16;
460 capitals=16;/* Print in upper case */
461 goto print_signed;
462
463 case 'r':
464 truncate = _doprnt_truncates;
465 case 'R':
466 base = radix;
467 goto print_signed;
468
469 case 'n':
470 truncate = _doprnt_truncates;
471 case 'N':
472 base = radix;
473 goto print_unsigned;
474
475 print_signed:
476 if (long_long) {
477 n = va_arg(argp, long long);
478 } else {
479 n = va_arg(argp, int);
480 }
481 if (n >= 0) {
482 u = n;
483 sign_char = plus_sign;
484 }
485 else {
486 u = -n;
487 sign_char = '-';
488 }
489 goto print_num;
490
491 print_unsigned:
492 if (long_long) {
493 u = va_arg(argp, unsigned long long);
494 } else {
495 u = va_arg(argp, unsigned int);
496 }
497 goto print_num;
498
499 print_num:
500 {
501 charbuf[MAXBUF];/* build number here */
502 register char *p = &buf[MAXBUF-1];
503 static char digits[] = "0123456789abcdef0123456789ABCDEF";
504 const char *prefix = NULL;
505
506 if (truncate) u = (long long)((int)(u));
507
508 if (u != 0 && altfmt) {
509 if (base == 8)
510 prefix = "0";
511 else if (base == 16)
512 prefix = "0x";
513 }
514
515 do {
516 /* Print in the correct case */
517 *p-- = digits[(u % base)+capitals];
518 u /= base;
519 } while (u != 0);
520
521 length -= (int)(&buf[MAXBUF-1] - p);
522 if (sign_char)
523 length--;
524 if (prefix)
525 length -= (int)strlen(prefix);
526
527 if (padc == ' ' && !ladjust) {
528 /* blank padding goes before prefix */
529 while (--length >= 0) {
530 if (putc) (*putc)(' ', arg);
531 nprinted++;
532 }
533 }
534 if (sign_char) {
535 if (putc) (*putc)(sign_char, arg);
536 nprinted++;
537 }
538 if (prefix) {
539 while (*prefix) {
540 if (putc) (*putc)(*prefix++, arg);
541 nprinted++;
542 }
543 }
544 if (padc == '0') {
545 /* zero padding goes after sign and prefix */
546 while (--length >= 0) {
547 if (putc) (*putc)('0', arg);
548 nprinted++;
549 }
550 }
551 while (++p != &buf[MAXBUF]) {
552 if (putc) (*putc)(*p, arg);
553 nprinted++;
554 }
555
556 if (ladjust) {
557 while (--length >= 0) {
558 if (putc) (*putc)(' ', arg);
559 nprinted++;
560 }
561 }
562 break;
563 }
564
565 case '\0':
566 fmt--;
567 break;
568
569 default:
570 if (putc) (*putc)(c, arg);
571 nprinted++;
572 }
573 fmt++;
574}
575
576return nprinted;
577}
578#endif
579
580int
581prf(
582 const char*fmt,
583 va_listap,
584 /* character output routine */
585 void(*putc)(char))
586{
587 return __doprnt(fmt, ap, dummy_putc, putc, 10);
588}
589
590
591static char *copybyte_str;
592
593static void
594copybyte(
595 char byte)
596{
597 *copybyte_str++ = byte;
598 *copybyte_str = '\0';
599}
600
601int
602sprintf(char *buf, const char *fmt, ...)
603{
604 va_list listp;
605
606 va_start(listp, fmt);
607 copybyte_str = buf;
608 prf(fmt, listp, copybyte);
609 va_end(listp);
610 return strlen(buf);
611}
612
613static void
614snprintf_func(int ch, void *arg)
615{
616 struct snprintf_arg *const info = arg;
617
618 if (info->remain >= 2) {
619 *info->str++ = ch;
620 info->remain--;
621 }
622}
623
624/*
625 * Scaled down version of vsnprintf(3).
626 */
627int
628vsnprintf(char *str, size_t size, const char *format, va_list ap)
629{
630 struct snprintf_arg info;
631 int retval;
632
633 info.str = str;
634 info.remain = size;
635 retval = __doprnt(format, ap, snprintf_func, &info, 10);
636 if (info.remain >= 1)
637 *info.str++ = '\0';
638 return retval;
639}
640
641/*
642 * Scaled down version of snprintf(3).
643 */
644int
645snprintf(char *str, size_t size, const char *format, ...)
646{
647 int retval;
648 va_list ap;
649
650 va_start(ap, format);
651 retval = vsnprintf(str, size, format, ap);
652 va_end(ap);
653 return(retval);
654}

Archive Download this file

Revision: 2115