1 //==========================================================================
5 // Stripped down (no floating point) for debugging printf in ROMable BSP.
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: gthomas
50 //####DESCRIPTIONEND####
52 //=========================================================================
55 * Copyright (c) 1990, 1999 The Regents of the University of California.
56 * All rights reserved.
58 * This code is derived from software contributed to Berkeley by
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
64 * 1. Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer.
66 * 2. Redistributions in binary form must reproduce the above copyright
67 * notice, this list of conditions and the following disclaimer in the
68 * documentation and/or other materials provided with the distribution.
69 * 3. All advertising materials mentioning features or use of this software
70 * must display the following acknowledgement:
71 * This product includes software developed by the University of
72 * California, Berkeley and its contributors.
73 * 4. Neither the name of the University nor the names of its contributors
74 * may be used to endorse or promote products derived from this software
75 * without specific prior written permission.
77 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
78 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
80 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
81 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
82 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
83 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
84 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
85 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
86 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
91 * Stripped down (no floating point) for debugging printf in ROMable BSP.
99 #define NULL ((void *)0)
103 * Macros for converting digits to letters and vice versa
105 #define to_digit(c) ((c) - '0')
106 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
107 #define to_char(n) ((n) + '0')
110 * Flags used during conversion.
112 #define ALT 0x001 /* alternate form */
113 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
114 #define LADJUST 0x004 /* left adjustment */
115 #define LONGDBL 0x008 /* long double; unimplemented */
116 #define LONGINT 0x010 /* long integer */
117 #define QUADINT 0x020 /* quad integer */
118 #define SHORTINT 0x040 /* short integer */
119 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
120 #define FPT 0x100 /* Floating point number */
124 __vprintf(void (*putc_func)(char c), const char *fmt0, va_list ap)
126 char *fmt; /* format string */
127 int ch; /* character from fmt */
128 int n, m; /* handy integers (short term usage) */
129 char *cp; /* handy char pointer (short term usage) */
130 int flags; /* flags as above */
131 int width; /* width from format (%8d), or 0 */
132 int prec; /* precision from format (%.3d), or -1 */
133 char sign; /* sign prefix (' ', '+', '-', or \0) */
134 unsigned long _uquad;
135 enum {OCT, DEC, HEX} base; /* base for [diouxX] conversion */
136 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
137 int realsz; /* field size expanded by dprec */
138 int size; /* size of converted field or string */
139 char *xdigs = NULL; /* digits for [xX] conversion */
140 char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
141 char ox[2]; /* space for 0x hex-prefix */
143 #define PRINT(ptr, len) { \
144 for(n=0;n<(len);n++) { \
145 if((ptr)[n] == '\n') \
146 (*putc_func)('\r'); \
147 (*putc_func)((ptr)[n]); \
151 #define PAD(howmany, with) { \
152 if ((n = (howmany)) > 0) { \
154 (*putc_func)(with); \
159 * To extend shorts properly, we need both signed and unsigned
160 * argument extraction methods.
163 (flags&LONGINT ? va_arg(ap, long) : \
164 flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
165 (long)va_arg(ap, int))
168 (flags&LONGINT ? va_arg(ap, unsigned long) : \
169 flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \
170 (unsigned long)va_arg(ap, unsigned int))
175 * Scan the format for conversions (`%' character).
179 while (*fmt && *fmt != '%')
181 if ((m = fmt - cp) != 0) {
186 fmt++; /* skip over '%' */
202 * ``If the space and + flags both appear, the space
203 * flag will be ignored.''
214 * ``A negative field width argument is taken as a
215 * - flag followed by a positive field width.''
217 * They don't exclude field widths read from args.
219 if ((width = va_arg(ap, int)) >= 0)
230 if ((ch = *fmt++) == '*') {
232 prec = n < 0 ? -1 : n;
236 while (is_digit(ch)) {
237 n = 10 * n + to_digit(ch);
240 prec = n < 0 ? -1 : n;
244 * ``Note that 0 is taken as a flag, not as the
245 * beginning of a field width.''
250 case '1': case '2': case '3': case '4':
251 case '5': case '6': case '7': case '8': case '9':
254 n = 10 * n + to_digit(ch);
256 } while (is_digit(ch));
271 *(cp = buf) = va_arg(ap, int);
278 if ((long) _uquad < 0)
291 if ((cp = va_arg(ap, char *)) == NULL)
295 * can't use strlen; can only look for the
296 * NUL in the first `prec' characters, and
297 * strlen() will go further.
299 char *p = memchr(cp, 0, prec);
316 xdigs = "0123456789ABCDEF";
319 xdigs = "0123456789abcdef";
320 hex: _uquad = UARG();
322 /* leading 0x/X only if non-zero */
323 if (flags & ALT && _uquad != 0)
326 /* unsigned conversions */
329 * ``... diouXx conversions ... if a precision is
330 * specified, the 0 flag will be ignored.''
333 number: if ((dprec = prec) >= 0)
337 * ``The result of converting a zero value with an
338 * explicit precision of zero is no characters.''
342 if (_uquad != 0 || prec != 0) {
344 * Unsigned mod is hard, and unsigned mod
345 * by a constant is easier than that by
346 * a variable; hence this switch.
351 *--cp = to_char(_uquad & 7);
354 /* handle octal leading 0 */
355 if (flags & ALT && *cp != '0')
360 /* many numbers are 1 digit */
361 while (_uquad >= 10) {
362 *--cp = to_char(_uquad % 10);
365 *--cp = to_char(_uquad);
370 *--cp = xdigs[_uquad & 15];
376 cp = "bug in vfprintf: bad base";
381 size = buf + BUF - cp;
384 default: /* "%?" prints ?, unless ? is NUL */
387 /* pretend it was %c with argument ch */
396 * All reasonable formats wind up here. At this point, `cp'
397 * points to a string which (if not flags&LADJUST) should be
398 * padded out to `width' places. If flags&ZEROPAD, it should
399 * first be prefixed by any sign or other prefix; otherwise,
400 * it should be blank padded before the prefix is emitted.
401 * After any left-hand padding and prefixing, emit zeroes
402 * required by a decimal [diouxX] precision, then print the
403 * string proper, then emit zeroes required by any leftover
404 * floating precision; finally, if LADJUST, pad with blanks.
406 * Compute actual size, so we know how much to pad.
407 * size excludes decimal prec; realsz includes it.
409 realsz = dprec > size ? dprec : size;
412 else if (flags & HEXPREFIX)
415 /* right-adjusting blank padding */
416 if ((flags & (LADJUST|ZEROPAD)) == 0)
417 PAD(width - realsz, ' ');
422 } else if (flags & HEXPREFIX) {
428 /* right-adjusting zero padding */
429 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
430 PAD(width - realsz, '0');
432 /* leading zeroes from decimal precision */
433 PAD(dprec - size, '0');
435 /* the string or number proper */
438 /* left-adjusting padding (always blank) */
440 PAD(width - realsz, ' ');