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#define Ctod(c) ((c) - '0')
123
124#define MAXBUF (sizeof(long long int) * 8)/* enough for binary */
125static char digs[] = "0123456789abcdef";
126static int
127printnum(
128 unsigned long long intu,/* number to print */
129 intbase,
130 void(*putc)(int, void *),
131 void *arg)
132{
133charbuf[MAXBUF];/* build number here */
134char *p = &buf[MAXBUF-1];
135int nprinted = 0;
136
137do {
138 *p-- = digs[u % base];
139 u /= base;
140} while (u != 0);
141
142while (++p != &buf[MAXBUF]) {
143 if (putc) (*putc)(*p, arg);
144 nprinted++;
145}
146
147return nprinted;
148}
149
150bool_doprnt_truncates = false;
151
152int
153__doprnt(
154 const char*fmt,
155 va_listargp,
156 /* character output routine */
157 void(*putc)(int ch, void *arg),
158 void *arg,
159 intradix)/* default radix - for '%r' */
160{
161intlength;
162intprec;
163boolladjust;
164charpadc;
165long longn;
166unsigned long longu;
167intplus_sign;
168intsign_char;
169boolaltfmt, truncate;
170intbase;
171charc;
172intcapitals;
173intlong_long;
174int nprinted = 0;
175
176while ((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 charbuf[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
574return nprinted;
575}
576#endif
577
578int
579prf(
580 const char*fmt,
581 va_listap,
582 /* character output routine */
583 void(*putc)(char))
584{
585 return __doprnt(fmt, ap, dummy_putc, putc, 10);
586}
587
588
589static char *copybyte_str;
590
591static void
592copybyte(
593 char byte)
594{
595 *copybyte_str++ = byte;
596 *copybyte_str = '\0';
597}
598
599int
600sprintf(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
611static void
612snprintf_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 */
625int
626vsnprintf(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 */
642int
643snprintf(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.c7.1 (Berkeley) 6/5/86
693 */
694#include <sys/param.h>
695
696#define SPACE1
697#define ZERO2
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 */
712static int
713printn(u_long n, int b, int flag, int minwidth, void (*putfn_p)(int ch, void *arg), void *putfn_arg)
714{
715char prbuf[11];
716register char *cp;
717int width = 0, neg = 0, len = 0;
718
719if (b == 10 && (int)n < 0) {
720neg = 1;
721n = (unsigned)(-(int)n);
722}
723cp = prbuf;
724do {
725*cp++ = "0123456789abcdef0123456789ABCDEF"[(flag & UCASE) + n%b];
726n /= b;
727width++;
728} while (n);
729
730if (neg) {
731(*putfn_p)('-', putfn_arg);
732width++;
733 len++;
734}
735while (width++ < minwidth)
736 {
737(*putfn_p)( (flag & ZERO) ? '0' : ' ', putfn_arg);
738 len++;
739 }
740
741do
742 {
743(*putfn_p)(*--cp, putfn_arg);
744 len++;
745
746 } while (cp > prbuf);
747
748 return len;
749}
750
751int __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{
759int b, c, len =0;
760char *s;
761int flag = 0, width = 0;
762int minwidth;
763 unsigned int *adx = (unsigned int*)argp;
764loop:
765while ((c = *fmt++) != '%') {
766if(c == '\0')
767return len;
768if (putfn_p) {
769(*putfn_p)(c, putfn_arg);
770}
771len++;
772}
773minwidth = 0;
774again:
775c = *fmt++;
776switch (c) {
777case 'l':
778goto again;
779case ' ':
780flag |= SPACE;
781goto again;
782case '0':
783if (minwidth == 0) {
784/* this is a flag */
785flag |= ZERO;
786goto again;
787} /* fall through */
788case '1':
789case '2':
790case '3':
791case '4':
792case '5':
793case '6':
794case '7':
795case '8':
796case '9':
797minwidth *= 10;
798minwidth += c - '0';
799goto again;
800 case 'X':
801flag |= UCASE;
802/* fall through */
803case 'x':
804b = 16;
805goto number;
806case 'd':
807b = 10;
808goto number;
809case 'o': case 'O':
810b = 8;
811number:
812len += printn((u_long)*adx, b, flag, minwidth, putfn_p, putfn_arg);
813break;
814case 's':
815s = (char *)*adx;
816while ((c = *s++)) {
817if (putfn_p) {
818(*putfn_p)(c, putfn_arg);
819}
820len++;
821width++;
822}
823while (width++ < minwidth) {
824if (putfn_p) {
825(*putfn_p)(' ', putfn_arg);
826}
827len++;
828}
829break;
830case 'c':
831if (putfn_p) {
832(*putfn_p)((char)*adx, putfn_arg);
833}
834len++;
835break;
836default:
837break;
838}
839adx++;
840goto loop;
841}
842#endif

Archive Download this file

Revision: 1984