1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
24 /* The main engine for reading formatted data
26 ** Written by Kiem-Phong Vo.
29 #define MAXWIDTH (int)(((uint)~0)>>1) /* max amount to scan */
32 * pull in a private strtold()
37 /* refresh stream buffer - taking care of unseekable/share streams too */
39 static void _sfbuf(Sfio_t
* f
, int* peek
)
41 static void _sfbuf(f
, peek
)
46 if(f
->next
>= f
->endb
)
47 { if(*peek
) /* try peeking for a share stream if possible */
49 if(SFFILBUF(f
,-1) > 0)
53 *peek
= 0; /* can't peek, back to normal reads */
59 /* buffer used during scanning of a double value or a multi-byte
60 character. the fields mirror certain local variables in sfvscanf. */
61 typedef struct _scan_s
62 { int error
; /* get set by _sfdscan if no value specified */
63 int inp
; /* last input character read */
64 int width
; /* field width */
65 Sfio_t
*f
; /* stream being scanned */
66 uchar
*d
, *endd
, *data
; /* local buffering system */
67 int peek
; /* != 0 if unseekable/share stream */
68 int n_input
;/* number of input bytes processed */
71 /* ds != 0 for scanning double values */
72 #define SCinit(sc,ds) ((sc)->inp = (sc)->error = -1, (sc)->f = f, \
73 ((sc)->width = (ds) ? width : -1), \
74 (sc)->d = d, (sc)->endd = endd, (sc)->data = data, \
75 (sc)->peek = peek, (sc)->n_input = n_input)
76 #define SCend(sc,ds) (inp = (sc)->inp, f = (sc)->f, \
77 (width = (ds) ? (sc)->width : width), \
78 d = (sc)->d, endd = (sc)->endd, data = (sc)->data, \
79 peek = (sc)->peek, n_input = (sc)->n_input)
82 static int _scgetc(void* arg
, int flag
)
84 static int _scgetc(arg
, flag
)
89 Scan_t
*sc
= (Scan_t
*)arg
;
96 /* if width >= 0, do not allow to exceed width number of bytes */
102 if(sc
->d
>= sc
->endd
) /* refresh local buffer */
103 { sc
->n_input
+= sc
->d
- sc
->data
;
105 SFREAD(sc
->f
, sc
->data
, sc
->d
- sc
->data
);
106 else sc
->f
->next
= sc
->d
;
108 _sfbuf(sc
->f
, &sc
->peek
);
109 sc
->data
= sc
->d
= sc
->f
->next
;
110 sc
->endd
= sc
->f
->endb
;
112 if(sc
->d
>= sc
->endd
)
118 if((sc
->width
-= 1) >= 0) /* from _sfdscan */
119 return (sc
->inp
= (int)(*sc
->d
++));
120 else return ((int)(*sc
->d
++));
123 /* structure to match characters in a character class */
124 typedef struct _accept_s
125 { char ok
[SF_MAXCHAR
+1];
134 static char* _sfsetclass(const char* form
, Accept_t
* ac
, int flags
)
136 static char* _sfsetclass(form
, ac
, flags
)
137 char* form
; /* format string */
138 Accept_t
* ac
; /* values of accepted characters */
139 int flags
; /* SFFMT_LONG for wchar_t */
147 if(*form
== '^') /* complementing this set */
153 for(c
= 0; c
<= SF_MAXCHAR
; ++c
)
154 ac
->ok
[c
] = !ac
->yes
;
156 if(*form
== ']' || *form
== '-') /* special first char */
157 { ac
->ok
[*form
] = ac
->yes
;
160 ac
->form
= (char*)form
;
164 for(n
= 1; *form
!= ']'; form
+= n
)
165 { if((c
= *((uchar
*)form
)) == 0)
169 { endc
= *((uchar
*)(form
+2));
171 if(c
>= 128 || endc
>= 128 ) /* range must be ascii */
174 for(; c
<= endc
; ++c
)
180 #if _has_multibyte /* true multi-byte chars must be checked differently */
181 if((flags
&SFFMT_LONG
) && (n
= (int)SFMBLEN(form
,&mbs
)) <= 0)
189 ac
->endf
= (char*)form
;
190 return (char*)(form
+1);
195 static int _sfwaccept(wchar_t wc
, Accept_t
* ac
)
197 static int _sfwaccept(wc
, ac
)
204 char *form
= ac
->form
;
208 for(n
= 1; *form
!= ']'; form
+= n
)
209 { if((c
= *((uchar
*)form
)) == 0)
213 { endc
= *((uchar
*)(form
+2));
214 if(c
>= 128 || endc
>= 128 ) /* range must be ascii */
220 if((n
= mbrtowc(&fwc
, form
, ac
->endf
-form
, &mbs
)) > 1 &&
229 #if _has_multibyte == 1
230 #define SFgetwc(sc,wc,fmt,ac,mbs) _sfgetwc(sc,wc,fmt,ac,(Void_t*)(mbs))
232 #define SFgetwc(sc,wc,fmt,ac,mbs) _sfgetwc(sc,wc,fmt,ac,NIL(Void_t*))
236 static int _sfgetwc(Scan_t
* sc
, wchar_t* wc
, int fmt
, Accept_t
* ac
, Void_t
*mbs
)
238 static int _sfgetwc(sc
, wc
, fmt
, ac
, mbs
)
239 Scan_t
* sc
; /* the scanning handle */
240 wchar_t* wc
; /* to return a scanned wchar_t */
241 int fmt
; /* %s, %c, %[ */
242 Accept_t
* ac
; /* accept handle for %[ */
243 Void_t
* mbs
; /* multibyte parsing state */
247 char b
[16]; /* assuming that SFMBMAX <= 16! */
249 /* shift left data so that there will be more room to back up on error.
250 this won't help streams with small buffers - c'est la vie! */
251 if(sc
->d
> sc
->f
->data
&& (n
= sc
->endd
- sc
->d
) > 0 && n
< SFMBMAX
)
252 { memcpy(sc
->f
->data
, sc
->d
, n
);
253 if(sc
->f
->endr
== sc
->f
->endb
)
254 sc
->f
->endr
= sc
->f
->data
+n
;
255 if(sc
->f
->endw
== sc
->f
->endb
)
256 sc
->f
->endw
= sc
->f
->data
+n
;
257 sc
->f
->endb
= sc
->f
->data
+n
;
258 sc
->d
= sc
->data
= sc
->f
->data
;
259 sc
->endd
= sc
->f
->endb
;
260 if(!mbs
) sc
->f
->endb
= sc
->endd
; /* stop cc's "unused mbs" warning */
263 for(n
= 0; n
< SFMBMAX
; )
264 { if((v
= _scgetc((Void_t
*)sc
, 0)) <= 0)
268 if(mbrtowc(wc
, b
, n
, (mbstate_t*)mbs
) == (size_t)(-1))
269 goto no_match
; /* malformed multi-byte char */
271 { /* multi-byte char converted successfully */
275 { if(n
> 1 || (n
== 1 && !isspace(b
[0]) ) )
280 { if((n
== 1 && ac
->ok
[b
[0]]) ||
281 (n
> 1 && _sfwaccept(*wc
,ac
)) )
285 else /* if(fmt == '1') match a single wchar_t */
293 no_match
: /* this unget is lossy on a stream with small buffer */
294 if((sc
->d
-= n
) < sc
->data
)
298 #endif /*_has_multibyte*/
302 int sfvscanf(Sfio_t
* f
, reg
const char* form
, va_list args
)
304 int sfvscanf(f
,form
,args
)
305 Sfio_t
* f
; /* file to be scanned */
306 reg
char* form
; /* scanning format */
310 reg
int inp
, shift
, base
, width
;
312 int fmt
, flags
, dot
, n_assign
, v
, n
, n_input
;
326 int decimal
= 0, thousand
= 0;
334 Void_t
* value
; /* location to assign scanned value */
338 /* local buffering system */
340 uchar
*d
, *endd
, *data
;
342 #define SFbuf(f) (_sfbuf(f,&peek), (data = d = f->next), (endd = f->endb) )
343 #define SFlen(f) (d - data)
344 #define SFinit(f) ((peek = f->extent < 0 && (f->flags&SF_SHARE)), SFbuf(f) )
345 #define SFend(f) ((n_input += SFlen(f)), \
346 (peek ? SFREAD(f,(Void_t*)data,SFlen(f)) : ((f->next = d),0)) )
347 #define SFgetc(f,c) ((c) = (d < endd || (SFend(f), SFbuf(f), d < endd)) ? \
349 #define SFungetc(f,c) (d -= 1)
353 SFCVINIT(); /* initialize conversion tables */
357 if(!form
|| f
->mode
!= SF_READ
&& _sfmode(f
,SF_READ
,0) < 0)
361 SFinit(f
); /* initialize local buffering system */
363 n_assign
= n_input
= 0; inp
= -1;
373 SFSETLOCALE(&decimal
, &thousand
);
377 while((fmt
= *form
++))
380 { if(fmt
!= '\n' || !(f
->flags
&SF_LINE
))
383 { if(SFgetc(f
,inp
) < 0 || inp
== fmt
)
385 else if(!isspace(inp
))
394 if((n
= (int)mbrtowc(&wc
,form
-1,SFMBMAX
,&fmbs
)) <= 0)
398 SCinit(&scd
,0); SFMBCLR(&mbs
);
399 v
= SFgetwc(&scd
, &wc
, '1', &acc
, &mbs
);
407 if(SFgetc(f
,inp
) != fmt
)
419 do SFgetc(f
,inp
); while(isspace(inp
)); /* skip starting blanks */
428 { flags
= SFFMT_SKIP
;
433 /* matching some pattern */
434 base
= 10; size
= -1;
436 t_str
= NIL(char*); n_str
= 0;
437 value
= NIL(Void_t
*);
440 loop_flags
: /* LOOP FOR FLAGS, WIDTH, BASE, TYPE */
441 switch((fmt
= *form
++) )
443 case LEFTP
: /* get the type which is enclosed in balanced () */
448 case 0 : /* not balanceable, retract */
453 case LEFTP
: /* increasing nested level */
456 case RIGHTP
: /* decreasing nested level */
460 n_str
= (form
-1) - t_str
;
462 { t_str
= (*_Sffmtintf
)(t_str
+1,&n
);
465 !(fp
= (*_Sffmtposf
)(f
,oform
,oargs
,ft
,1)) )
469 else n
= FP_SET(-1,argn
);
472 { t_str
= fp
[n
].argv
.s
;
473 n_str
= fp
[n
].ft
.size
;
475 else if(ft
&& ft
->extf
)
476 { FMTSET(ft
, form
,args
,
480 (f
,(Void_t
*)&argv
,ft
);
483 if(!(ft
->flags
&SFFMT_VALUE
) )
485 if((t_str
= argv
.s
) &&
486 (n_str
= (int)ft
->size
) < 0)
487 n_str
= strlen(t_str
);
491 if((t_str
= va_arg(args
,char*)) )
492 n_str
= strlen(t_str
);
499 case '#' : /* alternative format */
500 flags
|= SFFMT_ALTER
;
503 case '.' : /* width & base */
509 else if(*form
== '*')
510 { form
= (*_Sffmtintf
)(form
+1,&n
);
514 !(fp
= (*_Sffmtposf
)(f
,oform
,oargs
,ft
,1)) )
518 else n
= FP_SET(-1,argn
);
522 else if(ft
&& ft
->extf
)
523 { FMTSET(ft
, form
,args
, '.',dot
, 0, 0,0,0,
525 if((*ft
->extf
)(f
, (Void_t
*)(&argv
), ft
) < 0)
527 if(ft
->flags
&SFFMT_VALUE
)
529 else v
= (dot
<= 2) ? va_arg(args
,int) : 0;
531 else v
= (dot
<= 2) ? va_arg(args
,int) : 0;
536 else goto loop_flags
;
538 case '0' : case '1' : case '2' : case '3' : case '4' :
539 case '5' : case '6' : case '7' : case '8' : case '9' :
541 for(v
= fmt
-'0'; isdigit(*form
); ++form
)
542 v
= v
*10 + (*form
- '0');
546 if(!fp
&& !(fp
= (*_Sffmtposf
)(f
,oform
,oargs
,ft
,1)) )
553 if(dot
== 0 || dot
== 1)
559 case 'I' : /* object size */
560 size
= -1; flags
= (flags
& ~SFFMT_TYPES
) | SFFMT_IFLAG
;
562 { for(size
= 0, n
= *form
; isdigit(n
); n
= *++form
)
563 size
= size
*10 + (n
- '0');
565 else if(*form
== '*')
566 { form
= (*_Sffmtintf
)(form
+1,&n
);
570 !(fp
= (*_Sffmtposf
)(f
,oform
,oargs
,ft
,1)))
574 else n
= FP_SET(-1,argn
);
576 if(fp
) /* use position list */
578 else if(ft
&& ft
->extf
)
579 { FMTSET(ft
, form
,args
, 'I',sizeof(int), 0, 0,0,0,
581 if((*ft
->extf
)(f
, (Void_t
*)(&argv
), ft
) < 0)
583 if(ft
->flags
&SFFMT_VALUE
)
585 else size
= va_arg(args
,int);
587 else size
= va_arg(args
,int);
592 size
= -1; flags
&= ~SFFMT_TYPES
;
595 flags
|= SFFMT_LLONG
;
597 else flags
|= SFFMT_LONG
;
600 size
= -1; flags
&= ~SFFMT_TYPES
;
603 flags
|= SFFMT_SSHORT
;
605 else flags
|= SFFMT_SHORT
;
608 size
= -1; flags
= (flags
&~SFFMT_TYPES
) | SFFMT_LDOUBLE
;
611 size
= -1; flags
= (flags
&~SFFMT_TYPES
) | SFFMT_JFLAG
;
614 size
= -1; flags
= (flags
&~SFFMT_TYPES
) | SFFMT_ZFLAG
;
617 size
= -1; flags
= (flags
&~SFFMT_TYPES
) | SFFMT_TFLAG
;
621 flags
|= SFFMT_THOUSAND
;
625 /* set object size for scalars */
626 if(flags
& SFFMT_TYPES
)
627 { if((_Sftype
[fmt
]&(SFFMT_INT
|SFFMT_UINT
)) || fmt
== 'n')
628 { if(flags
&SFFMT_LONG
)
630 else if(flags
&SFFMT_SHORT
)
631 size
= sizeof(short);
632 else if(flags
&SFFMT_SSHORT
)
634 else if(flags
&SFFMT_TFLAG
)
635 size
= sizeof(ptrdiff_t);
636 else if(flags
&SFFMT_ZFLAG
)
637 size
= sizeof(size_t);
638 else if(flags
&(SFFMT_LLONG
|SFFMT_JFLAG
) )
639 size
= sizeof(Sflong_t
);
640 else if(flags
&SFFMT_IFLAG
)
642 size
== sizeof(Sflong_t
)*CHAR_BIT
)
643 size
= sizeof(Sflong_t
);
648 else if(_Sftype
[fmt
]&SFFMT_FLOAT
)
649 { if(flags
&(SFFMT_LONG
|SFFMT_LLONG
))
650 size
= sizeof(double);
651 else if(flags
&SFFMT_LDOUBLE
)
652 size
= sizeof(Sfdouble_t
);
653 else if(flags
&SFFMT_IFLAG
)
655 size
= sizeof(Sfdouble_t
);
658 size
= sizeof(float);
660 else if(_Sftype
[fmt
]&SFFMT_CHAR
)
663 if((flags
&SFFMT_LONG
) || fmt
== 'C')
664 { size
= sizeof(wchar_t) > sizeof(int) ?
665 sizeof(wchar_t) : sizeof(int);
673 argp
= FP_SET(argp
,argn
);
675 { if(!(fp
[argp
].ft
.flags
&SFFMT_SKIP
) )
677 value
= fp
[argp
].argv
.vp
;
678 size
= fp
[argp
].ft
.size
;
679 if(ft
&& ft
->extf
&& fp
[argp
].ft
.fmt
!= fp
[argp
].fmt
)
680 fmt
= fp
[argp
].ft
.fmt
;
682 else flags
|= SFFMT_SKIP
;
684 else if(ft
&& ft
->extf
)
685 { FMTSET(ft
, form
,args
, fmt
, size
,flags
, width
,0,base
, t_str
,n_str
);
686 SFend(f
); SFOPEN(f
,0);
687 v
= (*ft
->extf
)(f
, (Void_t
*)&argv
, ft
);
688 SFLOCK(f
,0); SFbuf(f
);
692 else if(v
> 0) /* extf comsumed v input bytes */
694 if(!(ft
->flags
&SFFMT_SKIP
) )
698 else /* if(v == 0): extf did not use input stream */
699 { FMTGET(ft
, form
,args
, fmt
, size
, flags
, width
,n
,base
);
701 if((ft
->flags
&SFFMT_VALUE
) && !(ft
->flags
&SFFMT_SKIP
) )
706 if(_Sftype
[fmt
] == 0) /* unknown pattern */
711 fp
= (*_Sffmtposf
)(f
,oform
,oargs
,ft
,1);
714 if(!(argv
.ft
= va_arg(args
,Sffmt_t
*)) )
716 if(!argv
.ft
->form
&& ft
) /* change extension functions */
718 (*ft
->eventf
)(f
,SF_DPOP
,(Void_t
*)form
,ft
) < 0)
720 fmstk
->ft
= ft
= argv
.ft
;
722 else /* stack a new environment */
723 { if(!(fm
= (Fmt_t
*)malloc(sizeof(Fmt_t
))) )
726 ft
= fm
->ft
= argv
.ft
;
727 SFMBSET(ft
->mbs
, &fmbs
);
729 { fm
->form
= (char*)form
; SFMBCPY(&fm
->mbs
,&fmbs
);
730 va_copy(fm
->args
,args
);
733 va_copy(fm
->oargs
,oargs
);
737 form
= ft
->form
; SFMBCLR(ft
->mbs
);
738 va_copy(args
,ft
->args
);
744 else fm
->form
= NIL(char*);
746 fm
->eventf
= ft
->eventf
;
753 /* get the address to assign value */
754 if(!value
&& !(flags
&SFFMT_SKIP
) )
755 value
= va_arg(args
,Void_t
*);
757 if(fmt
== 'n') /* return length of consumed input */
759 #if !_ast_intmax_long
760 if(size
== sizeof(Sflong_t
) )
761 *((Sflong_t
*)value
) = (Sflong_t
)(n_input
+SFlen(f
));
764 if(size
== sizeof(long) )
765 *((long*)value
) = (long)(n_input
+SFlen(f
));
766 else if(size
== sizeof(short) )
767 *((short*)value
) = (short)(n_input
+SFlen(f
));
768 else if(size
== sizeof(uchar
))
769 *((uchar
*)value
) = (uchar
)(n_input
+SFlen(f
));
770 else *((int*)value
) = (int)(n_input
+SFlen(f
));
774 /* if get here, start scanning input */
776 width
= fmt
== 'c' ? 1 : MAXWIDTH
;
778 /* define the first input character */
779 if(fmt
== 'c' || fmt
== '[' || fmt
== 'C' )
782 { do { SFgetc(f
,inp
); }
783 while(isspace(inp
)); /* skip starting blanks */
788 if(_Sftype
[fmt
] == SFFMT_FLOAT
)
789 { SFungetc(f
,inp
); SCinit(&scd
,1);
790 argv
.ld
= _sfdscan((Void_t
*)(&scd
), _scgetc
);
801 #if !_ast_fltmax_double
802 if(size
== sizeof(Sfdouble_t
))
803 *((Sfdouble_t
*)value
) = argv
.ld
;
806 if(size
== sizeof(double))
807 *((double*)value
) = (double)argv
.ld
;
808 else *((float*)value
) = (float)argv
.ld
;
813 else if(_Sftype
[fmt
] == SFFMT_UINT
|| fmt
== 'p')
820 else if(_Sftype
[fmt
] == SFFMT_INT
)
822 if(inp
== '-' || inp
== '+')
824 flags
|= SFFMT_MINUS
;
825 while(--width
> 0 && SFgetc(f
,inp
) >= 0)
834 else if(fmt
== 'x' || fmt
== 'X' || fmt
== 'p')
836 else if(fmt
== 'i' && inp
== '0') /* self-described data */
838 if(width
> 1) /* peek to see if it's a base-16 */
839 { if(SFgetc(f
,inp
) >= 0)
840 { if(inp
== 'x' || inp
== 'X')
851 { sp
= (char*)_Sfcv36
;
857 if(inp
== '0' && --width
> 0)
858 { /* skip leading 0x or 0X */
859 if(SFgetc(f
,inp
) >= 0 &&
860 (inp
== 'x' || inp
== 'X') && --width
> 0)
863 if(inp
>= 0 && sp
[inp
] < 16)
868 { /* fast base 10 conversion */
869 #define TEN(x) (((x) << 3) + ((x) << 1) )
870 if (inp
>= '0' && inp
<= '9')
871 { argv
.lu
= TEN(argv
.lu
) + (inp
-'0');
874 else if(inp
== thousand
)
875 { if((v
&& n
!= 3) || (!v
&& n
> 3) )
880 if((width
-= 1) <= 0 || SFgetc(f
,inp
) < 0)
888 if(fmt
== 'i' && inp
== '#' && !(flags
&SFFMT_ALTER
) )
889 { base
= (int)argv
.lu
;
890 if(base
< 2 || base
> SF_RADIX
)
893 sp
= (char*)(base
<= 36 ? _Sfcv36
: _Sfcv64
);
895 SFgetc(f
,inp
) >= 0 && sp
[inp
] < base
)
901 sp
= (char*)(base
<= 36 ? _Sfcv36
: _Sfcv64
);
902 if(base
< 2 || base
> SF_RADIX
|| sp
[inp
] >= base
)
907 base_conv
: /* check for power of 2 conversions */
908 if((base
& ~(base
-1)) == base
)
910 shift
= base
< 4 ? 1 : 2;
912 shift
= base
< 16 ? 3 : 4;
913 else shift
= base
< 64 ? 5 : 6;
916 { argv
.lu
= (argv
.lu
<< shift
) + sp
[inp
];
917 } while(--width
> 0 &&
918 SFgetc(f
,inp
) >= 0 && sp
[inp
] < base
);
922 { argv
.lu
= (argv
.lu
* base
) + sp
[inp
];
923 } while(--width
> 0 &&
924 SFgetc(f
,inp
) >= 0 && sp
[inp
] < base
);
928 if(flags
&SFFMT_MINUS
)
936 *((Void_t
**)value
) = (Void_t
*)((ulong
)argv
.lu
);
938 *((Void_t
**)value
) = (Void_t
*)((uint
)argv
.lu
);
940 #if !_ast_intmax_long
941 else if(size
== sizeof(Sflong_t
))
942 *((Sflong_t
*)value
) = argv
.ll
;
944 else if(size
== sizeof(long))
945 { if(fmt
== 'd' || fmt
== 'i')
946 *((long*)value
) = (long)argv
.ll
;
947 else *((ulong
*)value
) = (ulong
)argv
.lu
;
949 else if(size
== sizeof(short))
950 { if(fmt
== 'd' || fmt
== 'i')
951 *((short*)value
) = (short)argv
.ll
;
952 else *((ushort
*)value
) = (ushort
)argv
.lu
;
954 else if(size
== sizeof(char) )
955 { if(fmt
== 'd' || fmt
== 'i')
956 *((char*)value
) = (char)argv
.ll
;
957 else *((uchar
*)value
) = (uchar
)argv
.lu
;
960 { if(fmt
== 'd' || fmt
== 'i')
961 *((int*)value
) = (int)argv
.ll
;
962 else *((uint
*)value
) = (uint
)argv
.lu
;
966 else if(fmt
== 'C' || fmt
== 'S')
967 { fmt
= fmt
== 'C' ? 'c' : 's';
968 flags
= (flags
& ~SFFMT_TYPES
) | SFFMT_LONG
;
971 else if(fmt
== 's' || fmt
== 'c' || fmt
== '[' )
980 argv
.ws
= (wchar_t*)value
;
983 argv
.s
= (char*)value
;
987 if(fmt
== '[' && !(form
= _sfsetclass(form
,&acc
,flags
)) )
992 n
= 0; /* count number of scanned characters */
995 { SFungetc(f
,inp
); SCinit(&scd
,0); SFMBCLR(&mbs
);
996 for(; width
> 0; --width
)
997 { if(SFgetwc(&scd
,&wc
,fmt
,&acc
,&mbs
) == 0)
1011 if((n
+= 1) <= size
)
1013 } while(--width
> 0 && SFgetc(f
,inp
) >= 0);
1017 { if((n
+= 1) <= size
)
1019 } while(--width
> 0 && SFgetc(f
,inp
) >= 0);
1021 else /* if(fmt == '[') */
1024 { if(n
> 0 || (flags
&SFFMT_ALTER
) )
1031 if((n
+= 1) <= size
)
1033 } while(--width
> 0 && SFgetc(f
,inp
) >= 0);
1036 if(value
&& (n
> 0 || fmt
== '[') )
1038 if(fmt
!= 'c' && size
>= 0)
1041 if(flags
&SFFMT_LONG
)
1050 if(width
> 0 && inp
>= 0)
1057 fp
= NIL(Fmtpos_t
*);
1059 while((fm
= fmstk
) ) /* pop the format stack and continue */
1061 { if(!form
|| !form
[0])
1062 (*fm
->eventf
)(f
,SF_FINAL
,NIL(Void_t
*),ft
);
1063 else if((*fm
->eventf
)(f
,SF_DPOP
,(Void_t
*)form
,ft
) < 0)
1068 if((form
= fm
->form
) )
1069 { SFMBCPY(&fmbs
,&fm
->mbs
);
1070 va_copy(args
, fm
->args
);
1072 va_copy(oargs
,fm
->oargs
);
1085 while((fm
= fmstk
) )
1087 (*fm
->eventf
)(f
,SF_FINAL
,NIL(Void_t
*),fm
->ft
);
1096 if(n_assign
== 0 && inp
< 0)
1099 SFMTXRETURN(f
,n_assign
);