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

Subversion Repositories openrisc

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

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 406 julius
        const char *sc;
57
        for (sc = s; *sc != '\0' && count--; ++sc) ;
58
        return sc - s;
59 355 julius
}
60
 
61
static int skip_atoi(const char **s)
62
{
63 406 julius
        int i = 0;
64
        while (is_digit(**s))
65
                i = i * 10 + *((*s)++) - '0';
66
        return i;
67 355 julius
}
68
 
69 406 julius
static char *number(char *str, long num, int base, int size, int precision,
70
                    int type)
71 355 julius
{
72 406 julius
        char c, sign, tmp[66];
73
        char *dig = digits;
74
        int i;
75 355 julius
 
76 406 julius
        if (type & UPPERCASE)
77
                dig = upper_digits;
78
        if (type & LEFT)
79
                type &= ~ZEROPAD;
80
        if (base < 2 || base > 36)
81
                return 0;
82 355 julius
 
83 406 julius
        c = (type & ZEROPAD) ? '0' : ' ';
84
        sign = 0;
85
        if (type & SIGN) {
86
                if (num < 0) {
87
                        sign = '-';
88
                        num = -num;
89
                        size--;
90
                } else if (type & PLUS) {
91
                        sign = '+';
92
                        size--;
93
                } else if (type & SPACE) {
94
                        sign = ' ';
95
                        size--;
96
                }
97
        }
98 355 julius
 
99 406 julius
        if (type & HEX_PREP) {
100
                if (base == 16)
101
                        size -= 2;
102
                else if (base == 8)
103
                        size--;
104
        }
105 355 julius
 
106 406 julius
        i = 0;
107 355 julius
 
108 406 julius
        if (num == 0)
109
                tmp[i++] = '0';
110
        else {
111
                while (num != 0) {
112
                        tmp[i++] = dig[((unsigned long)num) % (unsigned)base];
113
                        num = ((unsigned long)num) / (unsigned)base;
114
                }
115
        }
116 355 julius
 
117 406 julius
        if (i > precision)
118
                precision = i;
119
        size -= precision;
120
        if (!(type & (ZEROPAD | LEFT)))
121
                while (size-- > 0)
122
                        *str++ = ' ';
123
        if (sign)
124
                *str++ = sign;
125 355 julius
 
126 406 julius
        if (type & HEX_PREP) {
127
                if (base == 8)
128
                        *str++ = '0';
129
                else if (base == 16) {
130
                        *str++ = '0';
131
                        *str++ = digits[33];
132
                }
133
        }
134
 
135
        if (!(type & LEFT))
136
                while (size-- > 0)
137
                        *str++ = c;
138
        while (i < precision--)
139
                *str++ = '0';
140
        while (i-- > 0)
141
                *str++ = tmp[i];
142
        while (size-- > 0)
143
                *str++ = ' ';
144
 
145
        return str;
146 355 julius
}
147
 
148 406 julius
static char *eaddr(char *str, unsigned char *addr, int size, int precision,
149
                   int type)
150 355 julius
{
151 406 julius
        char tmp[24];
152
        char *dig = digits;
153
        int i, len;
154 355 julius
 
155 406 julius
        if (type & UPPERCASE)
156
                dig = upper_digits;
157
        len = 0;
158
        for (i = 0; i < 6; i++) {
159
                if (i != 0)
160
                        tmp[len++] = ':';
161
                tmp[len++] = dig[addr[i] >> 4];
162
                tmp[len++] = dig[addr[i] & 0x0F];
163
        }
164 355 julius
 
165 406 julius
        if (!(type & LEFT))
166
                while (len < size--)
167
                        *str++ = ' ';
168
        for (i = 0; i < len; ++i)
169
                *str++ = tmp[i];
170
        while (len < size--)
171
                *str++ = ' ';
172 355 julius
 
173 406 julius
        return str;
174 355 julius
}
175
 
176 406 julius
static char *iaddr(char *str, unsigned char *addr, int size, int precision,
177
                   int type)
178 355 julius
{
179 406 julius
        char tmp[24];
180
        int i, n, len;
181 355 julius
 
182 406 julius
        len = 0;
183
        for (i = 0; i < 4; i++) {
184
                if (i != 0)
185
                        tmp[len++] = '.';
186
                n = addr[i];
187 355 julius
 
188 406 julius
                if (n == 0)
189
                        tmp[len++] = digits[0];
190
                else {
191
                        if (n >= 100) {
192
                                tmp[len++] = digits[n / 100];
193
                                n = n % 100;
194
                                tmp[len++] = digits[n / 10];
195
                                n = n % 10;
196
                        } else if (n >= 10) {
197
                                tmp[len++] = digits[n / 10];
198
                                n = n % 10;
199
                        }
200 355 julius
 
201 406 julius
                        tmp[len++] = digits[n];
202
                }
203
        }
204 355 julius
 
205 406 julius
        if (!(type & LEFT))
206
                while (len < size--)
207
                        *str++ = ' ';
208
        for (i = 0; i < len; ++i)
209
                *str++ = tmp[i];
210
        while (len < size--)
211
                *str++ = ' ';
212
 
213
        return str;
214 355 julius
}
215
 
216
#ifdef HAS_FLOAT
217
 
218
char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
219
char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
220 406 julius
static void ee_bufcpy(char *d, char *s, int count);
221
 
222
void ee_bufcpy(char *pd, char *ps, int count)
223
{
224
        char *pe = ps + count;
225
        while (ps != pe)
226
                *pd++ = *ps++;
227 355 julius
}
228
 
229
static void parse_float(double value, char *buffer, char fmt, int precision)
230
{
231 406 julius
        int decpt, sign, exp, pos;
232
        char *digits = NULL;
233
        char cvtbuf[80];
234
        int capexp = 0;
235
        int magnitude;
236 355 julius
 
237 406 julius
        if (fmt == 'G' || fmt == 'E') {
238
                capexp = 1;
239
                fmt += 'a' - 'A';
240
        }
241 355 julius
 
242 406 julius
        if (fmt == 'g') {
243
                digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf);
244
                magnitude = decpt - 1;
245
                if (magnitude < -4 || magnitude > precision - 1) {
246
                        fmt = 'e';
247
                        precision -= 1;
248
                } else {
249
                        fmt = 'f';
250
                        precision -= decpt;
251
                }
252
        }
253 355 julius
 
254 406 julius
        if (fmt == 'e') {
255
                digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf);
256 355 julius
 
257 406 julius
                if (sign)
258
                        *buffer++ = '-';
259
                *buffer++ = *digits;
260
                if (precision > 0)
261
                        *buffer++ = '.';
262
                ee_bufcpy(buffer, digits + 1, precision);
263
                buffer += precision;
264
                *buffer++ = capexp ? 'E' : 'e';
265 355 julius
 
266 406 julius
                if (decpt == 0) {
267
                        if (value == 0.0)
268
                                exp = 0;
269
                        else
270
                                exp = -1;
271
                } else
272
                        exp = decpt - 1;
273 355 julius
 
274 406 julius
                if (exp < 0) {
275
                        *buffer++ = '-';
276
                        exp = -exp;
277
                } else
278
                        *buffer++ = '+';
279 355 julius
 
280 406 julius
                buffer[2] = (exp % 10) + '0';
281
                exp = exp / 10;
282
                buffer[1] = (exp % 10) + '0';
283
                exp = exp / 10;
284
                buffer[0] = (exp % 10) + '0';
285
                buffer += 3;
286
        } else if (fmt == 'f') {
287
                digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf);
288
                if (sign)
289
                        *buffer++ = '-';
290
                if (*digits) {
291
                        if (decpt <= 0) {
292
                                *buffer++ = '0';
293
                                *buffer++ = '.';
294
                                for (pos = 0; pos < -decpt; pos++)
295
                                        *buffer++ = '0';
296
                                while (*digits)
297
                                        *buffer++ = *digits++;
298
                        } else {
299
                                pos = 0;
300
                                while (*digits) {
301
                                        if (pos++ == decpt)
302
                                                *buffer++ = '.';
303
                                        *buffer++ = *digits++;
304
                                }
305
                        }
306
                } else {
307
                        *buffer++ = '0';
308
                        if (precision > 0) {
309
                                *buffer++ = '.';
310
                                for (pos = 0; pos < precision; pos++)
311
                                        *buffer++ = '0';
312
                        }
313
                }
314
        }
315 355 julius
 
316 406 julius
        *buffer = '\0';
317 355 julius
}
318
 
319
static void decimal_point(char *buffer)
320
{
321 406 julius
        while (*buffer) {
322
                if (*buffer == '.')
323
                        return;
324
                if (*buffer == 'e' || *buffer == 'E')
325
                        break;
326
                buffer++;
327
        }
328 355 julius
 
329 406 julius
        if (*buffer) {
330
                int n = strnlen(buffer, 256);
331
                while (n > 0) {
332
                        buffer[n + 1] = buffer[n];
333
                        n--;
334
                }
335 355 julius
 
336 406 julius
                *buffer = '.';
337
        } else {
338
                *buffer++ = '.';
339
                *buffer = '\0';
340
        }
341 355 julius
}
342
 
343
static void cropzeros(char *buffer)
344
{
345 406 julius
        char *stop;
346 355 julius
 
347 406 julius
        while (*buffer && *buffer != '.')
348
                buffer++;
349
        if (*buffer++) {
350
                while (*buffer && *buffer != 'e' && *buffer != 'E')
351
                        buffer++;
352
                stop = buffer--;
353
                while (*buffer == '0')
354
                        buffer--;
355
                if (*buffer == '.')
356
                        buffer--;
357
                while (buffer != stop)
358
                        *++buffer = 0;
359
        }
360 355 julius
}
361
 
362 406 julius
static char *flt(char *str, double num, int size, int precision, char fmt,
363
                 int flags)
364 355 julius
{
365 406 julius
        char tmp[80];
366
        char c, sign;
367
        int n, i;
368 355 julius
 
369 406 julius
        // Left align means no zero padding
370
        if (flags & LEFT)
371
                flags &= ~ZEROPAD;
372 355 julius
 
373 406 julius
        // Determine padding and sign char
374
        c = (flags & ZEROPAD) ? '0' : ' ';
375
        sign = 0;
376
        if (flags & SIGN) {
377
                if (num < 0.0) {
378
                        sign = '-';
379
                        num = -num;
380
                        size--;
381
                } else if (flags & PLUS) {
382
                        sign = '+';
383
                        size--;
384
                } else if (flags & SPACE) {
385
                        sign = ' ';
386
                        size--;
387
                }
388
        }
389
        // Compute the precision value
390
        if (precision < 0)
391
                precision = 6;  // Default precision: 6
392 355 julius
 
393 406 julius
        // Convert floating point number to text
394
        parse_float(num, tmp, fmt, precision);
395 355 julius
 
396 406 julius
        if ((flags & HEX_PREP) && precision == 0)
397
                decimal_point(tmp);
398
        if (fmt == 'g' && !(flags & HEX_PREP))
399
                cropzeros(tmp);
400 355 julius
 
401 406 julius
        n = strnlen(tmp, 256);
402 355 julius
 
403 406 julius
        // Output number with alignment and padding
404
        size -= n;
405
        if (!(flags & (ZEROPAD | LEFT)))
406
                while (size-- > 0)
407
                        *str++ = ' ';
408
        if (sign)
409
                *str++ = sign;
410
        if (!(flags & LEFT))
411
                while (size-- > 0)
412
                        *str++ = c;
413
        for (i = 0; i < n; i++)
414
                *str++ = tmp[i];
415
        while (size-- > 0)
416
                *str++ = ' ';
417 355 julius
 
418 406 julius
        return str;
419 355 julius
}
420
 
421
#endif
422
 
423
static int ee_vsprintf(char *buf, const char *fmt, va_list args)
424
{
425 406 julius
        int len;
426
        unsigned long num;
427
        int i, base;
428
        char *str;
429
        char *s;
430 355 julius
 
431 406 julius
        int flags;              // Flags to number()
432 355 julius
 
433 406 julius
        int field_width;        // Width of output field
434
        int precision;          // Min. # of digits for integers; max number of chars for from string
435
        int qualifier;          // 'h', 'l', or 'L' for integer fields
436 355 julius
 
437 406 julius
        for (str = buf; *fmt; fmt++) {
438
                if (*fmt != '%') {
439
                        *str++ = *fmt;
440
                        continue;
441
                }
442
                // Process flags
443
                flags = 0;
444 355 julius
repeat:
445 406 julius
                fmt++;          // This also skips first '%'
446
                switch (*fmt) {
447
                case '-':
448
                        flags |= LEFT;
449
                        goto repeat;
450
                case '+':
451
                        flags |= PLUS;
452
                        goto repeat;
453
                case ' ':
454
                        flags |= SPACE;
455
                        goto repeat;
456
                case '#':
457
                        flags |= HEX_PREP;
458
                        goto repeat;
459
                case '0':
460
                        flags |= ZEROPAD;
461
                        goto repeat;
462
                }
463 355 julius
 
464 406 julius
                // Get field width
465
                field_width = -1;
466
                if (is_digit(*fmt))
467
                        field_width = skip_atoi(&fmt);
468
                else if (*fmt == '*') {
469
                        fmt++;
470
                        field_width = va_arg(args, int);
471
                        if (field_width < 0) {
472
                                field_width = -field_width;
473
                                flags |= LEFT;
474
                        }
475
                }
476
                // Get the precision
477
                precision = -1;
478
                if (*fmt == '.') {
479
                        ++fmt;
480
                        if (is_digit(*fmt))
481
                                precision = skip_atoi(&fmt);
482
                        else if (*fmt == '*') {
483
                                ++fmt;
484
                                precision = va_arg(args, int);
485
                        }
486
                        if (precision < 0)
487
                                precision = 0;
488
                }
489
                // Get the conversion qualifier
490
                qualifier = -1;
491
                if (*fmt == 'l' || *fmt == 'L') {
492
                        qualifier = *fmt;
493
                        fmt++;
494
                }
495
                // Default base
496
                base = 10;
497 355 julius
 
498 406 julius
                switch (*fmt) {
499
                case 'c':
500
                        if (!(flags & LEFT))
501
                                while (--field_width > 0)
502
                                        *str++ = ' ';
503
                        *str++ = (unsigned char)va_arg(args, int);
504
                        while (--field_width > 0)
505
                                *str++ = ' ';
506
                        continue;
507 355 julius
 
508 406 julius
                case 's':
509
                        s = va_arg(args, char *);
510
                        if (!s)
511
                                s = "<NULL>";
512
                        len = strnlen(s, precision);
513
                        if (!(flags & LEFT))
514
                                while (len < field_width--)
515
                                        *str++ = ' ';
516
                        for (i = 0; i < len; ++i)
517
                                *str++ = *s++;
518
                        while (len < field_width--)
519
                                *str++ = ' ';
520
                        continue;
521 355 julius
 
522 406 julius
                case 'p':
523
                        if (field_width == -1) {
524
                                field_width = 2 * sizeof(void *);
525
                                flags |= ZEROPAD;
526
                        }
527
                        str =
528
                            number(str, (unsigned long)va_arg(args, void *), 16,
529
                                   field_width, precision, flags);
530
                        continue;
531 355 julius
 
532 406 julius
                case 'A':
533
                        flags |= UPPERCASE;
534 355 julius
 
535 406 julius
                case 'a':
536
                        if (qualifier == 'l')
537
                                str =
538
                                    eaddr(str, va_arg(args, unsigned char *),
539
                                          field_width, precision, flags);
540
                        else
541
                                str =
542
                                    iaddr(str, va_arg(args, unsigned char *),
543
                                          field_width, precision, flags);
544
                        continue;
545 355 julius
 
546 406 julius
                        // Integer number formats - set up the flags and "break"
547
                case 'o':
548
                        base = 8;
549
                        break;
550 355 julius
 
551 406 julius
                case 'X':
552
                        flags |= UPPERCASE;
553 355 julius
 
554 406 julius
                case 'x':
555
                        base = 16;
556
                        break;
557 355 julius
 
558 406 julius
                case 'd':
559
                case 'i':
560
                        flags |= SIGN;
561 355 julius
 
562 406 julius
                case 'u':
563
                        break;
564 355 julius
 
565
#ifdef HAS_FLOAT
566
 
567 406 julius
                case 'f':
568
                        str =
569
                            flt(str, va_arg(args, double), field_width,
570
                                precision, *fmt, flags | SIGN);
571
                        continue;
572 355 julius
 
573
#endif
574
 
575 406 julius
                default:
576
                        if (*fmt != '%')
577
                                *str++ = '%';
578
                        if (*fmt)
579
                                *str++ = *fmt;
580
                        else
581
                                --fmt;
582
                        continue;
583
                }
584 355 julius
 
585 406 julius
                if (qualifier == 'l')
586
                        num = va_arg(args, unsigned long);
587
                else if (flags & SIGN)
588
                        num = va_arg(args, int);
589
                else
590
                        num = va_arg(args, unsigned int);
591 355 julius
 
592 406 julius
                str = number(str, num, base, field_width, precision, flags);
593
        }
594 355 julius
 
595 406 julius
        *str = '\0';
596
        return str - buf;
597 355 julius
}
598
 
599 406 julius
void uart_send_char(char c)
600
{
601 355 julius
 
602 406 julius
        uart_putc(c);
603
 
604 355 julius
}
605
 
606
int ee_printf(const char *fmt, ...)
607
{
608 406 julius
        char buf[256], *p;
609
        va_list args;
610
        int n = 0;
611 355 julius
 
612 406 julius
        va_start(args, fmt);
613
        ee_vsprintf(buf, fmt, args);
614
        va_end(args);
615
        p = buf;
616
        while (*p) {
617
                uart_send_char(*p);
618
                n++;
619
                p++;
620
        }
621 355 julius
 
622 406 julius
        return n;
623 355 julius
}

powered by: WebSVN 2.1.0

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