4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include <sys/types.h>
55 #define NCHARS (1 << BITSPERBYTE)
57 /* if the _IOWRT flag is set, this must be a call from sscanf */
58 #define locgetc(cnt) (cnt += 1, (iop->_flag & _IOWRT) ? \
59 ((*iop->_ptr == '\0') ? EOF : *iop->_ptr++) : \
61 #define locungetc(cnt, x) (cnt -= 1, (x == EOF) ? EOF : \
62 ((iop->_flag & _IOWRT) ? *(--iop->_ptr) : \
63 (++iop->_cnt, *(--iop->_ptr))))
65 #define wlocgetc() ((iop->_flag & _IOWRT) ? \
66 ((*iop->_ptr == '\0') ? EOF : *iop->_ptr++) : \
68 #define wlocungetc(x) ((x == EOF) ? EOF : \
69 ((iop->_flag & _IOWRT) ? *(--iop->_ptr) : \
72 #define MAXARGS 30 /* max. number of args for fast positional paramters */
75 * stva_list is used to subvert C's restriction that a variable with an
76 * array type can not appear on the left hand side of an assignment operator.
77 * By putting the array inside a structure, the functionality of assigning to
78 * the whole array through a simple assignment is achieved..
80 typedef struct stva_list
{
84 static int number(int *, int *, int, int, int, int, FILE *, va_list *);
85 static int readchar(FILE *, int *);
86 static int string(int *, int *, int, int, int, char *, FILE *, va_list *);
87 static int wstring(int *, int *, int, int, int, FILE *, va_list *);
88 static int wbrstring(int *, int *, int, int, int, FILE *,
89 unsigned char *, va_list *);
91 static int brstring(int *, int *, int, int, int, FILE *,
92 unsigned char *, va_list *);
94 static int _bi_getwc(FILE *);
95 static int _bi_ungetwc(wint_t, FILE *);
98 static int _mkarglst(const wchar_t *, stva_list
, stva_list
[]);
99 static wint_t _wd_getwc(int *, FILE *);
100 static wint_t _wd_ungetwc(int *, wchar_t, FILE *);
101 static int _watoi(wchar_t *);
103 static int _mkarglst(const char *, stva_list
, stva_list
[]);
108 _doscan(FILE *iop
, const char *fmt
, va_list va_Alist
)
113 if (iop
->_flag
& _IOWRT
)
114 ret
= __doscan_u(iop
, fmt
, va_Alist
, 0);
117 ret
= __doscan_u(iop
, fmt
, va_Alist
, 0);
127 __wdoscan_u(FILE *iop
, const wchar_t *fmt
, va_list va_Alist
, int scflag
)
130 __doscan_u(FILE *iop
, const char *sfmt
, va_list va_Alist
, int scflag
)
135 wchar_t inchar
, size
;
136 int nmatch
= 0, len
, stow
;
139 int nmatch
= 0, len
, inchar
, stow
, size
;
142 unsigned char *bracket_str
= NULL
;
143 int chcount
, flag_eof
;
146 /* variables for postional parameters */
148 const wchar_t *sformat
= fmt
; /* save the beginning of the format */
150 const unsigned char *fmt
= (const unsigned char *)sfmt
;
151 const char *sformat
= sfmt
; /* save the beginning of the format */
153 int fpos
= 1; /* 1 if first postional parameter */
154 stva_list args
; /* used to step through the argument list */
155 stva_list sargs
; /* used to save start of the argument list */
156 stva_list arglst
[MAXARGS
];
158 * array giving the appropriate values
159 * for va_arg() to retrieve the
160 * corresponding argument:
161 * arglst[0] is the first argument
162 * arglst[1] is the second argument,etc.
164 /* Check if readable stream */
165 if (!(iop
->_flag
& (_IOREAD
| _IORW
))) {
171 * Initialize args and sargs to the start of the argument list.
172 * We don't know any portable way to copy an arbitrary C object
173 * so we use a system-specific routine(probably a macro) from
174 * stdarg.h. (Remember that if va_list is an array, in_args will
175 * be a pointer and &in_args won't be what we would want for
178 va_copy(args
.ap
, va_Alist
);
182 chcount
= 0; flag_eof
= 0;
185 * ****************************************************
186 * Main loop: reads format to determine a pattern,
187 * and then goes to read input stream
188 * in attempt to match the pattern.
189 * ****************************************************
192 if ((ch
= *fmt
++) == '\0') {
193 return (nmatch
); /* end of format */
198 while (iswspace(inchar
=
199 _wd_getwc(&chcount
, iop
)))
201 if (_wd_ungetwc(&chcount
, inchar
, iop
) == WEOF
)
206 if (ch
!= '%' || (ch
= *fmt
++) == '%') {
209 while (iswspace(inchar
=
210 _wd_getwc(&chcount
, iop
)))
212 if (_wd_ungetwc(&chcount
, inchar
, iop
)
217 if ((inchar
= _wd_getwc(&chcount
, iop
)) == ch
)
219 if (_wd_ungetwc(&chcount
, inchar
, iop
) != WEOF
) {
220 return (nmatch
); /* failed to match input */
227 while (isspace(inchar
= locgetc(chcount
)))
229 if (locungetc(chcount
, inchar
) == EOF
)
235 if (ch
!= '%' || (ch
= *fmt
++) == '%') {
238 while (isspace(inchar
=
241 if (locungetc(chcount
, inchar
) == EOF
)
245 if ((inchar
= locgetc(chcount
)) == ch
)
247 if (locungetc(chcount
, inchar
) != EOF
) {
248 return (nmatch
); /* failed to match input */
254 charswitch
: /* target of a goto 8-( */
263 for (len
= 0; ((ch
>= 0) && (ch
< 256) && isdigit(ch
));
265 len
= len
* 10 + ch
- '0';
267 for (len
= 0; isdigit(ch
); ch
= *fmt
++)
268 len
= len
* 10 + ch
- '0';
273 * positional parameter handling - the number
274 * specified in len gives the argument to which
275 * the next conversion should be applied.
276 * WARNING: This implementation of positional
277 * parameters assumes that the sizes of all pointer
278 * types are the same. (Code similar to that
279 * in the portable doprnt.c should be used if this
280 * assumption does not hold for a particular
284 if (_mkarglst(sformat
, sargs
, arglst
) != 0) {
290 if (len
<= MAXARGS
) {
291 args
= arglst
[len
- 1];
293 args
= arglst
[MAXARGS
- 1];
294 for (len
-= MAXARGS
; len
> 0; len
--)
295 (void) va_arg(args
.ap
, void *);
305 if ((size
= ch
) == 'l' || (size
== 'h') || (size
== 'L') ||
306 (size
== 'j') || (size
== 't') || (size
== 'z'))
309 if ((size
= ch
) == 'l' || (size
== 'h') || (size
== 'L') ||
310 (size
== 'w') || (size
== 'j') || (size
== 't') ||
314 if (size
== 'l' && ch
== 'l') {
315 size
= 'm'; /* size = 'm' if long long */
317 } else if (size
== 'h' && ch
== 'h') {
318 size
= 'b'; /* use size = 'b' if char */
320 } else if ((size
== 't') || (size
== 'z')) {
322 } else if (size
== 'j') {
324 /* check scflag for size of u/intmax_t (32-bit libc) */
325 if (!(scflag
& _F_INTMAX32
)) {
333 return (EOF
); /* unexpected end of format */
341 wchar_t *wbracket_str
;
344 /* p points to the address of '[' */
345 p
= (wchar_t *)fmt
- 1;
352 if (((c
= *fmt
) == ']') || (c
== '-')) {
356 while ((c
= *fmt
) != ']') {
358 return (EOF
); /* unexpected EOF */
366 wbracket_str
= (wchar_t *)
367 malloc(sizeof (wchar_t) * (len
+ 1));
368 if (wbracket_str
== NULL
) {
372 (void) wmemcpy(wbracket_str
,
373 (const wchar_t *)p
, len
);
374 *(wbracket_str
+ len
) = L
'\0';
375 if (negflg
&& *(wbracket_str
+ 1) == '^') {
376 *(wbracket_str
+ 1) = L
'!';
379 wlen
= wcslen(wbracket_str
);
380 clen
= wcstombs((char *)NULL
, wbracket_str
, 0);
381 if (clen
== (size_t)-1) {
385 bracket_str
= (unsigned char *)
386 malloc(sizeof (unsigned char) * (clen
+ 1));
387 if (bracket_str
== NULL
) {
392 clen
= wcstombs((char *)bracket_str
, wbracket_str
,
395 if (clen
== (size_t)-1) {
407 p
= (unsigned char *)(fmt
- 1);
414 if (((c
= *fmt
) == ']') || (c
== '-')) {
418 while ((c
= *fmt
) != ']') {
421 } else if (isascii(c
)) {
425 i
= mblen((const char *)fmt
,
437 bracket_str
= (unsigned char *)
438 malloc(sizeof (unsigned char) * (len
+ 1));
439 if (bracket_str
== NULL
) {
443 (void) strncpy((char *)bracket_str
,
444 (const char *)p
, len
);
445 *(bracket_str
+ len
) = '\0';
447 *(bracket_str
+ 1) == '^') {
448 *(bracket_str
+ 1) = '!';
459 (void) memset(tab
, !t
, NCHARS
);
460 if ((c
= *fmt
) == ']' || c
== '-') {
465 while ((c
= *fmt
) != ']') {
471 if ((c
== '-') && (d
!= ']') &&
473 (void) memset(&tab
[b
], t
,
487 if ((ch
>= 0) && (ch
< 256) &&
488 isupper((int)ch
)) { /* no longer documented */
489 if (_lib_version
== c_issue_4
) {
490 if (size
!= 'm' && size
!= 'L')
493 ch
= _tolower((int)ch
);
495 if (ch
!= 'n' && !flag_eof
) {
496 if (ch
!= 'c' && ch
!= 'C' && ch
!= '[') {
497 while (iswspace(inchar
=
498 _wd_getwc(&chcount
, iop
)))
500 if (_wd_ungetwc(&chcount
, inchar
, iop
) == WEOF
)
506 if (isupper(ch
)) { /* no longer documented */
507 if (_lib_version
== c_issue_4
) {
508 if (size
!= 'm' && size
!= 'L')
513 if (ch
!= 'n' && !flag_eof
) {
514 if (ch
!= 'c' && ch
!= 'C' && ch
!= '[') {
515 while (isspace(inchar
= locgetc(chcount
)))
517 if (locungetc(chcount
, inchar
) == EOF
)
529 if ((size
== 'l') || (size
== 'C') || (size
== 'S'))
531 if ((size
== 'w') || (size
== 'l') || (size
== 'C') ||
535 size
= wstring(&chcount
, &flag_eof
, stow
,
536 (int)ch
, len
, iop
, &args
.ap
);
538 size
= string(&chcount
, &flag_eof
, stow
,
539 (int)ch
, len
, tab
, iop
, &args
.ap
);
544 size
= wbrstring(&chcount
, &flag_eof
, stow
,
545 (int)ch
, len
, iop
, bracket_str
, &args
.ap
);
550 size
= brstring(&chcount
, &flag_eof
, stow
,
551 (int)ch
, len
, iop
, bracket_str
, &args
.ap
);
555 size
= string(&chcount
, &flag_eof
, stow
,
556 ch
, len
, tab
, iop
, &args
.ap
);
564 if (size
== 'b') /* char */
565 *va_arg(args
.ap
, char *) = (char)chcount
;
566 else if (size
== 'h')
567 *va_arg(args
.ap
, short *) = (short)chcount
;
568 else if (size
== 'l')
569 *va_arg(args
.ap
, long *) = (long)chcount
;
570 else if (size
== 'm') /* long long */
571 *va_arg(args
.ap
, long long *) =
574 *va_arg(args
.ap
, int *) = (int)chcount
;
579 size
= number(&chcount
, &flag_eof
, stow
, (int)ch
,
580 len
, (int)size
, iop
, &args
.ap
);
586 return ((flag_eof
&& !nmatch
) ? EOF
: nmatch
);
592 return (nmatch
!= 0 ? nmatch
: EOF
); /* end of input */
595 /* ****************************************************************** */
596 /* Functions to read the input stream in an attempt to match incoming */
597 /* data to the current pattern from the main loop of _doscan(). */
598 /* ****************************************************************** */
600 number(int *chcount
, int *flag_eof
, int stow
, int type
, int len
, int size
,
601 FILE *iop
, va_list *listp
)
605 int c
, base
, inchar
, lookahead
;
606 int digitseen
= 0, floater
= 0, negflg
= 0;
608 long long lcval
= 0LL;
615 * lc = 0 corresponds to c90 mode: do not recognize
616 * hexadecimal fp strings; attempt to push back
617 * all unused characters read
619 * lc = -1 corresponds to c99 mode: recognize hexa-
620 * decimal fp strings; push back at most one
623 lc
= (__xpg6
& _C99SUSv3_recognize_hexfp
)? -1 : 0;
642 size
= 'l'; /* pointers are long in LP64 */
649 return (0); /* unrecognized conversion character */
654 * Handle floating point with
659 fp_exception_field_type efs
;
660 enum decimal_string_form form
;
668 file_to_decimal(&nb
, len
, lc
, &dr
, &form
, &echar
, iop
, &nread
);
671 * In C99 mode, the entire string read has to be
672 * accepted in order to qualify as a match
674 if (nb
!= buffer
+ nread
)
677 if (stow
&& (form
!= invalid_form
)) {
680 if (size
== 'L') { /* long double */
682 __hex_to_quadruple(&dr
, dm
.rd
,
683 va_arg(*listp
, quadruple
*), &efs
);
685 decimal_to_quadruple(
686 va_arg(*listp
, quadruple
*),
689 #elif defined(__i386) || defined(__amd64)
691 if (size
== 'L') { /* long double */
693 __hex_to_extended(&dr
, dm
.rd
,
694 va_arg(*listp
, extended
*), &efs
);
697 va_arg(*listp
, extended
*),
701 #error Unknown architecture
703 else if (size
== 'l') { /* double */
705 __hex_to_double(&dr
, dm
.rd
,
706 va_arg(*listp
, double *), &efs
);
709 va_arg(*listp
, double *),
713 __hex_to_single(&dr
, dm
.rd
,
714 va_arg(*listp
, single
*), &efs
);
716 decimal_to_single((single
*)
717 va_arg(*listp
, single
*),
720 if ((efs
& (1 << fp_overflow
)) != 0) {
723 if ((efs
& (1 << fp_underflow
)) != 0) {
727 (*chcount
) += nread
; /* Count characters read. */
728 c
= locgetc((*chcount
));
729 if (locungetc((*chcount
), c
) == EOF
)
731 return ((form
== invalid_form
) ? 0 : 1);
732 /* successful match if non-zero */
735 switch (c
= locgetc((*chcount
))) {
742 if ((c
= locgetc((*chcount
))) != '0')
747 * If %i or %x, the characters 0x or 0X may optionally precede
748 * the sequence of letters and digits (base 16).
750 if ((type
!= 'i' && type
!= 'x') || (len
<= 1))
752 if (((inchar
= locgetc((*chcount
))) == 'x') ||
754 lookahead
= readchar(iop
, chcount
);
755 if (isxdigit(lookahead
)) {
759 (void) locungetc((*chcount
), lookahead
);
760 /* Take into account the 'x' */
764 /* Take into account '0x' */
768 (void) locungetc((*chcount
), lookahead
);
769 (void) locungetc((*chcount
), inchar
);
772 /* inchar wans't 'x'. */
773 (void) locungetc((*chcount
), inchar
); /* Put it back. */
774 if (type
== 'i') /* Only %i accepts an octal. */
778 for (; --len
>= 0; *np
++ = (char)c
, c
= locgetc((*chcount
))) {
779 if (np
> numbuf
+ 62) {
783 if (isdigit(c
) || base
== 16 && isxdigit(c
)) {
784 int digit
= c
- (isdigit(c
) ? '0' :
785 isupper(c
) ? 'A' - 10 : 'a' - 10);
789 lcval
= base
* lcval
+ digit
;
796 if (stow
&& digitseen
) {
797 /* suppress possible overflow on 2's-comp negation */
798 if (negflg
&& lcval
!= (1ULL << 63))
802 *va_arg(*listp
, long long *) = lcval
;
805 *va_arg(*listp
, long *) = (long)lcval
;
808 *va_arg(*listp
, short *) = (short)lcval
;
811 *va_arg(*listp
, char *) = (char)lcval
;
814 *va_arg(*listp
, int *) = (int)lcval
;
818 if (locungetc((*chcount
), c
) == EOF
)
820 return (digitseen
); /* successful match if non-zero */
823 /* Get a character. If not using sscanf and at the buffer's end */
824 /* then do a direct read(). Characters read via readchar() */
825 /* can be pushed back on the input stream by locungetc((*chcount),) */
826 /* since there is padding allocated at the end of the stream buffer. */
828 readchar(FILE *iop
, int *chcount
)
833 if ((iop
->_flag
& _IOWRT
) || (iop
->_cnt
!= 0))
834 inchar
= locgetc((*chcount
));
836 if (read(FILENO(iop
), buf
, 1) != 1)
838 inchar
= (int)buf
[0];
845 string(int *chcount
, int *flag_eof
, int stow
, int type
, int len
, char *tab
,
846 FILE *iop
, va_list *listp
)
852 start
= ptr
= stow
? va_arg(*listp
, char *) : NULL
;
853 if (((type
== 'c') || (type
== 'C')) && len
== MAXINT
)
856 while ((ch
= locgetc((*chcount
))) != EOF
&&
857 !(((type
== 's') || (type
== 'S')) && isspace(ch
))) {
859 while ((ch
= locgetc((*chcount
))) != EOF
&&
860 !(((type
== 's') || (type
== 'S')) &&
861 isspace(ch
) || type
== '[' && tab
[ch
])) {
872 } else if (len
> 0 && locungetc((*chcount
), ch
) == EOF
)
875 return (0); /* no match */
876 if (stow
&& ((type
!= 'c') && (type
!= 'C')))
878 return (1); /* successful match */
881 /* This function initializes arglst, to contain the appropriate */
882 /* va_list values for the first MAXARGS arguments. */
883 /* WARNING: this code assumes that the sizes of all pointer types */
884 /* are the same. (Code similar to that in the portable doprnt.c */
885 /* should be used if this assumption is not true for a */
886 /* particular port.) */
890 _mkarglst(const wchar_t *fmt
, stva_list args
, stva_list arglst
[])
893 _mkarglst(const char *fmt
, stva_list args
, stva_list arglst
[])
897 #define STRCHR wcschr
898 #define STRSPN wcsspn
899 #define ATOI(x) _watoi((wchar_t *)x)
900 #define SPNSTR1 L"01234567890"
901 #define SPNSTR2 L"# +-.0123456789hL$"
903 #define STRCHR strchr
904 #define STRSPN strspn
905 #define ATOI(x) atoi(x)
906 #define SPNSTR1 "01234567890"
907 #define SPNSTR2 "# +-.0123456789hL$"
910 int maxnum
, curargno
;
916 while ((fmt
= STRCHR(fmt
, '%')) != NULL
) {
918 if (*fmt
== '*' || *fmt
== '%')
920 if (fmt
[n
= STRSPN(fmt
, SPNSTR1
)] == L
'$') {
921 /* convert to zero base */
922 curargno
= ATOI(fmt
) - 1;
926 if (maxnum
< curargno
)
928 curargno
++; /* default to next in list */
930 fmt
+= STRSPN(fmt
, SPNSTR2
);
933 fmt
++; /* has to be at least on item in scan list */
937 while (*fmt
!= ']') {
939 return (-1); /* bad format */
945 } else if (isascii(*fmt
)) {
948 i
= mblen((const char *)
960 if (maxnum
> MAXARGS
)
962 for (n
= 0; n
<= maxnum
; n
++) {
964 (void) va_arg(args
.ap
, void *);
971 * For wide character handling
976 wstring(int *chcount
, int *flag_eof
, int stow
, int type
,
977 int len
, FILE *iop
, va_list *listp
)
984 wstart
= ptr
= stow
? va_arg(*listp
, wchar_t *) : NULL
;
986 if ((type
== 'c') && len
== MAXINT
)
988 while (((wch
= _wd_getwc(chcount
, iop
)) != WEOF
) &&
989 !(type
== 's' && iswspace(wch
))) {
1000 if (len
> 0 && _wd_ungetwc(chcount
, wch
, iop
) == WEOF
)
1004 return (0); /* no match */
1005 if (stow
&& (type
!= 'c'))
1007 return (1); /* successful match */
1012 wstring(int *chcount
, int *flag_eof
, int stow
, int type
, int len
, FILE *iop
,
1019 wstart
= ptr
= stow
? va_arg(*listp
, wchar_t *) : NULL
;
1021 if ((type
== 'c') && len
== MAXINT
)
1023 while (((wch
= _bi_getwc(iop
)) != EOF
) &&
1024 !(type
== 's' && (isascii(wch
) ? isspace(wch
) : 0))) {
1025 (*chcount
) += _scrwidth((wchar_t)wch
);
1036 if (len
> 0 && _bi_ungetwc(wch
, iop
) == EOF
)
1040 return (0); /* no match */
1041 if (stow
&& (type
!= 'c'))
1043 return (1); /* successful match */
1049 _wd_getwc(int *chcount
, FILE *iop
)
1054 if (!(iop
->_flag
& _IOWRT
)) {
1055 /* call from fwscanf, wscanf */
1056 wc
= __fgetwc_xpg5(iop
);
1060 /* call from swscanf */
1061 if (*iop
->_ptr
== '\0')
1063 len
= mbtowc((wchar_t *)&wc
, (const char *)iop
->_ptr
,
1074 _wd_ungetwc(int *chcount
, wchar_t wc
, FILE *iop
)
1078 char mbs
[MB_LEN_MAX
];
1083 if (!(iop
->_flag
& _IOWRT
)) {
1084 /* call from fwscanf, wscanf */
1085 ret
= __ungetwc_xpg5((wint_t)wc
, iop
);
1086 if (ret
!= (wint_t)wc
)
1091 /* call from swscanf */
1092 len
= wctomb(mbs
, wc
);
1097 return ((wint_t)wc
);
1102 _watoi(wchar_t *fmt
)
1108 if ((ch
>= 0) && (ch
< 256) && isdigit((int)ch
)) {
1110 while (((ch
= *++fmt
) >= 0) && (ch
< 256) &&
1122 wbrstring(int *chcount
, int *flag_eof
, int stow
, int type
,
1123 int len
, FILE *iop
, unsigned char *brstr
, va_list *listp
)
1127 char str
[MB_LEN_MAX
+ 1]; /* include null termination */
1128 wchar_t *ptr
, *start
;
1133 start
= ptr
= stow
? va_arg(*listp
, wchar_t *) : NULL
;
1136 while ((wch
= _wd_getwc(&dummy
, iop
)) != WEOF
) {
1138 while ((wch
= _bi_getwc(iop
)) != WEOF
) {
1140 i
= wctomb(str
, (wchar_t)wch
);
1145 if (fnmatch((const char *)brstr
, (const char *)str
,
1153 (*chcount
) += _scrwidth(wch
);
1171 if (len
> 0 && _wd_ungetwc(&dummy
, wch
, iop
) == WEOF
)
1173 if (len
> 0 && _bi_ungetwc(wch
, iop
) == WEOF
)
1178 return (0); /* no match */
1181 return (1); /* successful match */
1186 brstring(int *chcount
, int *flag_eof
, int stow
, int type
,
1187 int len
, FILE *iop
, unsigned char *brstr
, va_list *listp
)
1191 char str
[MB_LEN_MAX
+ 1]; /* include null termination */
1192 char *ptr
, *start
, *p
;
1195 start
= ptr
= stow
? va_arg(*listp
, char *) : NULL
;
1197 while ((wch
= _wd_getwc(&dummy
, iop
)) != WEOF
) {
1199 i
= wctomb(str
, (wchar_t)wch
);
1204 if (fnmatch((const char *)brstr
, (const char *)str
,
1230 if (len
> 0 && _wd_ungetwc(&dummy
, wch
, iop
) == WEOF
)
1234 return (0); /* no match */
1237 return (1); /* successful match */
1242 * Locally define getwc and ungetwc
1245 _bi_getwc(FILE *iop
)
1249 int i
, nbytes
, cur_max
;
1250 char buff
[MB_LEN_MAX
];
1252 if ((c
= wlocgetc()) == EOF
)
1255 if (isascii(c
)) /* ASCII code */
1260 cur_max
= (int)MB_CUR_MAX
;
1261 /* MB_CUR_MAX doen't exeed the value of MB_LEN_MAX */
1262 /* So we use MB_CUR_MAX instead of MB_LEN_MAX for */
1263 /* improving the performance. */
1264 for (i
= 1; i
< cur_max
; i
++) {
1267 (void) wlocungetc(c
);
1271 /* this still may be a valid multibyte character */
1277 if ((nbytes
= mbtowc(&intcode
, buff
, i
)) == -1) {
1279 * If mbtowc fails, the input was not a legal character.
1280 * ungetc all but one character.
1282 * Note: the number of pushback characters that
1283 * ungetc() can handle must be >= (MB_LEN_MAX - 1).
1284 * In Solaris 2.x, the number of pushback
1288 (void) wlocungetc((signed char)buff
[i
]);
1291 return (WEOF
); /* Illegal EUC sequence. */
1294 while (i
-- > nbytes
) {
1296 * Note: the number of pushback characters that
1297 * ungetc() can handle must be >= (MB_LEN_MAX - 1).
1298 * In Solaris 2.x, the number of pushback
1301 (void) wlocungetc((signed char)buff
[i
]);
1303 return ((int)intcode
);
1307 _bi_ungetwc(wint_t wc
, FILE *iop
)
1309 char mbs
[MB_LEN_MAX
];
1313 if ((wc
== WEOF
) || ((iop
->_flag
& _IOREAD
) == 0))
1316 n
= wctomb(mbs
, (wchar_t)wc
);
1320 if (iop
->_ptr
<= iop
->_base
) {
1321 if (iop
->_base
== NULL
) {
1324 if ((iop
->_ptr
== iop
->_base
) && (iop
->_cnt
== 0)) {
1326 } else if ((iop
->_ptr
- n
) < (iop
->_base
- PUSHBACK
)) {
1331 p
= (unsigned char *)(mbs
+n
-1); /* p points the last byte */
1332 /* if _IOWRT is set to iop->_flag, it means this is */
1333 /* an invocation from sscanf(), and in that time we */
1334 /* don't touch iop->_cnt. Otherwise, which means an */
1335 /* invocation from fscanf() or scanf(), we touch iop->_cnt */
1336 if ((iop
->_flag
& _IOWRT
) == 0) {
1337 /* scanf() and fscanf() */
1340 *--iop
->_ptr
= *(p
--);