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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [sw/] [lib/] [printf.c] - Blame information for rev 426

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

Line No. Rev Author Line
1 349 julius
// Ripped out of latest ecos build from 
2
//http://sources-redhat.mirrors.airband.net/ecos/releases/ecos-3.0b1/ecos-3.0beta1.i386linux.tar.bz2
3
// File: ecos-3.0b1/packages/language/c/libc/stdio/v3_0b1/src/output/vfnprintf.cxx
4
 
5
//  Hacked to pieces so it would work with OpenRISC compiler, not using libc
6
//===========================================================================
7
//
8
//      vfnprintf.c
9
//
10
//      I/O routines for vfnprintf() for use with ANSI C library
11
//
12
//===========================================================================
13
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
14
// -------------------------------------------                              
15
// This file is part of eCos, the Embedded Configurable Operating System.   
16
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
17
//
18
// eCos is free software; you can redistribute it and/or modify it under    
19
// the terms of the GNU General Public License as published by the Free     
20
// Software Foundation; either version 2 or (at your option) any later      
21
// version.                                                                 
22
//
23
// eCos is distributed in the hope that it will be useful, but WITHOUT      
24
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
25
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
26
// for more details.                                                        
27
//
28
// You should have received a copy of the GNU General Public License        
29
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
30
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
31
//
32
// As a special exception, if other files instantiate templates or use      
33
// macros or inline functions from this file, or you compile this file      
34
// and link it with other works to produce a work based on this file,       
35
// this file does not by itself cause the resulting work to be covered by   
36
// the GNU General Public License. However the source code for this file    
37
// must still be made available in accordance with section (3) of the GNU   
38
// General Public License v2.                                               
39
//
40
// This exception does not invalidate any other reasons why a work based    
41
// on this file might be covered by the GNU General Public License.         
42
// -------------------------------------------                              
43
// ####ECOSGPLCOPYRIGHTEND####                                              
44
//===========================================================================
45
//#####DESCRIPTIONBEGIN####
46
//
47
// Author(s):    jlarmour
48
// Contributors: 
49
// Date:         2000-04-20
50
// Purpose:     
51
// Description: 
52
// Usage:       
53
//
54
//####DESCRIPTIONEND####
55
//
56
//===========================================================================
57
//
58
// This code is based on original code with the following copyright:
59
//
60
/*-
61
 * Copyright (c) 1990 The Regents of the University of California.
62
 * All rights reserved.
63
 *
64
 * This code is derived from software contributed to Berkeley by
65
 * Chris Torek.
66
 *
67
 * Redistribution and use in source and binary forms, with or without
68
 * modification, are permitted provided that the following conditions
69
 * are met:
70
 * 1. Redistributions of source code must retain the above copyright
71
 *    notice, this list of conditions and the following disclaimer.
72
 * 2. Redistributions in binary form must reproduce the above copyright
73
 *    notice, this list of conditions and the following disclaimer in the
74
 *    documentation and/or other materials provided with the distribution.
75
 * 3. Neither the name of the University nor the names of its contributors
76
 *    may be used to endorse or promote products derived from this software
77
 *    without specific prior written permission.
78
 *
79
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
80
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
81
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
82
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
83
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
84
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
85
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
86
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
87
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
88
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
89
 * SUCH DAMAGE.
90
 */
91
 
92
 
93
// CONFIGURATION
94
 
95
//#include <pkgconf/libc_stdio.h>   // Configuration header
96
//#include <pkgconf/libc_i18n.h>    // Configuration header for mb support
97
 
98
// INCLUDES
99
 
100
//jb#include <stdarg.h>               // Variable argument definitions
101
//jb#include <string.h>               // memchr() and strlen() functions
102
//#include <stdio.h>                // Standard header for all stdio files
103
 
104
//#include <cyg/libc/stdio/stream.hxx> // C library streams
105
 
106
//#include "vfnprintf.h"
107
 
108
//jb#include <stddef.h> // for null, va_lsit
109
 
110 393 julius
#include "lib-utils.h" // has all these required basic c functions now
111 349 julius
 
112
//#include <cyg/infra/cyg_type.h>   // Common type definitions and support
113
#define CYG_MACRO_START do {
114
#define CYG_MACRO_END   } while (0)
115
 
116
#define CYG_EMPTY_STATEMENT CYG_MACRO_START CYG_MACRO_END
117
 
118
#define CYG_UNUSED_PARAM( _type_, _name_ ) CYG_MACRO_START      \
119
  _type_ __tmp1 = (_name_);                                     \
120
  _type_ __tmp2 = __tmp1;                                       \
121
  __tmp1 = __tmp2;                                              \
122
CYG_MACRO_END
123
 
124
 
125
# define BUF            40
126
 
127
/*
128
 * Actual printf innards.
129
 *
130
 * This code is large and complicated...
131
 */
132
 
133
 
134
/*
135
 * Macros for converting digits to letters and vice versa
136
 */
137
#define to_digit(c)     ((c) - '0')
138
#define is_digit(c)     ((unsigned)to_digit(c) <= 9)
139
#define to_char(n)      ((n) + '0')
140
 
141
/*
142
 * Flags used during conversion.
143
 */
144
#define ALT             0x001           /* alternate form */
145
#define HEXPREFIX       0x002           /* add 0x or 0X prefix */
146
#define LADJUST         0x004           /* left adjustment */
147
#define LONGDBL         0x008           /* long double; unimplemented */
148
#define LONGINT         0x010           /* long integer */
149
#define QUADINT         0x020           /* quad integer */
150
#define SHORTINT        0x040           /* short integer */
151
#define ZEROPAD         0x080           /* zero (as opposed to blank) pad */
152
#define FPT             0x100           /* Floating point number */
153
#define SIZET           0x200           /* size_t */
154
 
155
 
156
// Function which prints back to the buffer, ptr, len bytes
157
// returns 1 if it should finish up, otherwise 0 to continue
158
int
159
print_back_to_string(char * ptr, int len, size_t * n, int * ret, char ** stream)
160
{
161
#define MIN(a, b) ((a) < (b) ? (a) : (b))
162
  do {
163
    int length = MIN( (int) len, *n - *ret - 1);
164
    memcpy(*stream + *ret, ptr, length);
165
    if (length < (int)len) {
166
      *ret += length;
167
      return 1; // finish up
168
    }
169
 
170
  } while(0);
171
 
172
    return 0;
173
}
174
 
175
//externC int 
176
int
177
//vfnprintf ( FILE *stream, size_t n, const char *format, va_list arg) __THROW
178
vfnprintf ( char *stream, size_t n, const char *format, va_list arg)
179
{
180
  char *fmt;     /* format string */
181
  int ch;        /* character from fmt */
182
  int x, y;      /* handy integers (short term usage) */
183
  char *cp;      /* handy char pointer (short term usage) */
184
  int flags;     /* flags as above */
185
 
186
  int ret;                /* return value accumulator */
187
  int width;              /* width from format (%8d), or 0 */
188
  int prec;               /* precision from format (%.3d), or -1 */
189
  char sign;              /* sign prefix (' ', '+', '-', or \0) */
190
  wchar_t wc;
191
 
192
#define quad_t    long long
193
#define u_quad_t  unsigned long long
194
 
195
  u_quad_t _uquad;        /* integer arguments %[diouxX] */
196
  enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
197
  int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
198
  int fieldsz;            /* field size expanded by sign, etc */
199
  int realsz;             /* field size expanded by dprec */
200
  int size;               /* size of converted field or string */
201
  char *xdigs;            /* digits for [xX] conversion */
202
#define NIOV 8
203
  char buf[BUF];          /* space for %c, %[diouxX], %[eEfgG] */
204
  char ox[2];             /* space for 0x hex-prefix */
205
 
206
  /*
207
   * Choose PADSIZE to trade efficiency vs. size.  If larger printf
208
   * fields occur frequently, increase PADSIZE and make the initialisers
209
   * below longer.
210
   */
211
#define PADSIZE 16              /* pad chunk size */
212
  static char blanks[PADSIZE] =
213
    {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
214
  static char zeroes[PADSIZE] =
215
    {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
216
 
217
  /*
218
   * BEWARE, these `goto error' on error, and PAD uses `n'.
219
   */
220
 
221
  // We'll copy len bytes from (char*) ptr, into the output stream
222
  // making sure we don't go over the end, so calculate length to be
223
  // either the whole length we've been passed, or the whole length
224
  // that is possible to write
225
  // We finish if it was not possible to write the entire variable
226
  // into the buffer, ie we had to write all we could, not all we
227
  // wanted to.
228
  /*
229
    #define PRINT(ptr, len)                                             \
230
    CYG_MACRO_START                                                     \
231
    int length = MIN( (int) len, n - ret - 1);                          \
232
    char* begin_stream_write = stream;                                  \
233
    stream = memcpy(stream, ptr, length);                               \
234
    length = (unsigned long) stream - (unsigned long) begin_stream_write; \
235
    if (length < (int)len) {                                            \
236
    ret += length;                                                      \
237
    goto done;                                                          \
238
    }                                                                   \
239
    CYG_MACRO_END
240
  */
241
 
242
        //PRINT(with, PADSIZE);                                         \
243
      //PRINT(with, x);                                                 \
244
 
245
#define PAD(howmany, with)                                              \
246
  CYG_MACRO_START                                                       \
247
    if ((x = (howmany)) > 0) {                                           \
248
      while (x > PADSIZE) {                                             \
249
        if (print_back_to_string(with, PADSIZE, &n, &ret, &stream)) goto done; \
250
        x -= PADSIZE;                                                   \
251
      }                                                                 \
252
      if (print_back_to_string(with, x, &n, &ret, &stream))goto done;   \
253
    }                                                                   \
254
  CYG_MACRO_END
255
 
256
  /*
257
   * To extend shorts properly, we need both signed and unsigned
258
   * argument extraction methods.
259
   */
260
 
261
#define SARG()                                    \
262
  (flags&QUADINT ? va_arg(arg, long long) :       \
263
   flags&LONGINT ? va_arg(arg, long) :                       \
264
   flags&SHORTINT ? (long)(short)va_arg(arg, int) :          \
265
   flags&SIZET ? (long)va_arg(arg, size_t) :                 \
266
   (long)va_arg(arg, int))
267
#define UARG()                                             \
268
  (flags&QUADINT ? va_arg(arg, unsigned long long) :       \
269
   flags&LONGINT ? va_arg(arg, unsigned long) :                         \
270
   flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(arg, int) :   \
271
   flags&SIZET ? va_arg(arg, size_t) :                                  \
272
   (unsigned long)va_arg(arg, unsigned int))
273
 
274
 
275
  xdigs = NULL;  // stop compiler whinging
276
  fmt = (char *)format;
277
  ret = 0;
278
 
279
  /*
280
   * Scan the format for conversions (`%' character).
281
   */
282
  for (;;) {
283
    cp = (char *)fmt; // char pointer - set to where we begin looking from
284
    while ((x = ((wc = *fmt) != 0))) { // While, wc=next char and x is one while there's still chars left
285
      fmt += x; // increment the pointer to the char
286
      if (wc == '%') { // check if it's the beginning of
287
        fmt--; // Decrement the char pointer, actually
288
        break;
289
      }
290
    }
291
    if ((y = fmt - cp) != 0) { // y is length of string to copy out just now
292
      //PRINT(cp, y); // Copy macro 
293
      if(print_back_to_string(cp, y, &n, &ret, &stream)) goto done; // Copy macro 
294
      ret += y; // increment return chars
295
    }
296
    if ((x <= 0) || (ret >= (int)n))  // @@@ this check with n isn't good enough
297
      goto done;
298
    fmt++;          /* skip over '%' */
299
 
300
    flags = 0;
301
    dprec = 0;
302
    width = 0;
303
    prec = -1;
304
    sign = '\0';
305
 
306
  rflag:          ch = *fmt++;
307
  reswitch:       switch (ch) {
308
    case ' ':
309
      /*
310
       * ``If the space and + flags both appear, the space
311
       * flag will be ignored.''
312
       *      -- ANSI X3J11
313
       */
314
      if (!sign)
315
        sign = ' ';
316
      goto rflag;
317
    case '#':
318
      flags |= ALT;
319
      goto rflag;
320
    case '*':
321
      /*
322
       * ``A negative field width argument is taken as a
323
       * - flag followed by a positive field width.''
324
       *      -- ANSI X3J11
325
       * They don't exclude field widths read from args.
326
       */
327
      if ((width = va_arg(arg, int)) >= 0)
328
        goto rflag;
329
      width = -width;
330
      /* FALLTHROUGH */
331
    case '-':
332
      flags |= LADJUST;
333
      goto rflag;
334
    case '+':
335
      sign = '+';
336
      goto rflag;
337
    case '.':
338
      if ((ch = *fmt++) == '*') {
339
        x = va_arg(arg, int);
340
        prec = x < 0 ? -1 : x;
341
        goto rflag;
342
      }
343
      x = 0;
344
      while (is_digit(ch)) {
345
        x = 10 * x + to_digit(ch);
346
        ch = *fmt++;
347
      }
348
      prec = x < 0 ? -1 : x;
349
      goto reswitch;
350
    case '0':
351
      /*
352
       * ``Note that 0 is taken as a flag, not as the
353
       * beginning of a field width.''
354
       *      -- ANSI X3J11
355
       */
356
      flags |= ZEROPAD;
357
      goto rflag;
358
    case '1': case '2': case '3': case '4':
359
    case '5': case '6': case '7': case '8': case '9':
360
      x = 0;
361
      do {
362
        x = 10 * x + to_digit(ch);
363
        ch = *fmt++;
364
      } while (is_digit(ch));
365
      width = x;
366
      goto reswitch;
367
    case 'h':
368
      flags |= SHORTINT;
369
      goto rflag;
370
    case 'l':
371
      if (*fmt == 'l') {
372
        fmt++;
373
        flags |= QUADINT;
374
      } else {
375
        flags |= LONGINT;
376
      }
377
      goto rflag;
378
    case 'q':
379
      flags |= QUADINT;
380
      goto rflag;
381
    case 'c':
382
      *(cp = buf) = va_arg(arg, int);
383
      size = 1;
384
      sign = '\0';
385
      break;
386
    case 'D':
387
      flags |= LONGINT;
388
      /*FALLTHROUGH*/
389
    case 'd':
390
    case 'i':
391
      _uquad = SARG();
392
#ifndef _NO_LONGLONG
393
      if ((quad_t)_uquad < 0)
394
#else
395
        if ((long) _uquad < 0)
396
#endif
397
          {
398
 
399
            _uquad = -_uquad;
400
            sign = '-';
401
          }
402
      base = DEC;
403
      goto number;
404
 
405
    case 'e':
406
    case 'E':
407
    case 'f':
408
    case 'g':
409
    case 'G':
410
      // Output nothing at all
411
      (void) va_arg(arg, double); // take off arg anyway
412
      cp = "";
413
      size = 0;
414
      sign = '\0';
415
      break;
416
 
417
    case 'n':
418
#ifndef _NO_LONGLONG
419
      if (flags & QUADINT)
420
        *va_arg(arg, quad_t *) = ret;
421
      else
422
#endif
423
        if (flags & LONGINT)
424
          *va_arg(arg, long *) = ret;
425
        else if (flags & SHORTINT)
426
          *va_arg(arg, short *) = ret;
427
        else if (flags & SIZET)
428
          *va_arg(arg, size_t *) = ret;
429
        else
430
          *va_arg(arg, int *) = ret;
431
      continue;       /* no output */
432
    case 'O':
433
      flags |= LONGINT;
434
      /*FALLTHROUGH*/
435
    case 'o':
436
      _uquad = UARG();
437
      base = OCT;
438
      goto nosign;
439
    case 'p':
440
      /*
441
       * ``The argument shall be a pointer to void.  The
442
       * value of the pointer is converted to a sequence
443
       * of printable characters, in an implementation-
444
       * defined manner.''
445
       *      -- ANSI X3J11
446
       */
447
      /* NOSTRICT */
448
      _uquad = (unsigned long)va_arg(arg, void *);
449
      base = HEX;
450
      xdigs = (char *)"0123456789abcdef";
451
      flags |= HEXPREFIX;
452
      ch = 'x';
453
      goto nosign;
454
    case 's':
455
      if ((cp = va_arg(arg, char *)) == NULL)
456
        cp = (char *)"(null)";
457
      if (prec >= 0) {
458
        /*
459
         * can't use strlen; can only look for the
460
         * NUL in the first `prec' characters, and
461
         * strlen() will go further.
462
         */
463
        char *p = (char *)memchr(cp, 0, prec);
464
 
465
        if (p != NULL) {
466
          size = p - cp;
467
          if (size > prec)
468
            size = prec;
469
        } else
470
          size = prec;
471
      } else
472
        size = strlen(cp);
473
      sign = '\0';
474
      break;
475
    case 'U':
476
      flags |= LONGINT;
477
      /*FALLTHROUGH*/
478
    case 'u':
479
      _uquad = UARG();
480
      base = DEC;
481
      goto nosign;
482
    case 'X':
483
      xdigs = (char *)"0123456789ABCDEF";
484
      goto hex;
485
    case 'x':
486
      xdigs = (char *)"0123456789abcdef";
487
    hex:                    _uquad = UARG();
488
      base = HEX;
489
      /* leading 0x/X only if non-zero */
490
      if (flags & ALT && _uquad != 0)
491
        flags |= HEXPREFIX;
492
 
493
      /* unsigned conversions */
494
    nosign:                 sign = '\0';
495
      /*
496
       * ``... diouXx conversions ... if a precision is
497
       * specified, the 0 flag will be ignored.''
498
       *      -- ANSI X3J11
499
       */
500
    number:                 if ((dprec = prec) >= 0)
501
        flags &= ~ZEROPAD;
502
 
503
      /*
504
       * ``The result of converting a zero value with an
505
       * explicit precision of zero is no characters.''
506
       *      -- ANSI X3J11
507
       */
508
      cp = buf + BUF;
509
      if (_uquad != 0 || prec != 0) {
510
        /*
511
         * Unsigned mod is hard, and unsigned mod
512
         * by a constant is easier than that by
513
         * a variable; hence this switch.
514
         */
515
        switch (base) {
516
        case OCT:
517
          do {
518
            *--cp = to_char(_uquad & 7);
519
            _uquad >>= 3;
520
          } while (_uquad);
521
          /* handle octal leading 0 */
522
          if (flags & ALT && *cp != '0')
523
            *--cp = '0';
524
          break;
525
 
526
        case DEC:
527
          if (!(flags & QUADINT)) {
528
            /* many numbers are 1 digit */
529
            unsigned long v = (unsigned long)_uquad;
530
            while (v >= 10) {
531
              /* The following is usually faster than using a modulo */
532
              unsigned long next = v / 10;
533
              *--cp = to_char(v - (next * 10));
534
              v = next;
535
            }
536
            *--cp = to_char(v);
537
          }
538
          else {
539
            while (_uquad >= 10) {
540
              /* The following is usually faster than using a modulo */
541
              u_quad_t next = _uquad / 10;
542
              *--cp = to_char(_uquad - (next * 10));
543
              _uquad = next;
544
            }
545
            *--cp = to_char(_uquad);
546
          }
547
          break;
548
 
549
        case HEX:
550
          do {
551
            *--cp = xdigs[_uquad & 15];
552
            _uquad >>= 4;
553
          } while (_uquad);
554
          break;
555
 
556
        default:
557
          cp = (char *)"bug in vfprintf: bad base";
558
          size = strlen(cp);
559
          goto skipsize;
560
        }
561
      }
562
      size = buf + BUF - cp;
563
    skipsize:
564
      break;
565
    case 'z':
566
      flags |= SIZET;
567
      goto rflag;
568
    default:        /* "%?" prints ?, unless ? is NUL */
569
      if (ch == '\0')
570
        goto done;
571
      /* pretend it was %c with argument ch */
572
      cp = buf;
573
      *cp = ch;
574
      size = 1;
575
      sign = '\0';
576
      break;
577
    }
578
 
579
    /*
580
     * All reasonable formats wind up here.  At this point, `cp'
581
     * points to a string which (if not flags&LADJUST) should be
582
     * padded out to `width' places.  If flags&ZEROPAD, it should
583
     * first be prefixed by any sign or other prefix; otherwise,
584
     * it should be blank padded before the prefix is emitted.
585
     * After any left-hand padding and prefixing, emit zeroes
586
     * required by a decimal [diouxX] precision, then print the
587
     * string proper, then emit zeroes required by any leftover
588
     * floating precision; finally, if LADJUST, pad with blanks.
589
     *
590
     * Compute actual size, so we know how much to pad.
591
     * fieldsz excludes decimal prec; realsz includes it.
592
     */
593
#ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT
594
    fieldsz = size + fpprec;
595
#else
596
    fieldsz = size;
597
#endif
598
    if (sign)
599
      fieldsz++;
600
    else if (flags & HEXPREFIX)
601
      fieldsz+= 2;
602
    realsz = dprec > fieldsz ? dprec : fieldsz;
603
 
604
    /* right-adjusting blank padding */
605
    if ((flags & (LADJUST|ZEROPAD)) == 0) {
606
      if (width - realsz > 0) {
607
        PAD(width - realsz, blanks);
608
        ret += width - realsz;
609
      }
610
    }
611
 
612
    /* prefix */
613
    if (sign) {
614
      //PRINT(&sign, 1);
615
      if(print_back_to_string(&sign, 1, &n, &ret, &stream))goto done;
616
      ret++;
617
    } else if (flags & HEXPREFIX) {
618
      ox[0] = '0';
619
      ox[1] = ch;
620
      //PRINT(ox, 2);
621
      if(print_back_to_string(ox, 2, &n, &ret, &stream))goto done;
622
      ret += 2;
623
    }
624
 
625
    /* right-adjusting zero padding */
626
    if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) {
627
      if (width - realsz > 0) {
628
        PAD(width - realsz, zeroes);
629
        ret += width - realsz;
630
      }
631
    }
632
 
633
    if (dprec - fieldsz > 0) {
634
      /* leading zeroes from decimal precision */
635
      PAD(dprec - fieldsz, zeroes);
636
      ret += dprec - fieldsz;
637
    }
638
 
639
    /* the string or number proper */
640
    //PRINT(cp, size);
641
    if(print_back_to_string(cp,size, &n, &ret, &stream))goto done;
642
    ret += size;
643
 
644
#ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT
645
    /* trailing f.p. zeroes */
646
    PAD(fpprec, zeroes);
647
    ret += fpprec;
648
#endif
649
 
650
    /* left-adjusting padding (always blank) */
651
    if (flags & LADJUST) {
652
      if (width - realsz > 0) {
653
        PAD(width - realsz, blanks);
654
        ret += width - realsz;
655
      }
656
    }
657
 
658
  }
659
 
660
 done:
661
 error:
662
  return ret;// remove this error stuff (((Cyg_OutputStream *) stream)->get_error() ? EOF : ret);
663
  /* NOTREACHED */
664
}
665
 
666
#include "printf.h"
667
 
668
// Actual printf function we call, with static buffer of 512 bytes
669
char PRINTFBUFFER[PRINTFBUFFER_SIZE]; // Declare a global printf buffer
670
 
671
int
672
printf_to_sim(const char *fmt, ...)
673
{
674
 
675
  va_list args;
676
  va_start(args, fmt);
677
 
678
  int str_l = vfnprintf(PRINTFBUFFER, PRINTFBUFFER_SIZE, fmt, args);
679
 
680
  if (!str_l) return -1; // no length string - just return
681
 
682
  char c;
683
  int i=0;
684
  while(i<str_l)  sim_putc(PRINTFBUFFER[i++]);
685
 
686
  va_end(args);
687
 
688
  return str_l;
689
}
690
 
691
int
692
puts_to_sim(const char *str)
693
{
694
  return printf_to_sim("%s\n", str);
695
}
696
 
697 393 julius
// Calls to the UART driver are always in the library - hence it is always
698
// required to compile everything.
699 349 julius
#include "uart.h"
700
 
701
int
702
printf_to_uart(const char *fmt, ...)
703
{
704
 
705
  va_list args;
706
  va_start(args, fmt);
707
 
708
  int str_l = vfnprintf(PRINTFBUFFER, PRINTFBUFFER_SIZE, fmt, args);
709
 
710
  if (!str_l) return -1; // no length string - just return
711
 
712
  // Assumes uart is initialised
713
  int i=0;while(i<str_l) uart_putc(DEFAULT_UART,PRINTFBUFFER[i++]);
714
 
715
  va_end(args);
716
 
717
  return str_l;
718
 
719
}
720
 
721
int
722
putchar_to_uart(int c)
723
{
724
  printf_to_uart("%c",c);
725
 
726
  return c;
727
}
728
 
729
int
730
puts_to_uart(const char *str)
731
{
732
  return printf_to_uart("%s\n", str);
733
}
734
 
735
// EOF printf.c

powered by: WebSVN 2.1.0

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