Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 theseven 1
/***************************************************************************
2
 *             __________               __   ___.
3
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7
 *                     \/            \/     \/    \/            \/
8
 * $Id$
9
 *
10
 * Copyright (C) 2002 by Gary Czvitkovicz
11
 *
12
 * This program is free software; you can redistribute it and/or
13
 * modify it under the terms of the GNU General Public License
14
 * as published by the Free Software Foundation; either version 2
15
 * of the License, or (at your option) any later version.
16
 *
17
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18
 * KIND, either express or implied.
19
 *
20
 ****************************************************************************/
21
 
22
 
111 theseven 23
#include "global.h"
2 theseven 24
#include <limits.h>
128 theseven 25
#include "libc/include/string.h"
2 theseven 26
 
27
static const char hexdigit[] = "0123456789ABCDEF";
28
 
29
int format(
30
    /* call 'push()' for each output letter */
31
    int (*push)(void *userp, unsigned char data),
32
    void *userp,
33
    const char *fmt,
34
    va_list ap)
35
{
36
    char *str;
37
    char tmpbuf[12], pad;
38
    int ch, width, val, sign, precision;
39
    long lval, lsign;
40
    unsigned int uval;
41
    unsigned long ulval;
42
    bool ok = true;
43
 
44
    tmpbuf[sizeof tmpbuf - 1] = '\0';
45
 
46
    while ((ch = *fmt++) != '\0' && ok)
47
    {
48
    if (ch == '%')
49
    {
50
        ch = *fmt++;
51
        pad = ' ';
52
        if (ch == '0')
53
        pad = '0';
54
 
55
        width = 0;
56
        while (ch >= '0' && ch <= '9')
57
        {
58
        width = 10*width + ch - '0';
59
        ch = *fmt++;
60
        }
61
 
62
        precision = 0;
63
        if(ch == '.')
64
        {
65
            ch = *fmt++;
66
            while (ch >= '0' && ch <= '9')
67
            {
68
                precision = 10*precision + ch - '0';
69
                ch = *fmt++;
70
            }
71
        } else {
72
            precision = INT_MAX;
73
        }
74
 
75
        str = tmpbuf + sizeof tmpbuf - 1;
76
        switch (ch)
77
        {
78
        case 'c':
79
            *--str = va_arg (ap, int);
80
            break;
81
 
82
        case 's':
83
            str = va_arg (ap, char*);
84
            break;
85
 
86
        case 'd':
87
            val = sign = va_arg (ap, int);
88
            if (val < 0)
89
            val = -val;
90
            do
91
            {
92
            *--str = (val % 10) + '0';
93
            val /= 10;
94
            }
95
            while (val > 0);
96
            if (sign < 0)
97
            *--str = '-';
98
            break;
99
 
100
        case 'u':
101
            uval = va_arg(ap, unsigned int);
102
            do
103
            {
104
            *--str = (uval % 10) + '0';
105
            uval /= 10;
106
            }
107
            while (uval > 0);
108
            break;
109
 
110
        case 'x':
111
        case 'X':
112
            pad='0';
113
            uval = va_arg (ap, int);
114
            do
115
            {
116
            *--str = hexdigit[uval & 0xf];
117
            uval >>= 4;
118
            }
119
            while (uval);
120
            break;
121
 
122
        case 'l':
123
        case 'z': /* assume sizeof(size_t) == sizeof(long) */
124
            ch = *fmt++;
125
            switch(ch) {
126
                case 'x':
127
                case 'X':
128
                    pad='0';
129
                    ulval = va_arg (ap, long);
130
                    do
131
                    {
132
                        *--str = hexdigit[ulval & 0xf];
133
                        ulval >>= 4;
134
                    }
135
                    while (ulval);
136
                    break;
137
                case 'd':
138
                    lval = lsign = va_arg (ap, long);
139
                    if (lval < 0)
140
                        lval = -lval;
141
                    do
142
                    {
143
                        *--str = (lval % 10) + '0';
144
                        lval /= 10;
145
                    }
146
                    while (lval > 0);
147
                    if (lsign < 0)
148
                        *--str = '-';
149
                    break;
150
 
151
                case 'u':
152
                    ulval = va_arg(ap, unsigned long);
153
                    do
154
                    {
155
                        *--str = (ulval % 10) + '0';
156
                        ulval /= 10;
157
                    }
158
                    while (ulval > 0);
159
                    break;
160
 
161
                default:
162
                    *--str = 'l';
163
                    *--str = ch;
164
            }
165
 
166
            break;
167
 
168
        default:
169
            *--str = ch;
170
            break;
171
        }
172
 
173
        if (width > 0)
174
        {
175
        width -= strlen (str);
176
        while (width-- > 0 && ok)
177
            ok=push(userp, pad);
178
        }
179
        while (*str != '\0' && ok && precision--)
180
                ok=push(userp, *str++);
181
    }
182
    else
183
        ok=push(userp, ch);
184
    }
185
    return ok; /* true means good */
186
}
187
 
188
int vuprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap)
189
{
190
    return format(push, userp, fmt, ap);
191
}