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

Subversion Repositories xenie

[/] [xenie/] [trunk/] [examples/] [Eth_example/] [mb_fw/] [xenie_eth_test_womtd/] [src/] [uprintf.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 DFC
/*
2
 * Sprintf is taken from dip122 project.
3
 * I just adopted it that msp430-gcc can handle it
4
 * The code is about 1500 bytes (depends on -O options)
5
 *
6
 * (c) msp gcc team http://mspgcc.sourceforge.net
7
 */
8
 
9
/******************************************************************************
10
 This file is a patched version of printf called _printf_P
11
 It is made to work with avr-gcc for Atmel AVR MCUs.
12
 There are some differences from standard printf:
13
        1. There is no floating point support (with fp the code is about 8K!)
14
        2. Return type is void
15
        3. Format string must be in program memory (by using macro printf this is
16
           done automaticaly)
17
        4. %n is not implemented (just remove the comment around it if you need it)
18
        5. If LIGHTPRINTF is defined, the code is about 550 bytes smaller and the
19
           folowing specifiers are disabled :
20
                space # * . - + p s o O
21
        6. A function void uart_sendchar(char c) is used for output. The UART must
22
                be initialized before using printf.
23
 
24
 Alexander Popov
25
 sasho@vip.orbitel.bg
26
 
27
 small modifications to make it work with liblcd_dip122.a
28
 replaced uart_sendchar with (*write_char)(char)
29
 2001 Michael Schaenzler
30
*******************************************************************************/
31
 
32
/*
33
 * Actual printf innards.
34
 *
35
 * This code is large and complicated...
36
 */
37
 
38
#include <string.h>
39
#ifdef __STDC__
40
#include <stdarg.h>
41
#else
42
#include <varargs.h>
43
#endif
44
 
45
 
46
static char *Bufs;
47
 
48
static void (*uprintf_print_fn)(void *inst, const char *buf, int len);
49
static void *uprintf_print_fn_inst;
50
 
51
void uprintf_init(void (*print)(void *inst, const char *buf, int len), void *inst)
52
{
53
        uprintf_print_fn = print;
54
        uprintf_print_fn_inst = inst;
55
}
56
 
57
#define PRINTP PRINT
58
 
59
 
60
static void PRINT_f(const char * ptr, unsigned int len)
61
{
62
        if (uprintf_print_fn)
63
                uprintf_print_fn(uprintf_print_fn_inst, ptr, len);
64
        else
65
                while(1); /* Uprintf was not initialized */
66
}
67
 
68
static void PRINTS_f(const char * ptr, unsigned int len)
69
{
70
    for(;len;len--)
71
        *Bufs++ = *ptr++;
72
}
73
 
74
#define PAD_SP(x) __write_pad(PRINT, ' ',x);
75
#define PAD_0(x) __write_pad(PRINT,'0',x);
76
 
77
static void __write_pad(void PRINT(const char * ptr, unsigned int len), char c, signed char howmany)
78
{
79
    for(;howmany>0;howmany--)
80
        PRINT(&c, 1);
81
}
82
 
83
 
84
#define BUF             20
85
 
86
#define PRG_RDB(x)      *x
87
 
88
 
89
/*
90
 * Macros for converting digits to letters and vice versa
91
 */
92
#define to_digit(c)     ((c) - '0')
93
#define  is_digit(c)    ((c)<='9' && (c)>='0')
94
#define to_char(n)      ((n) + '0')
95
 
96
/*
97
 * Flags used during conversion.
98
 */
99
#define LONGINT         0x01            /* long integer */
100
#define LONGDBL         0x02            /* long double; unimplemented */
101
#define SHORTINT                0x04            /* short integer */
102
#define ALT                     0x08            /* alternate form */
103
#define LADJUST         0x10            /* left adjustment */
104
#define ZEROPAD         0x20            /* zero (as opposed to blank) pad */
105
#define HEXPREFIX       0x40            /* add 0x or 0X prefix */
106
 
107
int vuprintf (void PRINT(const char * ptr, unsigned int len), char const *fmt0, va_list ap);
108
 
109
void uprintf (char const *fmt0, ...)
110
{
111
        va_list ap;
112
        va_start(ap, fmt0);
113
        vuprintf(PRINT_f, fmt0, ap);
114
        va_end(ap);
115
}
116
 
117
int suprintf (char *buf, char const *fmt0, ...)
118
{
119
        int ret;
120
        va_list ap;
121
        va_start(ap, fmt0);
122
        ret = vuprintf(PRINTS_f, fmt0, ap);
123
        buf[ret] = '\0';
124
        va_end(ap);
125
 
126
        return ret;
127
}
128
 
129
int vuprintf (void PRINT(const char * ptr, unsigned int len), char const *fmt0, va_list ap)
130
{
131
    register const char *fmt; /* format string */
132
    register char ch;   /* character from fmt */
133
    register int n;             /* handy integer (short term usage) */
134
    register char *cp;  /* handy char pointer (short term usage) */
135
    const char *fmark;  /* for remembering a place in fmt */
136
    register unsigned char flags;       /* flags as above */
137
    signed char width;          /* width from format (%8d), or 0 */
138
    signed char prec;           /* precision from format (%.3d), or -1 */
139
    char sign;                          /* sign prefix (' ', '+', '-', or \0) */
140
    unsigned long _ulong=0;      /* integer arguments %[diouxX] */
141
#define OCT 8
142
#define DEC 10
143
#define HEX 16
144
    unsigned char base;         /* base for [diouxX] conversion */
145
    signed char dprec;          /* a copy of prec if [diouxX], 0 otherwise */
146
    signed char dpad;                   /* extra 0 padding needed for integers */
147
    signed char fieldsz;                /* field size expanded by sign, dpad etc */
148
    /* The initialization of 'size' is to suppress a warning that
149
       'size' might be used unitialized.  It seems gcc can't
150
       quite grok this spaghetti code ... */
151
    signed char size = 0;                /* size of converted field or string */
152
    char buf[BUF];              /* space for %c, %[diouxX], %[eEfgG] */
153
    char ox[2];                 /* space for 0x hex-prefix */
154
    int ret = 0; /* Number of bytes printed */
155
 
156
    fmt = fmt0;
157
 
158
    /*
159
     * Scan the format for conversions (`%' character).
160
     */
161
    for (;;)
162
    {
163
        for (fmark = fmt; (ch = PRG_RDB(fmt)) != '\0' && ch != '%'; fmt++)
164
            /* void */;
165
 
166
        if ((n = fmt - fmark) != 0)
167
        {
168
            PRINTP(fmark, n);
169
            ret += n;
170
        }
171
        if (ch == '\0')
172
            goto done;
173
        fmt++;          /* skip over '%' */
174
 
175
        flags = 0;
176
        dprec = 0;
177
        width = 0;
178
        prec = -1;
179
        sign = '\0';
180
 
181
rflag:
182
        ch = PRG_RDB(fmt++);
183
reswitch:
184
        if (ch=='u' || (ch|0x20)=='x')
185
        {
186
            if (flags&LONGINT)
187
            {
188
                _ulong=va_arg(ap, unsigned long);
189
            }
190
            else
191
            {
192
                register unsigned int _d;
193
                _d=va_arg(ap, unsigned int);
194
                _ulong = flags&SHORTINT ? (unsigned long)(unsigned short)_d : (unsigned long)_d;
195
            }
196
        }
197
 
198
        if(ch==' ')
199
        {
200
            /*
201
             * ``If the space and + flags both appear, the space
202
             * flag will be ignored.''
203
             *  -- ANSI X3J11
204
             */
205
            if (!sign)
206
                sign = ' ';
207
            goto rflag;
208
        }
209
        else if (ch=='#')
210
        {
211
            flags |= ALT;
212
            goto rflag;
213
        }
214
        else if (ch=='*'||ch=='-')
215
        {
216
            if (ch=='*')
217
            {
218
                /*
219
                 * ``A negative field width argument is taken as a
220
                 * - flag followed by a positive field width.''
221
                 *      -- ANSI X3J11
222
                 * They don't exclude field widths read from args.
223
                 */
224
                if ((width = va_arg(ap, int)) >= 0)
225
                    goto rflag;
226
                width = -width;
227
            }
228
            flags |= LADJUST;
229
            flags &= ~ZEROPAD; /* '-' disables '0' */
230
            goto rflag;
231
        }
232
        else if (ch=='+')
233
        {
234
            sign = '+';
235
            goto rflag;
236
        }
237
        else if (ch=='.')
238
        {
239
            if ((ch = PRG_RDB(fmt++)) == '*')
240
            {
241
                n = va_arg(ap, int);
242
                prec = n < 0 ? -1 : n;
243
                goto rflag;
244
            }
245
            n = 0;
246
            while (is_digit(ch))
247
            {
248
                n = n*10 + to_digit(ch);
249
                ch = PRG_RDB(fmt++);
250
            }
251
            prec = n < 0 ? -1 : n;
252
            goto reswitch;
253
        }
254
        else if (ch=='0')
255
        {
256
            /*
257
             * ``Note that 0 is taken as a flag, not as the
258
             * beginning of a field width.''
259
             *  -- ANSI X3J11
260
             */
261
            if (!(flags & LADJUST))
262
                flags |= ZEROPAD; /* '-' disables '0' */
263
            goto rflag;
264
        }
265
        else if (ch>='1' && ch<='9')
266
        {
267
            n = 0;
268
            do
269
            {
270
                n = 10 * n + to_digit(ch);
271
                ch = PRG_RDB(fmt++);
272
            }
273
            while (is_digit(ch));
274
            width = n;
275
            goto reswitch;
276
        }
277
        else if (ch=='h')
278
        {
279
            flags |= SHORTINT;
280
            goto rflag;
281
        }
282
        else if (ch=='l')
283
        {
284
            flags |= LONGINT;
285
            goto rflag;
286
        }
287
        else if (ch=='c')
288
        {
289
            *(cp = buf) = va_arg(ap, int);
290
            size = 1;
291
            sign = '\0';
292
        }
293
        else if (ch=='D'||ch=='d'||ch=='i')
294
        {
295
            if(ch=='D')
296
                flags |= LONGINT;
297
            if (flags&LONGINT)
298
            {
299
                _ulong=va_arg(ap, long);
300
            }
301
            else
302
            {
303
                register int _d;
304
                _d=va_arg(ap, int);
305
                _ulong = flags&SHORTINT ? (long)(short)_d : (long)_d;
306
            }
307
 
308
            if ((long)_ulong < 0)
309
            {
310
                _ulong = -_ulong;
311
                sign = '-';
312
            }
313
            base = DEC;
314
            goto number;
315
        }
316
        else if (ch=='O'||ch=='o')
317
        {
318
            if (ch=='O')
319
                flags |= LONGINT;
320
            base = OCT;
321
            goto nosign;
322
        }
323
        else if (ch=='p')
324
        {
325
            /*
326
             * ``The argument shall be a pointer to void.  The
327
             * value of the pointer is converted to a sequence
328
             * of printable characters, in an implementation-
329
             * defined manner.''
330
             *  -- ANSI X3J11
331
             */
332
            /* NOSTRICT */
333
            _ulong = (unsigned int)va_arg(ap, void *);
334
            base = HEX;
335
            flags |= HEXPREFIX;
336
            ch = 'x';
337
            goto nosign;
338
        }
339
        else if (ch=='s')
340
        {  /* print a string from RAM */
341
            if ((cp = va_arg(ap, char *)) == NULL)
342
            {
343
                cp=buf;
344
                cp[0] = '(';
345
                cp[1] = 'n';
346
                cp[2] = 'u';
347
                cp[4] = cp[3] = 'l';
348
                cp[5] = ')';
349
                cp[6] = '\0';
350
            }
351
            if (prec >= 0)
352
            {
353
                /*
354
                 * can't use strlen; can only look for the
355
                 * NUL in the first `prec' characters, and
356
                 * strlen() will go further.
357
                 */
358
                char *p = (char*)memchr(cp, 0, prec);
359
 
360
                if (p != NULL)
361
                {
362
                    size = p - cp;
363
                    if (size > prec)
364
                        size = prec;
365
                }
366
                else
367
                    size = prec;
368
            }
369
            else
370
                size = strlen(cp);
371
            sign = '\0';
372
        }
373
        else if(ch=='U'||ch=='u')
374
        {
375
            if (ch=='U')
376
                flags |= LONGINT;
377
            base = DEC;
378
            goto nosign;
379
        }
380
        else if (ch=='X'||ch=='x')
381
        {
382
            base = HEX;
383
            /* leading 0x/X only if non-zero */
384
            if ((flags & ALT) && _ulong != 0)
385
                flags |= HEXPREFIX;
386
 
387
            /* unsigned conversions */
388
nosign:
389
            sign = '\0';
390
            /*
391
             * ``... diouXx conversions ... if a precision is
392
             * specified, the 0 flag will be ignored.''
393
             *  -- ANSI X3J11
394
             */
395
number:
396
            if ((dprec = prec) >= 0)
397
                flags &= ~ZEROPAD;
398
 
399
            /*
400
             * ``The result of converting a zero value with an
401
             * explicit precision of zero is no characters.''
402
             *  -- ANSI X3J11
403
             */
404
            cp = buf + BUF;
405
            if (_ulong != 0 || prec != 0)
406
            {
407
                register unsigned char _d,notlastdigit;
408
                do
409
                {
410
                    notlastdigit=(_ulong>=base);
411
                    _d = _ulong % base;
412
 
413
                    if (_d<10)
414
                    {
415
                        _d+='0';
416
                    }
417
                    else
418
                    {
419
                        _d+='a'-10;
420
                        if (ch=='X') _d&=~0x20;
421
                    }
422
                    *--cp=_d;
423
                    _ulong /= base;
424
                }
425
                while (notlastdigit);
426
 
427
                /* handle octal leading 0 */
428
                if (base==OCT && (flags & ALT) && *cp != '0')
429
                    *--cp = '0';
430
            }
431
 
432
            size = buf + BUF - cp;
433
        }
434
        else
435
        {  /* default */
436
            /* "%?" prints ?, unless ? is NUL */
437
            if (ch == '\0')
438
                goto done;
439
            /* pretend it was %c with argument ch */
440
            cp = buf;
441
            *cp = ch;
442
            size = 1;
443
            sign = '\0';
444
        }
445
 
446
        /*
447
         * All reasonable formats wind up here.  At this point,
448
         * `cp' points to a string which (if not flags&LADJUST)
449
         * should be padded out to `width' places.  If
450
         * flags&ZEROPAD, it should first be prefixed by any
451
         * sign or other prefix; otherwise, it should be blank
452
         * padded before the prefix is emitted.  After any
453
         * left-hand padding and prefixing, emit zeroes
454
         * required by a decimal [diouxX] precision, then print
455
         * the string proper, then emit zeroes required by any
456
         * leftover floating precision; finally, if LADJUST,
457
         * pad with blanks.
458
         */
459
 
460
        /*
461
         * compute actual size, so we know how much to pad.
462
         */
463
        fieldsz = size;
464
 
465
        dpad = dprec - size;
466
        if (dpad < 0)
467
            dpad = 0;
468
 
469
        if (sign)
470
            fieldsz++;
471
        else if (flags & HEXPREFIX)
472
            fieldsz += 2;
473
        fieldsz += dpad;
474
 
475
        /* right-adjusting blank padding */
476
        if ((flags & (LADJUST|ZEROPAD)) == 0) {
477
            PAD_SP(width - fieldsz);
478
            ret += (width - fieldsz);
479
        }
480
        /* prefix */
481
        if (sign)
482
        {
483
            PRINT(&sign, 1);
484
            ret += 1;
485
        }
486
        else if (flags & HEXPREFIX)
487
        {
488
            ox[0] = '0';
489
            ox[1] = ch;
490
            PRINT(ox, 2);
491
            ret += 2;
492
        }
493
 
494
        /* right-adjusting zero padding */
495
        if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) {
496
            PAD_0(width - fieldsz);
497
            ret += (width - fieldsz);
498
        }
499
 
500
        /* leading zeroes from decimal precision */
501
        PAD_0(dpad);
502
        ret += dpad;
503
 
504
        /* the string or number proper */
505
        PRINT(cp, size);
506
        ret += size;
507
 
508
        /* left-adjusting padding (always blank) */
509
        if (flags & LADJUST) {
510
            PAD_SP(width - fieldsz);
511
            ret += (width - fieldsz);
512
        }
513
    }
514
done:
515
        ;
516
 
517
    return ret;
518
}
519
 
520
 

powered by: WebSVN 2.1.0

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