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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [bootloaders/] [orpmon/] [coremark/] [ee_printf.c] - Blame information for rev 355

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

Line No. Rev Author Line
1 355 julius
/* File : barebones/ee_printf.c
2
        This file contains an implementation of ee_printf that only requires a method to output a char to a UART without pulling in library code.
3
 
4
This code is based on a file that contains the following:
5
 Copyright (C) 2002 Michael Ringgaard. All rights reserved.
6
 
7
 Redistribution and use in source and binary forms, with or without
8
 modification, are permitted provided that the following conditions
9
 are met:
10
 
11
 1. Redistributions of source code must retain the above copyright
12
    notice, this list of conditions and the following disclaimer.
13
 2. Redistributions in binary form must reproduce the above copyright
14
    notice, this list of conditions and the following disclaimer in the
15
    documentation and/or other materials provided with the distribution.
16
 3. Neither the name of the project nor the names of its contributors
17
    may be used to endorse or promote products derived from this software
18
    without specific prior written permission.
19
 
20
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 SUCH DAMAGE.
31
 
32
*/
33
 
34
#include "coremark.h"
35
#include <stdarg.h>
36
#include "support.h"
37
#include "board.h"
38
#include "uart.h"
39
 
40
#define ZEROPAD         (1<<0)  /* Pad with zero */
41
#define SIGN            (1<<1)  /* Unsigned/signed long */
42
#define PLUS            (1<<2)  /* Show plus */
43
#define SPACE           (1<<3)  /* Spacer */
44
#define LEFT            (1<<4)  /* Left justified */
45
#define HEX_PREP        (1<<5)  /* 0x */
46
#define UPPERCASE   (1<<6)      /* 'ABCDEF' */
47
 
48
#define is_digit(c) ((c) >= '0' && (c) <= '9')
49
 
50
static char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
51
static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
52
static size_t strnlen(const char *s, size_t count);
53
 
54
static size_t strnlen(const char *s, size_t count)
55
{
56
  const char *sc;
57
  for (sc = s; *sc != '\0' && count--; ++sc);
58
  return sc - s;
59
}
60
 
61
static int skip_atoi(const char **s)
62
{
63
  int i = 0;
64
  while (is_digit(**s)) i = i*10 + *((*s)++) - '0';
65
  return i;
66
}
67
 
68
static char *number(char *str, long num, int base, int size, int precision, int type)
69
{
70
  char c, sign, tmp[66];
71
  char *dig = digits;
72
  int i;
73
 
74
  if (type & UPPERCASE)  dig = upper_digits;
75
  if (type & LEFT) type &= ~ZEROPAD;
76
  if (base < 2 || base > 36) return 0;
77
 
78
  c = (type & ZEROPAD) ? '0' : ' ';
79
  sign = 0;
80
  if (type & SIGN)
81
  {
82
    if (num < 0)
83
    {
84
      sign = '-';
85
      num = -num;
86
      size--;
87
    }
88
    else if (type & PLUS)
89
    {
90
      sign = '+';
91
      size--;
92
    }
93
    else if (type & SPACE)
94
    {
95
      sign = ' ';
96
      size--;
97
    }
98
  }
99
 
100
  if (type & HEX_PREP)
101
  {
102
    if (base == 16)
103
      size -= 2;
104
    else if (base == 8)
105
      size--;
106
  }
107
 
108
  i = 0;
109
 
110
  if (num == 0)
111
    tmp[i++] = '0';
112
  else
113
  {
114
    while (num != 0)
115
    {
116
      tmp[i++] = dig[((unsigned long) num) % (unsigned) base];
117
      num = ((unsigned long) num) / (unsigned) base;
118
    }
119
  }
120
 
121
  if (i > precision) precision = i;
122
  size -= precision;
123
  if (!(type & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' ';
124
  if (sign) *str++ = sign;
125
 
126
  if (type & HEX_PREP)
127
  {
128
    if (base == 8)
129
      *str++ = '0';
130
    else if (base == 16)
131
    {
132
      *str++ = '0';
133
      *str++ = digits[33];
134
    }
135
  }
136
 
137
  if (!(type & LEFT)) while (size-- > 0) *str++ = c;
138
  while (i < precision--) *str++ = '0';
139
  while (i-- > 0) *str++ = tmp[i];
140
  while (size-- > 0) *str++ = ' ';
141
 
142
  return str;
143
}
144
 
145
static char *eaddr(char *str, unsigned char *addr, int size, int precision, int type)
146
{
147
  char tmp[24];
148
  char *dig = digits;
149
  int i, len;
150
 
151
  if (type & UPPERCASE)  dig = upper_digits;
152
  len = 0;
153
  for (i = 0; i < 6; i++)
154
  {
155
    if (i != 0) tmp[len++] = ':';
156
    tmp[len++] = dig[addr[i] >> 4];
157
    tmp[len++] = dig[addr[i] & 0x0F];
158
  }
159
 
160
  if (!(type & LEFT)) while (len < size--) *str++ = ' ';
161
  for (i = 0; i < len; ++i) *str++ = tmp[i];
162
  while (len < size--) *str++ = ' ';
163
 
164
  return str;
165
}
166
 
167
static char *iaddr(char *str, unsigned char *addr, int size, int precision, int type)
168
{
169
  char tmp[24];
170
  int i, n, len;
171
 
172
  len = 0;
173
  for (i = 0; i < 4; i++)
174
  {
175
    if (i != 0) tmp[len++] = '.';
176
    n = addr[i];
177
 
178
    if (n == 0)
179
      tmp[len++] = digits[0];
180
    else
181
    {
182
      if (n >= 100)
183
      {
184
        tmp[len++] = digits[n / 100];
185
        n = n % 100;
186
        tmp[len++] = digits[n / 10];
187
        n = n % 10;
188
      }
189
      else if (n >= 10)
190
      {
191
        tmp[len++] = digits[n / 10];
192
        n = n % 10;
193
      }
194
 
195
      tmp[len++] = digits[n];
196
    }
197
  }
198
 
199
  if (!(type & LEFT)) while (len < size--) *str++ = ' ';
200
  for (i = 0; i < len; ++i) *str++ = tmp[i];
201
  while (len < size--) *str++ = ' ';
202
 
203
  return str;
204
}
205
 
206
#ifdef HAS_FLOAT
207
 
208
char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
209
char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
210
static void ee_bufcpy(char *d, char *s, int count);
211
 
212
void ee_bufcpy(char *pd, char *ps, int count) {
213
        char *pe=ps+count;
214
        while (ps!=pe)
215
                *pd++=*ps++;
216
}
217
 
218
static void parse_float(double value, char *buffer, char fmt, int precision)
219
{
220
  int decpt, sign, exp, pos;
221
  char *digits = NULL;
222
  char cvtbuf[80];
223
  int capexp = 0;
224
  int magnitude;
225
 
226
  if (fmt == 'G' || fmt == 'E')
227
  {
228
    capexp = 1;
229
    fmt += 'a' - 'A';
230
  }
231
 
232
  if (fmt == 'g')
233
  {
234
    digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf);
235
    magnitude = decpt - 1;
236
    if (magnitude < -4  ||  magnitude > precision - 1)
237
    {
238
      fmt = 'e';
239
      precision -= 1;
240
    }
241
    else
242
    {
243
      fmt = 'f';
244
      precision -= decpt;
245
    }
246
  }
247
 
248
  if (fmt == 'e')
249
  {
250
    digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf);
251
 
252
    if (sign) *buffer++ = '-';
253
    *buffer++ = *digits;
254
    if (precision > 0) *buffer++ = '.';
255
    ee_bufcpy(buffer, digits + 1, precision);
256
    buffer += precision;
257
    *buffer++ = capexp ? 'E' : 'e';
258
 
259
    if (decpt == 0)
260
    {
261
      if (value == 0.0)
262
        exp = 0;
263
      else
264
        exp = -1;
265
    }
266
    else
267
      exp = decpt - 1;
268
 
269
    if (exp < 0)
270
    {
271
      *buffer++ = '-';
272
      exp = -exp;
273
    }
274
    else
275
      *buffer++ = '+';
276
 
277
    buffer[2] = (exp % 10) + '0';
278
    exp = exp / 10;
279
    buffer[1] = (exp % 10) + '0';
280
    exp = exp / 10;
281
    buffer[0] = (exp % 10) + '0';
282
    buffer += 3;
283
  }
284
  else if (fmt == 'f')
285
  {
286
    digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf);
287
    if (sign) *buffer++ = '-';
288
    if (*digits)
289
    {
290
      if (decpt <= 0)
291
      {
292
        *buffer++ = '0';
293
        *buffer++ = '.';
294
        for (pos = 0; pos < -decpt; pos++) *buffer++ = '0';
295
        while (*digits) *buffer++ = *digits++;
296
      }
297
      else
298
      {
299
        pos = 0;
300
        while (*digits)
301
        {
302
          if (pos++ == decpt) *buffer++ = '.';
303
          *buffer++ = *digits++;
304
        }
305
      }
306
    }
307
    else
308
    {
309
      *buffer++ = '0';
310
      if (precision > 0)
311
      {
312
        *buffer++ = '.';
313
        for (pos = 0; pos < precision; pos++) *buffer++ = '0';
314
      }
315
    }
316
  }
317
 
318
  *buffer = '\0';
319
}
320
 
321
static void decimal_point(char *buffer)
322
{
323
  while (*buffer)
324
  {
325
    if (*buffer == '.') return;
326
    if (*buffer == 'e' || *buffer == 'E') break;
327
    buffer++;
328
  }
329
 
330
  if (*buffer)
331
  {
332
    int n = strnlen(buffer,256);
333
    while (n > 0)
334
    {
335
      buffer[n + 1] = buffer[n];
336
      n--;
337
    }
338
 
339
    *buffer = '.';
340
  }
341
  else
342
  {
343
    *buffer++ = '.';
344
    *buffer = '\0';
345
  }
346
}
347
 
348
static void cropzeros(char *buffer)
349
{
350
  char *stop;
351
 
352
  while (*buffer && *buffer != '.') buffer++;
353
  if (*buffer++)
354
  {
355
    while (*buffer && *buffer != 'e' && *buffer != 'E') buffer++;
356
    stop = buffer--;
357
    while (*buffer == '0') buffer--;
358
    if (*buffer == '.') buffer--;
359
    while (buffer!=stop)
360
                *++buffer=0;
361
  }
362
}
363
 
364
static char *flt(char *str, double num, int size, int precision, char fmt, int flags)
365
{
366
  char tmp[80];
367
  char c, sign;
368
  int n, i;
369
 
370
  // Left align means no zero padding
371
  if (flags & LEFT) flags &= ~ZEROPAD;
372
 
373
  // Determine padding and sign char
374
  c = (flags & ZEROPAD) ? '0' : ' ';
375
  sign = 0;
376
  if (flags & SIGN)
377
  {
378
    if (num < 0.0)
379
    {
380
      sign = '-';
381
      num = -num;
382
      size--;
383
    }
384
    else if (flags & PLUS)
385
    {
386
      sign = '+';
387
      size--;
388
    }
389
    else if (flags & SPACE)
390
    {
391
      sign = ' ';
392
      size--;
393
    }
394
  }
395
 
396
  // Compute the precision value
397
  if (precision < 0)
398
    precision = 6; // Default precision: 6
399
 
400
  // Convert floating point number to text
401
  parse_float(num, tmp, fmt, precision);
402
 
403
  if ((flags & HEX_PREP) && precision == 0) decimal_point(tmp);
404
  if (fmt == 'g' && !(flags & HEX_PREP)) cropzeros(tmp);
405
 
406
  n = strnlen(tmp,256);
407
 
408
  // Output number with alignment and padding
409
  size -= n;
410
  if (!(flags & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' ';
411
  if (sign) *str++ = sign;
412
  if (!(flags & LEFT)) while (size-- > 0) *str++ = c;
413
  for (i = 0; i < n; i++) *str++ = tmp[i];
414
  while (size-- > 0) *str++ = ' ';
415
 
416
  return str;
417
}
418
 
419
#endif
420
 
421
static int ee_vsprintf(char *buf, const char *fmt, va_list args)
422
{
423
  int len;
424
  unsigned long num;
425
  int i, base;
426
  char *str;
427
  char *s;
428
 
429
  int flags;            // Flags to number()
430
 
431
  int field_width;      // Width of output field
432
  int precision;        // Min. # of digits for integers; max number of chars for from string
433
  int qualifier;        // 'h', 'l', or 'L' for integer fields
434
 
435
  for (str = buf; *fmt; fmt++)
436
  {
437
    if (*fmt != '%')
438
    {
439
      *str++ = *fmt;
440
      continue;
441
    }
442
 
443
    // Process flags
444
    flags = 0;
445
repeat:
446
    fmt++; // This also skips first '%'
447
    switch (*fmt)
448
    {
449
      case '-': flags |= LEFT; goto repeat;
450
      case '+': flags |= PLUS; goto repeat;
451
      case ' ': flags |= SPACE; goto repeat;
452
      case '#': flags |= HEX_PREP; goto repeat;
453
      case '0': flags |= ZEROPAD; goto repeat;
454
    }
455
 
456
    // Get field width
457
    field_width = -1;
458
    if (is_digit(*fmt))
459
      field_width = skip_atoi(&fmt);
460
    else if (*fmt == '*')
461
    {
462
      fmt++;
463
      field_width = va_arg(args, int);
464
      if (field_width < 0)
465
      {
466
        field_width = -field_width;
467
        flags |= LEFT;
468
      }
469
    }
470
 
471
    // Get the precision
472
    precision = -1;
473
    if (*fmt == '.')
474
    {
475
      ++fmt;
476
      if (is_digit(*fmt))
477
        precision = skip_atoi(&fmt);
478
      else if (*fmt == '*')
479
      {
480
        ++fmt;
481
        precision = va_arg(args, int);
482
      }
483
      if (precision < 0) precision = 0;
484
    }
485
 
486
    // Get the conversion qualifier
487
    qualifier = -1;
488
    if (*fmt == 'l' || *fmt == 'L')
489
    {
490
      qualifier = *fmt;
491
      fmt++;
492
    }
493
 
494
    // Default base
495
    base = 10;
496
 
497
    switch (*fmt)
498
    {
499
      case 'c':
500
        if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' ';
501
        *str++ = (unsigned char) va_arg(args, int);
502
        while (--field_width > 0) *str++ = ' ';
503
        continue;
504
 
505
      case 's':
506
        s = va_arg(args, char *);
507
        if (!s) s = "<NULL>";
508
        len = strnlen(s, precision);
509
        if (!(flags & LEFT)) while (len < field_width--) *str++ = ' ';
510
        for (i = 0; i < len; ++i) *str++ = *s++;
511
        while (len < field_width--) *str++ = ' ';
512
        continue;
513
 
514
      case 'p':
515
        if (field_width == -1)
516
        {
517
          field_width = 2 * sizeof(void *);
518
          flags |= ZEROPAD;
519
        }
520
        str = number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags);
521
        continue;
522
 
523
      case 'A':
524
        flags |= UPPERCASE;
525
 
526
      case 'a':
527
        if (qualifier == 'l')
528
          str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
529
        else
530
          str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
531
        continue;
532
 
533
      // Integer number formats - set up the flags and "break"
534
      case 'o':
535
        base = 8;
536
        break;
537
 
538
      case 'X':
539
        flags |= UPPERCASE;
540
 
541
      case 'x':
542
        base = 16;
543
        break;
544
 
545
      case 'd':
546
      case 'i':
547
        flags |= SIGN;
548
 
549
      case 'u':
550
        break;
551
 
552
#ifdef HAS_FLOAT
553
 
554
      case 'f':
555
        str = flt(str, va_arg(args, double), field_width, precision, *fmt, flags | SIGN);
556
        continue;
557
 
558
#endif
559
 
560
      default:
561
        if (*fmt != '%') *str++ = '%';
562
        if (*fmt)
563
          *str++ = *fmt;
564
        else
565
          --fmt;
566
        continue;
567
    }
568
 
569
    if (qualifier == 'l')
570
      num = va_arg(args, unsigned long);
571
    else if (flags & SIGN)
572
      num = va_arg(args, int);
573
    else
574
      num = va_arg(args, unsigned int);
575
 
576
    str = number(str, num, base, field_width, precision, flags);
577
  }
578
 
579
  *str = '\0';
580
  return str - buf;
581
}
582
 
583
void uart_send_char(char c) {
584
 
585
  uart_putc(c);
586
 
587
}
588
 
589
int ee_printf(const char *fmt, ...)
590
{
591
  char buf[256],*p;
592
  va_list args;
593
  int n=0;
594
 
595
  va_start(args, fmt);
596
  ee_vsprintf(buf, fmt, args);
597
  va_end(args);
598
  p=buf;
599
  while (*p) {
600
        uart_send_char(*p);
601
        n++;
602
        p++;
603
  }
604
 
605
  return n;
606
}
607
 

powered by: WebSVN 2.1.0

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