Subversion Repositories Kolibri OS

Rev

Rev 9862 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 9862 Rev 9863
1
/*
1
/*
2
        function for format read from any source
2
        function for format read from any source
3
 
3
 
4
Siemargl formats as http://www.cplusplus.com/reference/cstdio/scanf/, no wchar though
4
Siemargl formats as http://www.cplusplus.com/reference/cstdio/scanf/, no wchar though
5
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html  is used too
5
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html  is used too
6
 
6
 
7
todo:
7
todo:
8
[characters], [^characters]
8
[characters], [^characters]
9
-%n nothing scanned, filled only if good result
9
-%n nothing scanned, filled only if good result
10
-%d, i, u, o, x, p read similar - detect base by prefix 0 or 0x
10
-%d, i, u, o, x, p read similar - detect base by prefix 0 or 0x
11
-%a
11
-%a
12
-can overflow unsigned as signed
12
-can overflow unsigned as signed
13
-radix point always '.', no LOCALEs
13
-radix point always '.', no LOCALEs
14
*/
14
*/
15
 
15
 
16
 
16
 
17
#include 
17
#include 
18
#include 
18
#include 
19
#include 
19
#include 
20
#include 
20
#include 
21
 
21
 
22
typedef int (*virtual_getc)(void *sp, const void *obj);
22
typedef int (*virtual_getc)(void *sp, const void *obj);
23
typedef void (*virtual_ungetc)(void *sp, int c, const void *obj);
23
typedef void (*virtual_ungetc)(void *sp, int c, const void *obj);
24
 
24
 
25
enum flags_t
25
enum flags_t
26
{
26
{
27
    flag_unsigned   = 0x02,
27
        flag_unsigned   = 0x02,
28
    flag_register   = 0x04,
28
        flag_register   = 0x04,
29
    flag_plus       = 0x08,
29
        flag_plus       = 0x08,
30
    flag_left_just  = 0x10,
30
        flag_left_just  = 0x10,
31
    flag_lead_zeros = 0x20,
31
        flag_lead_zeros = 0x20,
32
    flag_space_plus = 0x40,
32
        flag_space_plus = 0x40,
33
    flag_hash_sign  = 0x80,
33
        flag_hash_sign  = 0x80,
34
    flag_point      = 0x100
34
        flag_point      = 0x100
35
};
35
};
36
 
36
 
37
int try_parse_real(long double *real, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc)
37
int     try_parse_real(long double *real, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc)
38
// returns 1 if OK, -1 == EOF, -2 parse broken
38
// returns 1 if OK, -1 == EOF, -2 parse broken
39
{
39
{
40
    int sign = 1, have_digits = 0;
40
    int sign = 1, have_digits = 0;
41
    long long div;
41
    long long div;
42
 
42
 
43
    if (ch == '+')
43
    if (ch == '+')
44
    {
44
    {
45
        ch = vgetc(save, src);
45
        ch = vgetc(save, src);
46
        if (ch == EOF) return EOF;
46
        if (ch == EOF) return EOF;
47
    } else
47
    } else
48
    if (ch == '-')
48
    if (ch == '-')
49
    {
49
    {
50
        sign = -1;
50
        sign = -1;
51
        ch = vgetc(save, src);
51
        ch = vgetc(save, src);
52
        if (ch == EOF) return EOF;
52
        if (ch == EOF) return EOF;
53
    };
53
    };
54
    *real = 0.0;
54
    *real = 0.0;
55
    for (;;) // mantissa before point
55
    for (;;) // mantissa before point
56
    {
56
    {
57
        // test ch is valid
57
        // test ch is valid
58
        if (isdigit(ch))
58
        if (isdigit(ch))
59
        {
59
        {
60
            *real = *real * 10 + ch - '0';
60
            *real = *real * 10 + ch - '0';
61
            have_digits++;
61
            have_digits++;
62
            ch = vgetc(save, src);
62
            ch = vgetc(save, src);
63
            if (ch == EOF || isspace(ch)) break; // ok, just finish num
63
            if (ch == EOF || isspace(ch)) break; // ok, just finish num
64
        } else
64
        } else
65
        if (ch == '.' || ch == 'E' || ch == 'e')
65
        if (ch == '.' || ch == 'E' || ch == 'e')
66
        {
66
        {
67
            break; // ok
67
            break; // ok
68
        }
68
        }
69
        else
69
        else
70
        {
70
        {
71
            vungetc(save, ch, src);
71
            vungetc(save, ch, src);
72
            break;
72
            break;
73
        }
73
        }
74
    }
74
    }
75
    if (ch != '.' && ch != 'E' && ch != 'e') // ok, just integer part
75
    if (ch != '.' && ch != 'E' && ch != 'e') // ok, just integer part
76
    {
76
    {
77
        *real *= sign;
77
        *real *= sign;
78
        if (have_digits)
78
        if (have_digits)
79
            return 1;
79
            return 1;
80
        else
80
        else
81
            return -2;
81
            return -2;
82
    }
82
    }
83
 
83
 
84
    if(ch == '.')
84
    if(ch == '.')
85
    {
85
    {
86
        ch = vgetc(save, src);
86
        ch = vgetc(save, src);
87
        div = 10; // use as divisor
87
        div = 10; // use as divisor
88
        for (;;) // mantissa after point
88
        for (;;) // mantissa after point
89
        {
89
        {
90
            // test ch is valid
90
            // test ch is valid
91
            if (isdigit(ch))
91
            if (isdigit(ch))
92
            {
92
            {
93
                *real += (double)(ch - '0') / div;
93
                *real += (double)(ch - '0') / div;
94
                div *= 10;
94
                div *= 10;
95
                have_digits++;
95
                have_digits++;
96
                ch = vgetc(save, src);
96
                ch = vgetc(save, src);
97
                if (ch == EOF || isspace(ch)) break; // ok, just finish num
97
                if (ch == EOF || isspace(ch)) break; // ok, just finish num
98
            } else
98
            } else
99
            if (ch == 'E' || ch == 'e')
99
            if (ch == 'E' || ch == 'e')
100
            {
100
            {
101
                break; // ok
101
                break; // ok
102
            }
102
            }
103
            else
103
            else
104
            {
104
            {
105
                vungetc(save, ch, src);
105
                vungetc(save, ch, src);
106
                break;
106
                break;
107
            }
107
            }
108
        }
108
        }
109
        if (ch != 'E' && ch != 'e')  // ok, real as XX.YY
109
        if (ch != 'E' && ch != 'e')  // ok, real as XX.YY
110
        {
110
        {
111
            *real *= sign;
111
            *real *= sign;
112
            if (have_digits)
112
            if (have_digits)
113
                return 1;
113
                return 1;
114
            else
114
            else
115
                return -2;
115
                return -2;
116
        }
116
        }
117
    }
117
    }
118
 
118
 
119
    ch = vgetc(save, src);
119
    ch = vgetc(save, src);
120
    *real *= sign;
120
    *real *= sign;
121
    // exponent
121
    // exponent
122
    sign = 1;
122
    sign = 1;
123
    if (ch == '+')
123
    if (ch == '+')
124
    {
124
    {
125
        ch = vgetc(save, src);
125
        ch = vgetc(save, src);
126
        if (ch == EOF) return EOF;
126
        if (ch == EOF) return EOF;
127
    } else
127
    } else
128
    if (ch == '-')
128
    if (ch == '-')
129
    {
129
    {
130
        sign = -1;
130
        sign = -1;
131
        ch = vgetc(save, src);
131
        ch = vgetc(save, src);
132
        if (ch == EOF) return EOF;
132
        if (ch == EOF) return EOF;
133
    };
133
    };
134
    div = 0;
134
    div = 0;
135
    for (;;)
135
    for (;;)
136
    {
136
    {
137
        // test ch is valid
137
        // test ch is valid
138
        if (isdigit(ch))
138
        if (isdigit(ch))
139
        {
139
        {
140
            div = div * 10 + ch - '0';
140
            div = div * 10 + ch - '0';
141
            ch = vgetc(save, src);
141
            ch = vgetc(save, src);
142
            if (ch == EOF || isspace(ch)) break; // ok, just finish num
142
            if (ch == EOF || isspace(ch)) break; // ok, just finish num
143
        }
143
        }
144
        else
144
        else
145
        {
145
        {
146
            vungetc(save, ch, src);
146
            vungetc(save, ch, src);
147
            break;
147
            break;
148
        }
148
        }
149
    }
149
    }
150
    div *= sign;
150
    div *= sign;
151
    *real *= pow(10, div);
151
    *real *= pow(10, div);
152
 
152
 
153
    return 1;
153
    return 1;
154
}
154
}
155
 
155
 
156
int try_parse_int(long long *digit, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc)
156
int     try_parse_int(long long *digit, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc)
157
{
157
{
158
    int sign = 1, base = 10, have_digits = 0;
158
    int sign = 1, base = 10, have_digits = 0;
159
 
159
 
160
    if (ch == '+')
160
    if (ch == '+')
161
    {
161
    {
162
        ch = vgetc(save, src);
162
        ch = vgetc(save, src);
163
        if (ch == EOF) return EOF;
163
        if (ch == EOF) return EOF;
164
    } else
164
    } else
165
    if (ch == '-')
165
    if (ch == '-')
166
    {
166
    {
167
        sign = -1;
167
        sign = -1;
168
        ch = vgetc(save, src);
168
        ch = vgetc(save, src);
169
        if (ch == EOF) return EOF;
169
        if (ch == EOF) return EOF;
170
    };
170
    };
171
 
171
 
172
    if (ch == '0')  // octal or hex, read next
172
    if (ch == '0')  // octal or hex, read next
173
    {
173
    {
174
        ch = vgetc(save, src);
174
        ch = vgetc(save, src);
175
        if (ch == 'o')
175
        if (ch == 'c' || ch == 'C')
176
            base = 8;
176
            base = 8;
177
        else if (ch == 'x' || ch == 'X')
177
        else if (ch == 'x' || ch == 'X')
178
            base = 16;
178
            base = 16;
179
        if (base == 10)
179
        if (base == 10)
180
            have_digits++;
180
            have_digits++;
181
        else
181
        else
182
        {
182
        {
183
            char tch = vgetc(save, src);
183
            char tch = vgetc(save, src);
184
            if ((base == 8 && isdigit(tch) && tch < '8') ||
184
            if ((base == 8 && isdigit(tch) && tch < '8') ||
185
                (base == 16 && isxdigit(tch)))
185
                (base == 16 && isxdigit(tch)))
186
                ch = tch;
186
                ch = tch;
187
            else
187
            else
188
            {
188
            {
189
                have_digits++;
189
                have_digits++;
190
                //base = 10; // not required: zero is zero with any (base > 1)
190
                //base = 10; // not required: zero is zero with any (base > 1)
191
                vungetc(save, tch, src);
191
                vungetc(save, tch, src);
192
            }
192
            }
193
        }
193
        }
194
    }
194
    }
195
    *digit = 0;
195
    *digit = 0;
196
    for (;;)
196
    for (;;)
197
    {
197
    {
198
        // test ch is valid
198
        // test ch is valid
199
        if ((isdigit(ch) && base == 10) ||
199
        if ((isdigit(ch) && base == 10) ||
200
            (isdigit(ch) && base == 8 && ch < '8') ||
200
            (isdigit(ch) && base == 8 && ch < '8') ||
201
            (isxdigit(ch) && base == 16))
201
            (isxdigit(ch) && base == 16))
202
        {
202
        {
203
            if (base == 16)
203
            if (base == 16)
204
            {
204
            {
205
                if (ch <= '9') ch -= '0';
205
                if (ch <= '9') ch -= '0';
206
                else
206
                else
207
                if (ch <= 'F') ch = 10 + ch - 'A';
207
                if (ch <= 'F') ch = 10 + ch - 'A';
208
                else
208
                else
209
                    ch = 10 + ch - 'a';
209
                    ch = 10 + ch - 'a';
210
            }
210
            }
211
            else
211
            else
212
                ch -= '0';
212
                ch -= '0';
213
            *digit = *digit * base + ch;
213
            *digit = *digit * base + ch;
214
            have_digits++;
214
            have_digits++;
215
            ch = vgetc(save, src);
215
            ch = vgetc(save, src);
216
            if (ch == EOF || isspace(ch)) break; // ok, just finish num
216
            if (ch == EOF || isspace(ch)) break; // ok, just finish num
217
        }
217
        }
218
        else if (ch == EOF || isspace(ch))
218
        else if (ch == EOF || isspace(ch))
219
            break;
219
            break;
220
        else
220
        else
221
        {
221
        {
222
            vungetc(save, ch, src);
222
            vungetc(save, ch, src);
223
            break;
223
            break;
224
        }
224
        }
225
    }
225
    }
226
    *digit *= sign;
226
    *digit *= sign;
227
    if (have_digits)
227
    if (have_digits)
228
        return 1;
228
        return 1;
229
    else
229
    else
230
        return -2;
230
        return -2;
231
}
231
}
232
 
232
 
233
 
233
 
234
 
234
 
235
int format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc)
235
int format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc)
236
{
236
{
237
    int                     i;
237
    int                     i;
238
    int                     length;
238
    int                     length;
239
    int                     fmt1, fmt2;  // width, precision
239
    int                     fmt1, fmt2;  // width, precision
240
    size_t                  pos, posc;
240
    size_t                  pos, posc;
241
    const char            *fmtc;  // first point to %, fmtc points to specifier
241
    const char            *fmtc;  // first point to %, fmtc points to specifier
242
    int                    ch;
242
    int                    ch;
243
    int                     format_flag;
243
    int                     format_flag;
244
    int                     flag_long;        // 2 = long double or long long int or wchar
244
    int                     flag_long;        // 2 = long double or long long int or wchar
245
    int                    *point_to_n = NULL, nread = 0;
245
    int                    *point_to_n = NULL, nread = 0;
246
    int                     flags;  // parsed flags
246
    int                     flags;  // parsed flags
247
    int                     save = 0;
247
    int                     save = 0;
248
    char                *arg_str;
248
    char                *arg_str;
249
    int	        *arg_int;
249
    int	        *arg_int;
250
    long        *arg_long;
250
    long        *arg_long;
251
    long long	*arg_longlong;
251
    long long	*arg_longlong;
252
    float       *arg_float;
252
    float       *arg_float;
253
    double      *arg_double;
253
    double      *arg_double;
254
    long double *arg_longdouble;
254
    long double *arg_longdouble;
255
    long long  digit;
255
    long long  digit;
256
    long double real;
256
    long double real;
257
    int skip_next; // skip arguments with * char format
257
    int skip_next; // skip arguments with * char format
258
 
258
 
259
    pos = 0;
259
    pos = 0;
260
    while(*fmt)
260
    while(*fmt)
261
    {
261
    {
262
        while (*fmt && isspace(*fmt)) fmt++; // skip spaces in format str
262
        while (*fmt && isspace(*fmt)) fmt++; // skip spaces in format str
263
 
263
 
264
        if (*fmt != '%')  // usual char
264
        if (*fmt != '%')  // usual char
265
        {
265
        {
266
            ch = vgetc(&save, src);
266
            ch = vgetc(&save, src);
267
            if (ch != *fmt++) // char not match format
267
            if (ch != *fmt++) // char not match format
268
            {
268
            {
269
                vungetc(&save, ch, src);
269
                vungetc(&save, ch, src);
270
                break;
270
                break;
271
            }
271
            }
272
            pos++;
272
            pos++;
273
            continue;
273
            continue;
274
        }
274
        }
275
 
275
 
276
        if (*(fmt + 1) == '%') // %%
276
        if (*(fmt + 1) == '%') // %%
277
        {
277
        {
278
            ch = vgetc(&save, src);
278
            ch = vgetc(&save, src);
279
            if (ch != '%') // char not match format
279
            if (ch != '%') // char not match format
280
            {
280
            {
281
                vungetc(&save, ch, src);
281
                vungetc(&save, ch, src);
282
                break;
282
                break;
283
            }
283
            }
284
            pos++;
284
            pos++;
285
            fmt += 2;
285
            fmt += 2;
286
            continue;
286
            continue;
287
        }
287
        }
288
        //checking to containg format in the string
288
        //checking to containg format in the string
289
        fmtc = fmt;
289
        fmtc = fmt;
290
        posc = pos;
290
        posc = pos;
291
 
291
 
292
        skip_next = 0;
292
        skip_next = 0;
293
        flags = 0;
293
        flags = 0;
294
        format_flag = 0;
294
        format_flag = 0;
295
        flag_long = 0;  // 2 = long double or long long int or wchar
295
        flag_long = 0;  // 2 = long double or long long int or wchar
296
 
296
 
297
        while(*fmtc != '\0' && !format_flag)    // searching end of format
297
        while(*fmtc != '\0' && !format_flag)    // searching end of format
298
        {
298
        {
299
                fmtc++; posc++;
299
                fmtc++; posc++;
300
                switch( *fmtc )
300
                switch( *fmtc )
301
                {
301
                {
302
                case 'a':
302
                case 'a':
303
                    format_flag = 1;
303
                    format_flag = 1;
304
                    flags |= flag_unsigned;
304
                    flags |= flag_unsigned;
305
                    break;
305
                    break;
306
                case 'c':   case 'd':   case 'i':   case 'e':   case 'f':   case 'g':   case 's':   case 'n':
306
                case 'c':   case 'd':   case 'i':   case 'e':   case 'f':   case 'g':   case 's':   case 'n':
307
                    format_flag = 1;
307
                    format_flag = 1;
308
                    break;
308
                    break;
309
                case 'l':
309
                case 'l':
310
                    flag_long  = flag_long ? 2 : 1;  // ll.eq.L
310
                    flag_long  = flag_long ? 2 : 1;  // ll.eq.L
311
                    break;
311
                    break;
312
                case 'L':
312
                case 'L':
313
                    flag_long = 2;
313
                    flag_long = 2;
314
                    break;
314
                    break;
315
                case 'o':   case 'u':   case 'x':   case 'p':
315
                case 'o':   case 'u':   case 'x':   case 'p':
316
                    format_flag = 1;
316
                    format_flag = 1;
317
                    flags |= flag_unsigned;
317
                    flags |= flag_unsigned;
318
                    break;
318
                    break;
319
                case '*':
319
                case '*':
320
                    skip_next = 1;
320
                    skip_next = 1;
321
                    break;
321
                    break;
322
                case '.':  // just skip
322
                case '.':  // just skip
323
                    break;
323
                    break;
324
                default:
324
                default:
325
                    if(isdigit(*fmtc))  break;
325
                    if(isdigit(*fmtc))  break;
326
                    goto exit_me;  // non format char found - user error
326
                    goto exit_me;  // non format char found - user error
327
                }
327
                }
328
        }
328
        }
329
 
329
 
330
        if (format_flag == 0)
330
        if (format_flag == 0)
331
        {
331
        {
332
            goto exit_me;  // format char not found - user error
332
            goto exit_me;  // format char not found - user error
333
        }
333
        }
334
 
334
 
335
        fmt1 = 0;
335
        fmt1 = 0;
336
        fmt2 = 0;
336
        fmt2 = 0;
337
        if (posc - pos > 1)  // try to read width, precision
337
        if (posc - pos > 1)  // try to read width, precision
338
        {
338
        {
339
            fmt++;
339
            fmt++;
340
            for(i = pos + 1; i < posc; i++)
340
            for(i = pos + 1; i < posc; i++)
341
            {
341
            {
342
                switch(*fmt)
342
                switch(*fmt)
343
                {
343
                {
344
                case '0':
344
                case '0':
345
                    if(fmt1 == 0 && (flags & flag_point) == 0)    flags |= flag_lead_zeros;
345
                    if(fmt1 == 0 && (flags & flag_point) == 0)    flags |= flag_lead_zeros;
346
                case '1':   case '2':   case '3':   case '4':
346
                case '1':   case '2':   case '3':   case '4':
347
                case '5':   case '6':   case '7':   case '8':   case '9':
347
                case '5':   case '6':   case '7':   case '8':   case '9':
348
                    if ((flags & flag_point) == 0)
348
                    if ((flags & flag_point) == 0)
349
                        fmt1 = fmt1 * 10 + (*fmt -'0');
349
                        fmt1 = fmt1 * 10 + (*fmt -'0');
350
                    else
350
                    else
351
                        fmt2 = fmt2 * 10 + (*fmt -'0');
351
                        fmt2 = fmt2 * 10 + (*fmt -'0');
352
                    break;
352
                    break;
353
                case '*': // ignoring
353
                case '*': // ignoring
354
                    break;
354
                    break;
355
                case '.':
355
                case '.':
356
                    flags |= flag_point;
356
                    flags |= flag_point;
357
                    break;
357
                    break;
358
                case 'l':   case 'L':      // valid chars - skip
358
                case 'l':   case 'L':      // valid chars - skip
359
                    break;
359
                    break;
360
                default: // must be error
360
                default: // must be error
361
                    goto exit_me;  // format char not found - user error
361
                    goto exit_me;  // format char not found - user error
362
                }
362
                }
363
                fmt++;
363
                fmt++;
364
            }
364
            }
365
        }
365
        }
366
 
366
 
367
        // do real work - format arguments values
367
        // do real work - format arguments values
368
        // skip input spaces
368
        // skip input spaces
369
        do {
369
        do {
370
            ch = vgetc(&save, src);
370
            ch = vgetc(&save, src);
371
            if (ch == EOF) goto exit_me;
371
            if (ch == EOF) goto exit_me;
372
        } while (isspace(ch));
372
        } while (isspace(ch));
373
 
373
 
374
        switch(*fmtc)
374
        switch(*fmtc)
375
        {
375
        {
376
        case 'n':
376
        case 'n':
377
            point_to_n = va_arg(argp, int*);
377
            point_to_n = va_arg(argp, int*);
378
            vungetc(&save, ch, src);
378
            vungetc(&save, ch, src);
379
            break;
379
            break;
380
        case 'c':  // read width chars, ever spaces
380
        case 'c':  // read width chars, ever spaces
381
            if (!skip_next) arg_str = va_arg(argp, char*);
381
            if (!skip_next) arg_str = va_arg(argp, char*);
382
            if (fmt1 == 0) length = 1;
382
            if (fmt1 == 0) length = 1;
383
            else length = fmt1;
383
            else length = fmt1;
384
            for (i = 0; i < length;)
384
            for (i = 0; i < length;)
385
            {
385
            {
386
                if (!skip_next) *arg_str++ = ch;
386
                if (!skip_next) *arg_str++ = ch;
387
                i++;
387
                i++;
388
                ch = vgetc(&save, src);
388
                ch = vgetc(&save, src);
389
                if (ch == EOF) break;
389
                if (ch == EOF) break;
390
            }
390
            }
391
            if (i < length) goto exit_me; // not enough chars
391
            if (i < length) goto exit_me; // not enough chars
392
            break;
392
            break;
393
        case 's':
393
        case 's':
394
            if (!skip_next) arg_str = va_arg(argp, char*);
394
            if (!skip_next) arg_str = va_arg(argp, char*);
395
            if (fmt1 == 0) length = 4095;   // max string scan 4096
395
            if (fmt1 == 0) length = 4095;   // max string scan 4096
396
            else length = fmt1;
396
            else length = fmt1;
397
            for (i = 0; i < length; i++)
397
            for (i = 0; i < length; i++)
398
            {
398
            {
399
                if (!skip_next) *arg_str++ = ch;
399
                if (!skip_next) *arg_str++ = ch;
400
 
400
 
401
                ch = vgetc(&save, src);
401
                ch = vgetc(&save, src);
402
                if (ch == EOF || isspace(ch)) break; // ok, just finish string
402
                if (ch == EOF || isspace(ch)) break; // ok, just finish string
403
            }
403
            }
404
            if (!skip_next) *arg_str++ = '\0';
404
            if (!skip_next) *arg_str++ = '\0';
405
            break;
405
            break;
406
        case 'd':   case 'i':   case 'u':
406
        case 'd':   case 'i':   case 'u':
407
        case 'o':   case 'p':   case 'x':
407
        case 'o':   case 'p':   case 'x':
408
            i = try_parse_int(&digit, ch, src, &save, vgetc, vungetc);
408
            i = try_parse_int(&digit, ch, src, &save, vgetc, vungetc);
409
            if (i < 0) goto exit_me;
409
            if (i < 0) goto exit_me;
410
 
410
 
411
            if (!skip_next)
411
            if (!skip_next)
412
            if (flag_long == 0) { arg_int = va_arg(argp, int*); *arg_int = (int)digit; } else
412
            if (flag_long == 0) { arg_int = va_arg(argp, int*); *arg_int = (int)digit; } else
413
            if (flag_long == 1) { arg_long = va_arg(argp, long*); *arg_long = (long)digit; } else
413
            if (flag_long == 1) { arg_long = va_arg(argp, long*); *arg_long = (long)digit; } else
414
            if (flag_long == 2) { arg_longlong = va_arg(argp, long long*); *arg_longlong = digit; }
414
            if (flag_long == 2) { arg_longlong = va_arg(argp, long long*); *arg_longlong = digit; }
415
            break;
415
            break;
416
        case 'a':   case 'A':   case 'f':   case 'F':
416
        case 'a':   case 'A':   case 'f':   case 'F':
417
        case 'e':   case 'E':
417
        case 'e':   case 'E':
418
        case 'g':   case 'G':
418
        case 'g':   case 'G':
419
            i = try_parse_real(&real, ch, src, &save, vgetc, vungetc);
419
            i = try_parse_real(&real, ch, src, &save, vgetc, vungetc);
420
            if (i < 0) goto exit_me;
420
            if (i < 0) goto exit_me;
421
 
421
 
422
            if (!skip_next)
422
            if (!skip_next)
423
            if (flag_long == 0) { arg_float = va_arg(argp, float*); *arg_float = (float)real; } else
423
            if (flag_long == 0) { arg_float = va_arg(argp, float*); *arg_float = (float)real; } else
424
            if (flag_long == 1) { arg_double = va_arg(argp, double*); *arg_double = (double)real; } else
424
            if (flag_long == 1) { arg_double = va_arg(argp, double*); *arg_double = (double)real; } else
425
            if (flag_long == 2) { arg_longdouble = va_arg(argp, long double*); *arg_longdouble = real; }
425
            if (flag_long == 2) { arg_longdouble = va_arg(argp, long double*); *arg_longdouble = real; }
426
            break;
426
            break;
427
        }
427
        }
428
 
428
 
429
        fmt = fmtc + 1;
429
        fmt = fmtc + 1;
430
        if (!skip_next) nread++;
430
        if (!skip_next) nread++;
431
    }
431
    }
432
exit_me:
432
exit_me:
433
    if (point_to_n) *point_to_n = nread;
433
    if (point_to_n) *point_to_n = nread;
434
    return  nread;
434
    return  nread;
435
}
435
}