~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to tools/sfio/sfvscanf.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include        "sfhdr.h"
 
2
 
 
3
/*      The main engine for reading formatted data
 
4
**
 
5
**      Written by Kiem-Phong Vo.
 
6
*/
 
7
 
 
8
#define MAXWIDTH        (int)(((uint)~0)>>1)    /* max amount to scan   */
 
9
 
 
10
#if __STD_C
 
11
static char* setclass(reg char* form, reg char* accept)
 
12
#else
 
13
static char* setclass(form,accept)
 
14
reg char*       form;   /* format string                        */
 
15
reg char*       accept; /* accepted characters are set to 1     */
 
16
#endif
 
17
{
 
18
        reg int         fmt, c, yes;
 
19
 
 
20
        if((fmt = *form++) == '^')
 
21
        {       /* we want the complement of this set */
 
22
                yes = 0;
 
23
                fmt = *form++;
 
24
        }
 
25
        else    yes = 1;
 
26
 
 
27
        for(c = 0; c <= SF_MAXCHAR; ++c)
 
28
                accept[c] = !yes;
 
29
 
 
30
        if(fmt == ']' || fmt == '-')
 
31
        {       /* special first char */
 
32
                accept[fmt] = yes;
 
33
                fmt = *form++;
 
34
        }
 
35
 
 
36
        for(; fmt != ']'; fmt = *form++)
 
37
        {       /* done */
 
38
                if(!fmt)
 
39
                        return (form-1);
 
40
 
 
41
                /* interval */
 
42
                if(fmt != '-' || form[0] == ']' || form[-2] > form[0])
 
43
                        accept[fmt] = yes;
 
44
                else for(c = form[-2]+1; c < form[0]; ++c)
 
45
                        accept[c] = yes;
 
46
        }
 
47
 
 
48
        return form;
 
49
}
 
50
 
 
51
#if __STD_C
 
52
static void _sfbuf(Sfio_t* f, int* rs)
 
53
#else
 
54
static void _sfbuf(f, rs)
 
55
Sfio_t* f;
 
56
int*    rs;
 
57
#endif
 
58
{
 
59
        if(f->next >= f->endb)
 
60
        {       if(*rs > 0)     /* try peeking for a share stream if possible */
 
61
                {       f->mode |= SF_RV;
 
62
                        if(SFFILBUF(f,-1) > 0)
 
63
                        {       f->mode |= SF_PEEK;
 
64
                                return;
 
65
                        }
 
66
                        *rs = -1;       /* can't peek, back to normal reads */
 
67
                }
 
68
                (void)SFFILBUF(f,-1);
 
69
        }
 
70
}
 
71
 
 
72
#if __STD_C
 
73
int sfvscanf(Sfio_t* f, reg const char* form, va_list args)
 
74
#else
 
75
int sfvscanf(f,form,args)
 
76
Sfio_t*         f;              /* file to be scanned */
 
77
reg char*       form;           /* scanning format */
 
78
va_list         args;
 
79
#endif
 
80
{
 
81
        reg uchar       *d, *endd, *data;
 
82
        reg int         inp, shift, base, width;
 
83
        ssize_t         size;
 
84
        int             fmt, flags, dot, n_assign, v, n, n_input;
 
85
        char*           sp;
 
86
        char            accept[SF_MAXDIGITS];
 
87
 
 
88
        Argv_t          argv;
 
89
        Sffmt_t         *ft;
 
90
        Fmt_t           *fm, *fmstk;
 
91
 
 
92
        Fmtpos_t*       fp;
 
93
        char            *oform;
 
94
        va_list         oargs;
 
95
        int             argp, argn;
 
96
 
 
97
        Void_t*         value;  /* location to assign scanned value */
 
98
        char*           t_str;
 
99
        ssize_t         n_str;
 
100
        int             rs;
 
101
 
 
102
#define SFBUF(f)        (_sfbuf(f,&rs), (data = d = f->next), (endd = f->endb) )
 
103
#define SFLEN(f)        (d-data)
 
104
#define SFEND(f)        ((n_input += d-data), \
 
105
                         (rs > 0 ? SFREAD(f,(Void_t*)data,d-data) : ((f->next = d), 0)) )
 
106
#define SFGETC(f,c)     ((c) = (d < endd || (SFEND(f), SFBUF(f), d < endd)) ? \
 
107
                                (int)(*d++) : -1 )
 
108
#define SFUNGETC(f,c)   (--d)
 
109
 
 
110
        SFMTXSTART(f,-1);
 
111
 
 
112
        if(!form)
 
113
                SFMTXRETURN(f, -1);
 
114
 
 
115
        if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
 
116
                SFMTXRETURN(f, -1);
 
117
        SFLOCK(f,0);
 
118
 
 
119
        rs = (f->extent < 0 && (f->flags&SF_SHARE)) ? 1 : 0;
 
120
 
 
121
        SFCVINIT();     /* initialize conversion tables */
 
122
 
 
123
        SFBUF(f);
 
124
        n_assign = n_input = 0;
 
125
 
 
126
        inp = -1;
 
127
 
 
128
        fmstk = NIL(Fmt_t*); ft = NIL(Sffmt_t*);
 
129
 
 
130
        fp = NIL(Fmtpos_t*); argn = -1;
 
131
        oform = (char*)form; va_copy(oargs,args);
 
132
 
 
133
loop_fmt :
 
134
        while((fmt = *form++) )
 
135
        {       if(fmt != '%')
 
136
                {       if(isspace(fmt))
 
137
                        {       if(fmt != '\n' || !(f->flags&SF_LINE))
 
138
                                        fmt = -1;
 
139
                                for(;;)
 
140
                                {       if(SFGETC(f,inp) < 0 || inp == fmt)
 
141
                                                goto loop_fmt;
 
142
                                        else if(!isspace(inp))
 
143
                                        {       SFUNGETC(f,inp);
 
144
                                                goto loop_fmt;
 
145
                                        }
 
146
                                }
 
147
                        }
 
148
                        else
 
149
                        { match_1:
 
150
                                if(SFGETC(f,inp) != fmt)
 
151
                                {       if(inp >= 0)
 
152
                                                SFUNGETC(f,inp);
 
153
                                        goto pop_fmt;
 
154
                                }
 
155
                        }
 
156
                        continue;
 
157
                }
 
158
 
 
159
                if(*form == '%')
 
160
                {       form += 1;
 
161
                        goto match_1;
 
162
                }
 
163
 
 
164
                if(*form == '\0')
 
165
                        goto pop_fmt;
 
166
 
 
167
                if(*form == '*')
 
168
                {       flags = SFFMT_SKIP;
 
169
                        form += 1;
 
170
                }
 
171
                else    flags = 0;
 
172
 
 
173
                /* matching some pattern */
 
174
                base = 10; size = -1;
 
175
                width = dot = 0;
 
176
                t_str = NIL(char*); n_str = 0;
 
177
                value = NIL(Void_t*);
 
178
                argp = -1;
 
179
 
 
180
        loop_flags:     /* LOOP FOR FLAGS, WIDTH, BASE, TYPE */
 
181
                switch((fmt = *form++) )
 
182
                {
 
183
                case LEFTP : /* get the type which is enclosed in balanced () */
 
184
                        t_str = (char*)form;
 
185
                        for(v = 1;;)
 
186
                        {       switch(*form++)
 
187
                                {
 
188
                                case 0 :        /* not balanceable, retract */
 
189
                                        form = t_str;
 
190
                                        t_str = NIL(char*);
 
191
                                        n_str = 0;
 
192
                                        goto loop_flags;
 
193
                                case LEFTP :    /* increasing nested level */
 
194
                                        v += 1;
 
195
                                        continue;
 
196
                                case RIGHTP :   /* decreasing nested level */
 
197
                                        if((v -= 1) != 0)
 
198
                                                continue;
 
199
                                        if(*t_str != '*' )
 
200
                                                n_str = (form-1) - t_str;
 
201
                                        else
 
202
                                        {       t_str = (*_Sffmtintf)(t_str+1,&n);
 
203
                                                if(*t_str == '$')
 
204
                                                {       if(!fp &&
 
205
                                                           !(fp = (*_Sffmtposf)
 
206
                                                                  (f,oform,oargs,1)) )
 
207
                                                                goto pop_fmt;
 
208
                                                        n = FP_SET(n,argn);
 
209
                                                }
 
210
                                                else    n = FP_SET(-1,argn);
 
211
 
 
212
                                                if(fp)
 
213
                                                {       t_str = fp[n].argv.s;
 
214
                                                        n_str = fp[n].ft.size;
 
215
                                                }
 
216
                                                else if(ft && ft->extf )
 
217
                                                {       FMTSET(ft, form,args,
 
218
                                                                LEFTP, 0, 0, 0,0,0,
 
219
                                                                NIL(char*),0);
 
220
                                                        n = (*ft->extf)
 
221
                                                              (f,(Void_t*)&argv,ft);
 
222
                                                        if(n < 0)
 
223
                                                                goto pop_fmt;
 
224
                                                        if(!(ft->flags&SFFMT_VALUE) )
 
225
                                                                goto t_arg;
 
226
                                                        if((t_str = argv.s) &&
 
227
                                                           (n_str = (int)ft->size) < 0)
 
228
                                                                n_str = strlen(t_str);
 
229
                                                }
 
230
                                                else
 
231
                                                { t_arg:
 
232
                                                        if((t_str = va_arg(args,char*)) )
 
233
                                                                n_str = strlen(t_str);
 
234
                                                }
 
235
                                        }
 
236
                                        goto loop_flags;
 
237
                                }
 
238
                        }
 
239
 
 
240
                case '#' : /* alternative format */
 
241
                        flags |= SFFMT_ALTER;
 
242
                        goto loop_flags;
 
243
 
 
244
                case '.' : /* width & base */
 
245
                        dot += 1;
 
246
                        if(isdigit(*form))
 
247
                        {       fmt = *form++;
 
248
                                goto dot_size;
 
249
                        }
 
250
                        else if(*form == '*')
 
251
                        {       form = (*_Sffmtintf)(form+1,&n);
 
252
                                if(*form == '$')
 
253
                                {       form += 1;
 
254
                                        if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,1)) )
 
255
                                                goto pop_fmt;
 
256
                                        n = FP_SET(n,argn);
 
257
                                }
 
258
                                else    n = FP_SET(-1,argn);
 
259
 
 
260
                                if(fp)
 
261
                                        v = fp[n].argv.i;
 
262
                                else if(ft && ft->extf )
 
263
                                {       FMTSET(ft, form,args, '.',dot, 0, 0,0,0,
 
264
                                                NIL(char*), 0);
 
265
                                        if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)
 
266
                                                goto pop_fmt;
 
267
                                        if(ft->flags&SFFMT_VALUE)
 
268
                                                v = argv.i;
 
269
                                        else    v = (dot <= 2) ? va_arg(args,int) : 0;
 
270
                                }
 
271
                                else    v = (dot <= 2) ? va_arg(args,int) : 0;
 
272
                                if(v < 0)
 
273
                                        v = 0;
 
274
                                goto dot_set;
 
275
                        }
 
276
                        else    goto loop_flags;
 
277
                        
 
278
                case '0' : case '1' : case '2' : case '3' : case '4' :
 
279
                case '5' : case '6' : case '7' : case '8' : case '9' :
 
280
                dot_size :
 
281
                        for(v = fmt-'0'; isdigit(*form); ++form)
 
282
                                v = v*10 + (*form - '0');
 
283
 
 
284
                        if(*form == '$')
 
285
                        {       form += 1;
 
286
                                if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,1)) )
 
287
                                        goto pop_fmt;
 
288
                                argp = v-1;
 
289
                                goto loop_flags;
 
290
                        }
 
291
 
 
292
                dot_set :
 
293
                        if(dot == 0 || dot == 1)
 
294
                                width = v;
 
295
                        else if(dot == 2)
 
296
                                base = v;
 
297
                        goto loop_flags;
 
298
 
 
299
                case 'I' : /* object size */
 
300
                        size = 0;
 
301
                        flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
 
302
                        if(isdigit(*form))
 
303
                        {       for(n = *form; isdigit(n); n = *++form)
 
304
                                        size = size*10 + (n - '0');
 
305
                        }
 
306
                        else if(*form == '*')
 
307
                        {       form = (*_Sffmtintf)(form+1,&n);
 
308
                                if(*form == '$')
 
309
                                {       form += 1;
 
310
                                        if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,1)))
 
311
                                                goto pop_fmt;
 
312
                                        n = FP_SET(n,argn);
 
313
                                }
 
314
                                else    n = FP_SET(-1,argn);
 
315
 
 
316
                                if(fp)  /* use position list */
 
317
                                        size = fp[n].argv.i;
 
318
                                else if(ft && ft->extf )
 
319
                                {       FMTSET(ft, form,args, 'I',sizeof(int), 0, 0,0,0,
 
320
                                                NIL(char*), 0);
 
321
                                        if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)
 
322
                                                goto pop_fmt;
 
323
                                        if(ft->flags&SFFMT_VALUE)
 
324
                                                size = argv.i;
 
325
                                        else    size = va_arg(args,int);
 
326
                                }
 
327
                                else    size = va_arg(args,int);
 
328
                        }
 
329
                        goto loop_flags;
 
330
 
 
331
                case 'l' :
 
332
                        size = -1;
 
333
                        flags &= ~SFFMT_TYPES;
 
334
                        if(*form == 'l')
 
335
                        {       form += 1;
 
336
                                flags |= SFFMT_LLONG;
 
337
                        }
 
338
                        else    flags |= SFFMT_LONG;
 
339
                        goto loop_flags;
 
340
                case 'h' :
 
341
                        size = -1;
 
342
                        flags &= ~SFFMT_TYPES;
 
343
                        if(*form == 'h')
 
344
                        {       form += 1;
 
345
                                flags |= SFFMT_SSHORT;
 
346
                        }
 
347
                        else    flags |= SFFMT_SHORT;
 
348
                        goto loop_flags;
 
349
                case 'L' :
 
350
                        size = -1;
 
351
                        flags = (flags&~SFFMT_TYPES) | SFFMT_LDOUBLE;
 
352
                        goto loop_flags;
 
353
                case 'j' :
 
354
                        size = -1;
 
355
                        flags = (flags&~SFFMT_TYPES) | SFFMT_JFLAG;
 
356
                        goto loop_flags;
 
357
                case 'z' :
 
358
                        size = -1;
 
359
                        flags = (flags&~SFFMT_TYPES) | SFFMT_ZFLAG;
 
360
                        goto loop_flags;
 
361
                case 't' :
 
362
                        size = -1;
 
363
                        flags = (flags&~SFFMT_TYPES) | SFFMT_TFLAG;
 
364
                        goto loop_flags;
 
365
                }
 
366
 
 
367
                /* set object size */
 
368
                if(flags & (SFFMT_TYPES & ~SFFMT_IFLAG) )
 
369
                {       if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
 
370
                        {       size =  (flags&SFFMT_LLONG) ? sizeof(Sflong_t) :
 
371
                                        (flags&SFFMT_LONG) ? sizeof(long) :
 
372
                                        (flags&SFFMT_SHORT) ? sizeof(short) :
 
373
                                        (flags&SFFMT_SSHORT) ? sizeof(char) :
 
374
                                        (flags&SFFMT_JFLAG) ? sizeof(Sflong_t) :
 
375
                                        (flags&SFFMT_TFLAG) ? sizeof(ptrdiff_t) :
 
376
                                        (flags&SFFMT_ZFLAG) ? sizeof(size_t) :
 
377
                                        -1;
 
378
                        }
 
379
                        else if(_Sftype[fmt]&SFFMT_FLOAT)
 
380
                        {       size = (flags&SFFMT_LDOUBLE) ? sizeof(Sfdouble_t) :
 
381
                                       (flags&(SFFMT_LONG|SFFMT_LLONG)) ?
 
382
                                                sizeof(double) : -1;
 
383
                        }
 
384
                }
 
385
 
 
386
                argp = FP_SET(argp,argn);
 
387
                if(fp)
 
388
                {       if(!(fp[argp].ft.flags&SFFMT_SKIP) )
 
389
                        {       n_assign += 1;
 
390
                                value = fp[argp].argv.vp;
 
391
                                size = fp[argp].ft.size;
 
392
                                if(ft && ft->extf && fp[argp].ft.fmt != fp[argp].fmt)
 
393
                                        fmt = fp[argp].ft.fmt;
 
394
                        }
 
395
                        else    flags |= SFFMT_SKIP;
 
396
                }
 
397
                else if(ft && ft->extf)
 
398
                {       FMTSET(ft, form,args, fmt, size,flags, width,0,base, t_str,n_str);
 
399
                        SFEND(f); SFOPEN(f,0);
 
400
                        v = (*ft->extf)(f, (Void_t*)&argv, ft);
 
401
                        SFLOCK(f,0); SFBUF(f);
 
402
 
 
403
                        if(v < 0)
 
404
                                goto pop_fmt;
 
405
                        else if(v == 0) /* extf did not use input stream */
 
406
                        {       FMTGET(ft, form,args, fmt, size, flags, width,n,base);
 
407
                                if((ft->flags&SFFMT_VALUE) && !(ft->flags&SFFMT_SKIP) )
 
408
                                        value = argv.vp;
 
409
                        }
 
410
                        else /* v > 0: number of input bytes consumed */
 
411
                        {       n_input += v;
 
412
                                if(!(ft->flags&SFFMT_SKIP) )
 
413
                                        n_assign += 1;
 
414
                                continue;
 
415
                        }
 
416
                }
 
417
 
 
418
                if(_Sftype[fmt] == 0) /* unknown pattern */
 
419
                        continue;
 
420
 
 
421
                /* get the address to assign value */
 
422
                if(!value && !(flags&SFFMT_SKIP) )
 
423
                        value = va_arg(args,Void_t*);
 
424
 
 
425
                if(*form == '!')
 
426
                {       form += 1;
 
427
                        if(!fp)
 
428
                                fp = (*_Sffmtposf)(f,oform,oargs,1);
 
429
                        else    goto pop_fmt;
 
430
 
 
431
                        if(!(argv.ft = va_arg(args,Sffmt_t*)) )
 
432
                                continue;
 
433
                        if(!argv.ft->form && ft ) /* change extension functions */
 
434
                        {       if(ft->eventf &&
 
435
                                   (*ft->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)
 
436
                                        continue;
 
437
                                fmstk->ft = ft = argv.ft;
 
438
                        }
 
439
                        else                    /* stack a new environment */
 
440
                        {       if(!(fm = (Fmt_t*)malloc(sizeof(Fmt_t))) )
 
441
                                        goto done;
 
442
 
 
443
                                if(argv.ft->form)
 
444
                                {       fm->form = (char*)form;
 
445
                                        va_copy(fm->args,args);
 
446
 
 
447
                                        fm->oform = oform;
 
448
                                        va_copy(fm->oargs,oargs);
 
449
                                        fm->argn = argn;
 
450
                                        fm->fp = fp;
 
451
 
 
452
                                        form = argv.ft->form;   
 
453
                                        va_copy(args,argv.ft->args);
 
454
                                        argn = -1;
 
455
                                        fp = NIL(Fmtpos_t*);
 
456
                                }
 
457
                                else    fm->form = NIL(char*);
 
458
 
 
459
                                fm->eventf = argv.ft->eventf;
 
460
                                fm->ft = ft;
 
461
                                fm->next = fmstk;
 
462
                                fmstk = fm;
 
463
                                ft = argv.ft;
 
464
                        }
 
465
                        continue;
 
466
                }
 
467
 
 
468
                if(fmt == 'n') /* return length of consumed input */
 
469
                {
 
470
#if !_ast_intmax_long
 
471
                        if(FMTCMP(size,Sflong_t,Sflong_t))
 
472
                                *((Sflong_t*)value) = (Sflong_t)(n_input+SFLEN(f));
 
473
                        else
 
474
#endif
 
475
                        if(sizeof(long) > sizeof(int) && FMTCMP(size,long,Sflong_t))
 
476
                                *((long*)value) = (long)(n_input+SFLEN(f));
 
477
                        else if(sizeof(short) < sizeof(int) &&
 
478
                                FMTCMP(size,short,Sflong_t))
 
479
                                *((short*)value) = (short)(n_input+SFLEN(f));
 
480
                        else if(size == sizeof(char))
 
481
                                *((char*)value) = (char)(n_input+SFLEN(f));
 
482
                        else    *((int*)value) = (int)(n_input+SFLEN(f));
 
483
                        continue;
 
484
                }
 
485
 
 
486
                /* if get here, start scanning input */
 
487
                if(width == 0)
 
488
                        width = fmt == 'c' ? 1 : MAXWIDTH;
 
489
 
 
490
                /* define the first input character */
 
491
                if(fmt == 'c' || fmt == '[')
 
492
                        SFGETC(f,inp);
 
493
                else
 
494
                {       do      { SFGETC(f,inp); }
 
495
                        while(isspace(inp))     /* skip starting blanks */
 
496
                                ;
 
497
                }
 
498
                if(inp < 0)
 
499
                        goto done;
 
500
 
 
501
                if(_Sftype[fmt] == SFFMT_FLOAT)
 
502
                {       reg char*       val;
 
503
                        reg int         dot, exponent;
 
504
 
 
505
                        val = accept;
 
506
                        if(width >= SF_MAXDIGITS)
 
507
                                width = SF_MAXDIGITS-1;
 
508
                        dot = exponent = 0;
 
509
                        do
 
510
                        {       if(isdigit(inp))
 
511
                                        *val++ = inp;
 
512
                                else if(inp == '.')
 
513
                                {       /* too many dots */
 
514
                                        if(dot++ > 0)
 
515
                                                break;
 
516
                                        *val++ = '.';
 
517
                                }
 
518
                                else if(inp == 'e' || inp == 'E')
 
519
                                {       /* too many e,E */
 
520
                                        if(exponent++ > 0)
 
521
                                                break;
 
522
                                        *val++ = inp;
 
523
                                        if(--width <= 0 || SFGETC(f,inp) < 0 ||
 
524
                                           (inp != '-' && inp != '+' && !isdigit(inp)) )
 
525
                                                break;
 
526
                                        *val++ = inp;
 
527
                                }
 
528
                                else if(inp == '-' || inp == '+')
 
529
                                {       /* too many signs */
 
530
                                        if(val > accept)
 
531
                                                break;
 
532
                                        *val++ = inp;
 
533
                                }
 
534
                                else    break;
 
535
 
 
536
                        } while(--width > 0 && SFGETC(f,inp) >= 0);
 
537
 
 
538
                        if(value)
 
539
                        {       *val = '\0';
 
540
#if !_ast_fltmax_double
 
541
                                if(FMTCMP(size,Sfdouble_t,Sfdouble_t))
 
542
                                        argv.ld = _sfstrtod(accept,NIL(char**));
 
543
                                else
 
544
#endif
 
545
                                        argv.d = (double)strtod(accept,NIL(char**));
 
546
                        }
 
547
 
 
548
                        if(value)
 
549
                        {       n_assign += 1;
 
550
#if !_ast_fltmax_double
 
551
                                if(FMTCMP(size,Sfdouble_t,Sfdouble_t))
 
552
                                        *((Sfdouble_t*)value) = argv.ld;
 
553
                                else
 
554
#endif
 
555
                                if(FMTCMP(size,double,Sfdouble_t))
 
556
                                        *((double*)value) = argv.d;
 
557
                                else    *((float*)value) = (float)argv.d;
 
558
                        }
 
559
                }
 
560
                else if(_Sftype[fmt] == SFFMT_UINT || fmt == 'p')
 
561
                {       if(inp == '-')
 
562
                        {       SFUNGETC(f,inp);
 
563
                                goto pop_fmt;
 
564
                        }
 
565
                        else    goto int_cvt;
 
566
                }
 
567
                else if(_Sftype[fmt] == SFFMT_INT)
 
568
                { int_cvt:
 
569
                        if(inp == '-' || inp == '+')
 
570
                        {       if(inp == '-')
 
571
                                        flags |= SFFMT_MINUS;
 
572
                                while(--width > 0 && SFGETC(f,inp) >= 0)
 
573
                                        if(!isspace(inp))
 
574
                                                break;
 
575
                        }
 
576
                        if(inp < 0)
 
577
                                goto done;
 
578
 
 
579
                        if(fmt == 'o')
 
580
                                base = 8;
 
581
                        else if(fmt == 'x' || fmt == 'p')
 
582
                                base = 16;
 
583
                        else if(fmt == 'i' && inp == '0') /* self-described data */
 
584
                        {       base = 8;
 
585
                                if(width > 1) /* peek to see if it's a base-16 */
 
586
                                {       if(SFGETC(f,inp) >= 0)
 
587
                                        {       if(inp == 'x' || inp == 'X')
 
588
                                                        base = 16;
 
589
                                                SFUNGETC(f,inp);
 
590
                                        }
 
591
                                        inp = '0';
 
592
                                }
 
593
                        }
 
594
 
 
595
                        /* now convert */
 
596
                        argv.lu = 0;
 
597
                        if(base == 16)
 
598
                        {       sp = (char*)_Sfcv36;
 
599
                                shift = 4;
 
600
                                if(sp[inp] >= 16)
 
601
                                {       SFUNGETC(f,inp);
 
602
                                        goto pop_fmt;
 
603
                                }
 
604
                                if(inp == '0' && --width > 0)
 
605
                                {       /* skip leading 0x or 0X */
 
606
                                        if(SFGETC(f,inp) >= 0 &&
 
607
                                           (inp == 'x' || inp == 'X') && --width > 0)
 
608
                                                SFGETC(f,inp);
 
609
                                }
 
610
                                if(inp >= 0 && sp[inp] < 16)
 
611
                                        goto base_shift;
 
612
                        }
 
613
                        else if(base == 10)
 
614
                        {       /* fast base 10 conversion */
 
615
                                if(inp < '0' || inp > '9')
 
616
                                {       SFUNGETC(f,inp);
 
617
                                        goto pop_fmt;
 
618
                                }
 
619
 
 
620
                                do
 
621
                                { argv.lu = (argv.lu<<3) + (argv.lu<<1) + (inp-'0');
 
622
                                } while(--width > 0 &&
 
623
                                        SFGETC(f,inp) >= '0' && inp <= '9');
 
624
 
 
625
                                if(fmt == 'i' && inp == '#' && !(flags&SFFMT_ALTER) )
 
626
                                {       base = (int)argv.lu;
 
627
                                        if(base < 2 || base > SF_RADIX)
 
628
                                                goto pop_fmt;
 
629
                                        argv.lu = 0;
 
630
                                        sp = base <= 36 ? (char*)_Sfcv36 : (char*)_Sfcv64;
 
631
                                        if(--width > 0 &&
 
632
                                           SFGETC(f,inp) >= 0 && sp[inp] < base)
 
633
                                                goto base_conv;
 
634
                                }
 
635
                        }
 
636
                        else
 
637
                        {       /* other bases */
 
638
                                sp = base <= 36 ? (char*)_Sfcv36 : (char*)_Sfcv64;
 
639
                                if(base < 2 || base > SF_RADIX || sp[inp] >= base)
 
640
                                {       SFUNGETC(f,inp);
 
641
                                        goto pop_fmt;
 
642
                                }
 
643
 
 
644
                        base_conv: /* check for power of 2 conversions */
 
645
                                if((base & ~(base-1)) == base)
 
646
                                {       if(base < 8)
 
647
                                                shift = base <  4 ? 1 : 2;
 
648
                                        else if(base < 32)
 
649
                                                shift = base < 16 ? 3 : 4;
 
650
                                        else    shift = base < 64 ? 5 : 6;
 
651
 
 
652
                        base_shift:     do
 
653
                                        { argv.lu = (argv.lu << shift) + sp[inp];
 
654
                                        } while(--width > 0 &&
 
655
                                                SFGETC(f,inp) >= 0 && sp[inp] < base);
 
656
                                }
 
657
                                else
 
658
                                {       do
 
659
                                        { argv.lu = (argv.lu * base) + sp[inp];
 
660
                                        } while(--width > 0 &&
 
661
                                                SFGETC(f,inp) >= 0 && sp[inp] < base);
 
662
                                }
 
663
                        }
 
664
 
 
665
                        if(flags&SFFMT_MINUS)
 
666
                                argv.ll = -argv.ll;
 
667
 
 
668
                        if(value)
 
669
                        {       n_assign += 1;
 
670
 
 
671
                                if(fmt == 'p')
 
672
#if _more_void_int
 
673
                                        *((Void_t**)value) = (Void_t*)((ulong)argv.lu);
 
674
#else
 
675
                                        *((Void_t**)value) = (Void_t*)((uint)argv.lu);
 
676
#endif
 
677
#if !_ast_intmax_long
 
678
                                else if(FMTCMP(size,Sflong_t,Sflong_t))
 
679
                                        *((Sflong_t*)value) = argv.ll;
 
680
#endif
 
681
                                else if(sizeof(long) > sizeof(int) &&
 
682
                                        FMTCMP(size,long,Sflong_t))
 
683
                                {       if(fmt == 'd' || fmt == 'i')
 
684
                                                *((long*)value) = (long)argv.ll;
 
685
                                        else    *((ulong*)value) = (ulong)argv.lu;
 
686
                                }
 
687
                                else if(sizeof(short) < sizeof(int) &&
 
688
                                        FMTCMP(size,short,Sflong_t))
 
689
                                {       if(fmt == 'd' || fmt == 'i')
 
690
                                                *((short*)value) = (short)argv.ll;
 
691
                                        else    *((ushort*)value) = (ushort)argv.lu;
 
692
                                }
 
693
                                else if(size == sizeof(char) )
 
694
                                {       if(fmt == 'd' || fmt == 'i')
 
695
                                                *((char*)value) = (char)argv.ll;
 
696
                                        else    *((uchar*)value) = (uchar)argv.lu;
 
697
                                }
 
698
                                else
 
699
                                {       if(fmt == 'd' || fmt == 'i')
 
700
                                                *((int*)value) = (int)argv.ll;
 
701
                                        else    *((uint*)value) = (uint)argv.lu;
 
702
                                }
 
703
                        }
 
704
                }
 
705
                else if(fmt == 's' || fmt == 'c' || fmt == '[')
 
706
                {       if(size < 0)
 
707
                                size = MAXWIDTH;
 
708
                        if(value)
 
709
                        {       argv.s = (char*)value;
 
710
                                if(fmt != 'c')
 
711
                                        size -= 1;
 
712
                        }
 
713
                        else    size = 0;
 
714
 
 
715
                        n = 0;
 
716
                        if(fmt == 's')
 
717
                        {       do
 
718
                                {       if(isspace(inp))
 
719
                                                break;
 
720
                                        if((n += 1) <= size)
 
721
                                                *argv.s++ = inp;
 
722
                                } while(--width > 0 && SFGETC(f,inp) >= 0);
 
723
                        }
 
724
                        else if(fmt == 'c')
 
725
                        {       do
 
726
                                {       if((n += 1) <= size)
 
727
                                                *argv.s++ = inp;
 
728
                                } while(--width > 0 && SFGETC(f,inp) >= 0);
 
729
                        }
 
730
                        else /* if(fmt == '[') */
 
731
                        {       form = setclass((char*)form,accept);
 
732
                                do
 
733
                                {       if(!accept[inp])
 
734
                                        {       if(n > 0 || (flags&SFFMT_ALTER) )
 
735
                                                        break;
 
736
                                                else
 
737
                                                {       SFUNGETC(f,inp);
 
738
                                                        goto pop_fmt;
 
739
                                                }
 
740
                                        }
 
741
                                        if((n += 1) <= size)
 
742
                                                *argv.s++ = inp;
 
743
                                } while(--width > 0 && SFGETC(f,inp) >= 0);
 
744
                        }
 
745
 
 
746
                        if(value && (n > 0 || fmt == '[') )
 
747
                        {       n_assign += 1;
 
748
                                if(fmt != 'c' && size >= 0)
 
749
                                        *argv.s = '\0';
 
750
                        }
 
751
                }
 
752
 
 
753
                if(width > 0 && inp >= 0)
 
754
                        SFUNGETC(f,inp);
 
755
        }
 
756
 
 
757
pop_fmt:
 
758
        if(fp)
 
759
        {       free(fp);
 
760
                fp = NIL(Fmtpos_t*);
 
761
        }
 
762
        while((fm = fmstk) ) /* pop the format stack and continue */
 
763
        {       if(fm->eventf)
 
764
                {       if(!form || !form[0])
 
765
                                (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),ft);
 
766
                        else if((*fm->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)
 
767
                                goto loop_fmt;
 
768
                }
 
769
 
 
770
                fmstk = fm->next;
 
771
                if((form = fm->form) )
 
772
                {       va_copy(args, fm->args);
 
773
                        oform = fm->oform;
 
774
                        va_copy(oargs,fm->oargs);
 
775
                        argn = fm->argn;
 
776
                        fp = fm->fp;
 
777
                }
 
778
                ft = fm->ft;
 
779
                free(fm);
 
780
                if(form && form[0])
 
781
                        goto loop_fmt;
 
782
        }
 
783
 
 
784
done:
 
785
        if(fp)
 
786
                free(fp);
 
787
        while((fm = fmstk) )
 
788
        {       if(fm->eventf)
 
789
                        (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),fm->ft);
 
790
                fmstk = fm->next;
 
791
                free(fm);
 
792
        }
 
793
 
 
794
        SFEND(f);
 
795
        SFOPEN(f,0);
 
796
 
 
797
        if(n_assign == 0 && inp < 0)
 
798
                n_assign = -1;
 
799
 
 
800
        SFMTXRETURN(f,n_assign);
 
801
}