OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [cygmon/] [v2_0/] [misc/] [bsp/] [common/] [vprintf.c] - Blame information for rev 586

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      vprintf.c
4
//
5
//      Stripped down (no floating point) for debugging printf in ROMable BSP.
6
//
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.
12
//
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.
16
//
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
20
// for more details.
21
//
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.
25
//
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.
32
//
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.
35
//
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####
42
//
43
// Author(s):    
44
// Contributors: gthomas
45
// Date:         1999-10-20
46
// Purpose:      
47
// Description:  
48
//               
49
//
50
//####DESCRIPTIONEND####
51
//
52
//=========================================================================
53
 
54
/*
55
 * Copyright (c) 1990, 1999 The Regents of the University of California.
56
 * All rights reserved.
57
 *
58
 * This code is derived from software contributed to Berkeley by
59
 * Chris Torek.
60
 *
61
 * Redistribution and use in source and binary forms, with or without
62
 * modification, are permitted provided that the following conditions
63
 * are met:
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.
76
 *
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
87
 * SUCH DAMAGE.
88
 */
89
 
90
/*
91
 * Stripped down (no floating point) for debugging printf in ROMable BSP.
92
 */
93
#include <string.h>
94
#include <stdarg.h>
95
 
96
#define BUF             40
97
 
98
#ifndef NULL
99
#define NULL ((void *)0)
100
#endif
101
 
102
/*
103
 * Macros for converting digits to letters and vice versa
104
 */
105
#define to_digit(c)     ((c) - '0')
106
#define is_digit(c)     ((unsigned)to_digit(c) <= 9)
107
#define to_char(n)      ((n) + '0')
108
 
109
/*
110
 * Flags used during conversion.
111
 */
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 */
121
 
122
 
123
void
124
__vprintf(void (*putc_func)(char c), const char *fmt0, va_list ap)
125
{
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 */
142
 
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]); \
148
        } \
149
}
150
 
151
#define PAD(howmany, with) {        \
152
        if ((n = (howmany)) > 0) {  \
153
            while (n--)             \
154
                (*putc_func)(with); \
155
        } \
156
}
157
 
158
    /*
159
     * To extend shorts properly, we need both signed and unsigned
160
     * argument extraction methods.
161
     */
162
#define SARG() \
163
        (flags&LONGINT ? va_arg(ap, long) : \
164
            flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
165
            (long)va_arg(ap, int))
166
 
167
#define UARG() \
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))
171
 
172
    fmt = (char *)fmt0;
173
 
174
    /*
175
     * Scan the format for conversions (`%' character).
176
     */
177
    for (;;) {
178
        cp = fmt;
179
        while (*fmt && *fmt != '%')
180
            fmt++;
181
        if ((m = fmt - cp) != 0) {
182
            PRINT(cp, m);
183
        }
184
 
185
        if (*fmt)
186
            fmt++;              /* skip over '%' */
187
        else
188
            goto done;
189
 
190
        flags = 0;
191
        dprec = 0;
192
        width = 0;
193
        prec = -1;
194
        sign = '\0';
195
 
196
    rflag:
197
        ch = *fmt++;
198
    reswitch:
199
        switch (ch) {
200
          case ' ':
201
            /*
202
             * ``If the space and + flags both appear, the space
203
             * flag will be ignored.''
204
             *  -- ANSI X3J11
205
             */
206
            if (!sign)
207
                sign = ' ';
208
            goto rflag;
209
          case '#':
210
            flags |= ALT;
211
            goto rflag;
212
          case '*':
213
            /*
214
             * ``A negative field width argument is taken as a
215
             * - flag followed by a positive field width.''
216
             *  -- ANSI X3J11
217
             * They don't exclude field widths read from args.
218
             */
219
            if ((width = va_arg(ap, int)) >= 0)
220
                goto rflag;
221
            width = -width;
222
            /* FALLTHROUGH */
223
          case '-':
224
            flags |= LADJUST;
225
            goto rflag;
226
          case '+':
227
            sign = '+';
228
            goto rflag;
229
          case '.':
230
            if ((ch = *fmt++) == '*') {
231
                n = va_arg(ap, int);
232
                prec = n < 0 ? -1 : n;
233
                goto rflag;
234
            }
235
            n = 0;
236
            while (is_digit(ch)) {
237
                n = 10 * n + to_digit(ch);
238
                ch = *fmt++;
239
            }
240
            prec = n < 0 ? -1 : n;
241
            goto reswitch;
242
          case '0':
243
            /*
244
             * ``Note that 0 is taken as a flag, not as the
245
             * beginning of a field width.''
246
             *  -- ANSI X3J11
247
             */
248
            flags |= ZEROPAD;
249
            goto rflag;
250
          case '1': case '2': case '3': case '4':
251
          case '5': case '6': case '7': case '8': case '9':
252
            n = 0;
253
            do {
254
                n = 10 * n + to_digit(ch);
255
                ch = *fmt++;
256
            } while (is_digit(ch));
257
            width = n;
258
            goto reswitch;
259
          case 'h':
260
            flags |= SHORTINT;
261
            goto rflag;
262
          case 'l':
263
            if (*fmt == 'l') {
264
                fmt++;
265
                flags |= QUADINT;
266
            } else {
267
                flags |= LONGINT;
268
            }
269
            goto rflag;
270
          case 'c':
271
            *(cp = buf) = va_arg(ap, int);
272
            size = 1;
273
            sign = '\0';
274
            break;
275
          case 'd':
276
          case 'i':
277
            _uquad = SARG();
278
            if ((long) _uquad < 0)
279
                {
280
 
281
                    _uquad = -_uquad;
282
                    sign = '-';
283
                }
284
            base = DEC;
285
            goto number;
286
          case 'o':
287
            _uquad = UARG();
288
            base = OCT;
289
            goto nosign;
290
          case 's':
291
            if ((cp = va_arg(ap, char *)) == NULL)
292
                cp = "(null)";
293
            if (prec >= 0) {
294
                /*
295
                 * can't use strlen; can only look for the
296
                 * NUL in the first `prec' characters, and
297
                 * strlen() will go further.
298
                 */
299
                char *p = memchr(cp, 0, prec);
300
 
301
                if (p != NULL) {
302
                    size = p - cp;
303
                    if (size > prec)
304
                        size = prec;
305
                } else
306
                    size = prec;
307
            } else
308
                size = strlen(cp);
309
            sign = '\0';
310
            break;
311
          case 'u':
312
            _uquad = UARG();
313
            base = DEC;
314
            goto nosign;
315
          case 'X':
316
            xdigs = "0123456789ABCDEF";
317
            goto hex;
318
          case 'x':
319
            xdigs = "0123456789abcdef";
320
        hex:                    _uquad = UARG();
321
            base = HEX;
322
            /* leading 0x/X only if non-zero */
323
            if (flags & ALT && _uquad != 0)
324
                flags |= HEXPREFIX;
325
 
326
            /* unsigned conversions */
327
        nosign:                 sign = '\0';
328
            /*
329
             * ``... diouXx conversions ... if a precision is
330
             * specified, the 0 flag will be ignored.''
331
             *  -- ANSI X3J11
332
             */
333
        number:                 if ((dprec = prec) >= 0)
334
            flags &= ~ZEROPAD;
335
 
336
            /*
337
             * ``The result of converting a zero value with an
338
             * explicit precision of zero is no characters.''
339
             *  -- ANSI X3J11
340
             */
341
            cp = buf + BUF;
342
            if (_uquad != 0 || prec != 0) {
343
                /*
344
                 * Unsigned mod is hard, and unsigned mod
345
                 * by a constant is easier than that by
346
                 * a variable; hence this switch.
347
                  */
348
                switch (base) {
349
                  case OCT:
350
                    do {
351
                        *--cp = to_char(_uquad & 7);
352
                        _uquad >>= 3;
353
                    } while (_uquad);
354
                    /* handle octal leading 0 */
355
                    if (flags & ALT && *cp != '0')
356
                        *--cp = '0';
357
                    break;
358
 
359
                  case DEC:
360
                    /* many numbers are 1 digit */
361
                    while (_uquad >= 10) {
362
                        *--cp = to_char(_uquad % 10);
363
                        _uquad /= 10;
364
                    }
365
                    *--cp = to_char(_uquad);
366
                    break;
367
 
368
                  case HEX:
369
                    do {
370
                        *--cp = xdigs[_uquad & 15];
371
                        _uquad >>= 4;
372
                    } while (_uquad);
373
                    break;
374
 
375
                  default:
376
                    cp = "bug in vfprintf: bad base";
377
                    size = strlen(cp);
378
                    goto skipsize;
379
                }
380
            }
381
            size = buf + BUF - cp;
382
        skipsize:
383
            break;
384
          default:      /* "%?" prints ?, unless ? is NUL */
385
            if (ch == '\0')
386
                goto done;
387
            /* pretend it was %c with argument ch */
388
            cp = buf;
389
            *cp = ch;
390
            size = 1;
391
            sign = '\0';
392
            break;
393
        }
394
 
395
        /*
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.
405
         *
406
         * Compute actual size, so we know how much to pad.
407
         * size excludes decimal prec; realsz includes it.
408
         */
409
        realsz = dprec > size ? dprec : size;
410
        if (sign)
411
            realsz++;
412
        else if (flags & HEXPREFIX)
413
            realsz+= 2;
414
 
415
        /* right-adjusting blank padding */
416
        if ((flags & (LADJUST|ZEROPAD)) == 0)
417
            PAD(width - realsz, ' ');
418
 
419
        /* prefix */
420
        if (sign) {
421
            PRINT(&sign, 1);
422
        } else if (flags & HEXPREFIX) {
423
            ox[0] = '0';
424
            ox[1] = ch;
425
            PRINT(ox, 2);
426
        }
427
 
428
        /* right-adjusting zero padding */
429
        if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
430
            PAD(width - realsz, '0');
431
 
432
        /* leading zeroes from decimal precision */
433
        PAD(dprec - size, '0');
434
 
435
        /* the string or number proper */
436
        PRINT(cp, size);
437
 
438
        /* left-adjusting padding (always blank) */
439
        if (flags & LADJUST)
440
            PAD(width - realsz, ' ');
441
    }
442
 done:
443
}
444
 
445
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.