Subversion Repositories freemyipod

Rev

Go to most recent revision | 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
 
23
#include <stdarg.h>
24
#include <stdbool.h>
25
#include <limits.h>
26
#include <string.h>
27
 
28
static const char hexdigit[] = "0123456789ABCDEF";
29
 
30
int format(
31
    /* call 'push()' for each output letter */
32
    int (*push)(void *userp, unsigned char data),
33
    void *userp,
34
    const char *fmt,
35
    va_list ap)
36
{
37
    char *str;
38
    char tmpbuf[12], pad;
39
    int ch, width, val, sign, precision;
40
    long lval, lsign;
41
    unsigned int uval;
42
    unsigned long ulval;
43
    bool ok = true;
44
 
45
    tmpbuf[sizeof tmpbuf - 1] = '\0';
46
 
47
    while ((ch = *fmt++) != '\0' && ok)
48
    {
49
    if (ch == '%')
50
    {
51
        ch = *fmt++;
52
        pad = ' ';
53
        if (ch == '0')
54
        pad = '0';
55
 
56
        width = 0;
57
        while (ch >= '0' && ch <= '9')
58
        {
59
        width = 10*width + ch - '0';
60
        ch = *fmt++;
61
        }
62
 
63
        precision = 0;
64
        if(ch == '.')
65
        {
66
            ch = *fmt++;
67
            while (ch >= '0' && ch <= '9')
68
            {
69
                precision = 10*precision + ch - '0';
70
                ch = *fmt++;
71
            }
72
        } else {
73
            precision = INT_MAX;
74
        }
75
 
76
        str = tmpbuf + sizeof tmpbuf - 1;
77
        switch (ch)
78
        {
79
        case 'c':
80
            *--str = va_arg (ap, int);
81
            break;
82
 
83
        case 's':
84
            str = va_arg (ap, char*);
85
            break;
86
 
87
        case 'd':
88
            val = sign = va_arg (ap, int);
89
            if (val < 0)
90
            val = -val;
91
            do
92
            {
93
            *--str = (val % 10) + '0';
94
            val /= 10;
95
            }
96
            while (val > 0);
97
            if (sign < 0)
98
            *--str = '-';
99
            break;
100
 
101
        case 'u':
102
            uval = va_arg(ap, unsigned int);
103
            do
104
            {
105
            *--str = (uval % 10) + '0';
106
            uval /= 10;
107
            }
108
            while (uval > 0);
109
            break;
110
 
111
        case 'x':
112
        case 'X':
113
            pad='0';
114
            uval = va_arg (ap, int);
115
            do
116
            {
117
            *--str = hexdigit[uval & 0xf];
118
            uval >>= 4;
119
            }
120
            while (uval);
121
            break;
122
 
123
        case 'l':
124
        case 'z': /* assume sizeof(size_t) == sizeof(long) */
125
            ch = *fmt++;
126
            switch(ch) {
127
                case 'x':
128
                case 'X':
129
                    pad='0';
130
                    ulval = va_arg (ap, long);
131
                    do
132
                    {
133
                        *--str = hexdigit[ulval & 0xf];
134
                        ulval >>= 4;
135
                    }
136
                    while (ulval);
137
                    break;
138
                case 'd':
139
                    lval = lsign = va_arg (ap, long);
140
                    if (lval < 0)
141
                        lval = -lval;
142
                    do
143
                    {
144
                        *--str = (lval % 10) + '0';
145
                        lval /= 10;
146
                    }
147
                    while (lval > 0);
148
                    if (lsign < 0)
149
                        *--str = '-';
150
                    break;
151
 
152
                case 'u':
153
                    ulval = va_arg(ap, unsigned long);
154
                    do
155
                    {
156
                        *--str = (ulval % 10) + '0';
157
                        ulval /= 10;
158
                    }
159
                    while (ulval > 0);
160
                    break;
161
 
162
                default:
163
                    *--str = 'l';
164
                    *--str = ch;
165
            }
166
 
167
            break;
168
 
169
        default:
170
            *--str = ch;
171
            break;
172
        }
173
 
174
        if (width > 0)
175
        {
176
        width -= strlen (str);
177
        while (width-- > 0 && ok)
178
            ok=push(userp, pad);
179
        }
180
        while (*str != '\0' && ok && precision--)
181
                ok=push(userp, *str++);
182
    }
183
    else
184
        ok=push(userp, ch);
185
    }
186
    return ok; /* true means good */
187
}
188
 
189
int vuprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap)
190
{
191
    return format(push, userp, fmt, ap);
192
}