Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
71 theseven 1
#include "global.h"
2
#include <stdarg.h>
3
#include <string.h>
4
#include <stdbool.h>
5
 
6
int isspace(int c)
7
{
8
    return (c == ' ') || (c == '\t') || (c == '\n');
9
}
10
 
11
int isdigit(int c)
12
{
13
    return (c >= '0') && (c <= '9');
14
}
15
 
16
int isxdigit(int c)
17
{
18
    return ((c >= '0') && (c <= '9'))
19
        || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F'));
20
}
21
 
22
static int parse_dec(int (*peek)(void *userp),
23
                     void (*pop)(void *userp),
24
                     void *userp,
25
                     long *vp)
26
{
27
    long v = 0;
28
    int n = 0;
29
    int minus = 0;
30
    char ch;
31
 
32
    if ((*peek)(userp) == '-')
33
    {
34
        (*pop)(userp);
35
        n++;
36
        minus = 1;
37
    }
38
 
39
    ch = (*peek)(userp);
40
    if (!isdigit(ch))
41
        return -1;
42
 
43
    do
44
    {
45
        v = v * 10 + ch - '0';
46
        (*pop)(userp);
47
        n++;
48
        ch = (*peek)(userp);
49
    } while (isdigit(ch));
50
 
51
    *vp = minus ? -v : v;
52
    return n;
53
}
54
 
55
static int parse_chars(int (*peek)(void *userp),
56
                       void (*pop)(void *userp),
57
                       void *userp,
58
                       char *vp,
59
                       bool fake)
60
{
61
    int n = 0;
62
 
63
    char *pt=vp;
64
 
65
    while (!isspace((*peek)(userp)))
66
    {
67
        if(fake==false)
68
            *(pt++) = (*peek)(userp);
69
 
70
        n++;
71
        (*pop)(userp);
72
    } 
73
 
74
    if(fake==false)
75
        (*pt)='\0';
76
 
77
    return n;
78
}
79
 
80
static int parse_hex(int (*peek)(void *userp),
81
                     void (*pop)(void *userp),
82
                     void *userp,
83
                     unsigned long *vp)
84
{
85
    unsigned long v = 0;
86
    int n = 0;
87
    char ch;
88
 
89
    ch = (*peek)(userp);
90
    if (!isxdigit(ch))
91
        return -1;
92
 
93
    do
94
    {
95
        if (ch >= 'a')
96
            ch = ch - 'a' + 10;
97
        else if (ch >= 'A')
98
            ch = ch - 'A' + 10;
99
        else
100
            ch = ch - '0';
101
        v = v * 16 + ch;
102
        (*pop)(userp);
103
        n++;
104
        ch = (*peek)(userp);
105
    } while (isxdigit(ch));
106
 
107
    *vp = v;
108
    return n;
109
}
110
 
111
static int skip_spaces(int (*peek)(void *userp),
112
                       void (*pop)(void *userp),
113
                       void *userp)
114
{
115
    int n = 0;
116
    while (isspace((*peek)(userp))) {
117
        n++;
118
        (*pop)(userp);
119
    }
120
    return n;
121
}
122
 
123
static int scan(int (*peek)(void *userp),
124
                void (*pop)(void *userp),
125
                void *userp,
126
                const char *fmt,
127
                va_list ap)
128
{
129
    char ch;
130
    int n = 0;
131
    int n_chars = 0;
132
    int r;
133
    long lval;
134
    bool skip=false;
135
    unsigned long ulval;
136
 
137
    while ((ch = *fmt++) != '\0')
138
    {
139
        bool literal = false;
140
 
141
        if (ch == '%')
142
        {
143
            ch = *fmt++;
144
 
145
            if(ch== '*')  /* We should process this, but not store it in an arguement */
146
            {
147
                ch=*fmt++;
148
                skip=true;
149
            }
150
            else
151
            {
152
                skip=false;
153
            }
154
 
155
            switch (ch)
156
            {
157
                case 'x':
158
                    n_chars += skip_spaces(peek, pop, userp);
159
                    if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
160
                    {
161
                        if(skip==false)
162
                        {
163
                            *(va_arg(ap, unsigned int *)) = ulval;
164
                            n++;
165
                        }
166
                        n_chars += r;
167
                    }
168
                    else
169
                        return n;
170
                    break;
171
                case 'd':
172
                    n_chars += skip_spaces(peek, pop, userp);
173
                    if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
174
                    {
175
                        if(skip==false)
176
                        {
177
                            *(va_arg(ap, int *)) = lval;
178
                            n++;
179
                        }
180
                        n_chars += r;
181
                    }
182
                    else
183
                        return n;
184
                    break;
185
                case 'n':
186
                    if(skip==false)
187
                    {
188
                        *(va_arg(ap, int *)) = n_chars;
189
                        n++;
190
                    }
191
                    break;
192
                case 'l':
193
                    n_chars += skip_spaces(peek, pop, userp);
194
                    ch = *fmt++;
195
                    switch (ch)
196
                    {
197
                        case 'x':
198
                            if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
199
                            {
200
                                if(skip==false)
201
                                {
202
                                    *(va_arg(ap, unsigned long *)) = ulval;
203
                                    n++;
204
                                }
205
                                n_chars += r;
206
                            }
207
                            else
208
                                return n;
209
                            break;
210
                        case 'd':
211
                            if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
212
                            {
213
                                if(skip==false)
214
                                {
215
                                    *(va_arg(ap, long *)) = lval;
216
                                    n++;
217
                                }    
218
                                n_chars += r;
219
                            }
220
                            else
221
                                return n;
222
                            break;
223
                        case '\0':
224
                            return n;
225
                        default:
226
                            literal = true;
227
                            break;
228
                    }
229
                    break;
230
                case 's':
231
                    n_chars += skip_spaces(peek, pop, userp);
232
                    n_chars += parse_chars(peek,pop, userp,skip?0:va_arg(ap, char *), skip );
233
                    if(skip==false)
234
                    {
235
                        n++;
236
                    }
237
                    break;
238
                case '\0':
239
                    return n;
240
                default:
241
                    literal = true;
242
                    break;
243
            }
244
        } else
245
            literal = true;
246
 
247
        if (literal)
248
        {
249
            n_chars += skip_spaces(peek, pop, userp);
250
            if ((*peek)(userp) != ch)
251
                continue;
252
            else
253
            {
254
                (*pop)(userp);
255
                n_chars++;
256
            }
257
        }
258
    }
259
    return n;
260
}
261
 
262
static int sspeek(void *userp)
263
{
264
    return **((char **)userp);
265
}
266
 
267
static void sspop(void *userp)
268
{
269
    (*((char **)userp))++;
270
}
271
 
272
int sscanf(const char *s, const char *fmt, ...)
273
{
274
    int r;
275
    va_list ap;
276
    const char *p;
277
 
278
    p = s;
279
    va_start(ap, fmt);
280
    r = scan(sspeek, sspop, &p, fmt, ap);
281
    va_end(ap);
282
    return r;
283
}