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 */
31 #include <sys/types.h>
53 #define NCHARS (1 << BITSPERBYTE)
55 /* if the _IOWRT flag is set, this must be a call from sscanf */
56 #define locgetc(cnt) (cnt += 1, (iop->_flag & _IOWRT) ? \
57 ((*iop->_ptr == '\0') ? EOF : *iop->_ptr++) : \
59 #define locungetc(cnt, x) (cnt -= 1, (x == EOF) ? EOF : \
60 ((iop->_flag & _IOWRT) ? *(--iop->_ptr) : \
61 (++iop->_cnt, *(--iop->_ptr))))
63 #define wlocgetc() ((iop->_flag & _IOWRT) ? \
64 ((*iop->_ptr == '\0') ? EOF : *iop->_ptr++) : \
66 #define wlocungetc(x) ((x == EOF) ? EOF : \
67 ((iop->_flag & _IOWRT) ? *(--iop->_ptr) : \
70 #define MAXARGS 30 /* max. number of args for fast positional paramters */
73 * stva_list is used to subvert C's restriction that a variable with an
74 * array type can not appear on the left hand side of an assignment operator.
75 * By putting the array inside a structure, the functionality of assigning to
76 * the whole array through a simple assignment is achieved..
78 typedef struct stva_list
{
82 static int number(int *, int *, int, int, int, int, FILE *, va_list *);
83 static int readchar(FILE *, int *);
84 static int string(int *, int *, int, int, int, char *, FILE *, va_list *);
85 static int wstring(int *, int *, int, int, int, FILE *, va_list *);
86 static int wbrstring(int *, int *, int, int, int, FILE *,
87 unsigned char *, va_list *);
89 static int brstring(int *, int *, int, int, int, FILE *,
90 unsigned char *, va_list *);
92 static int _bi_getwc(FILE *);
93 static int _bi_ungetwc(wint_t, FILE *);
96 static int _mkarglst(const wchar_t *, stva_list
, stva_list
[]);
97 static wint_t _wd_getwc(int *, FILE *);
98 static wint_t _wd_ungetwc(int *, wchar_t, FILE *);
99 static int _watoi(wchar_t *);
101 static int _mkarglst(const char *, stva_list
, stva_list
[]);
106 _doscan(FILE *iop
, const char *fmt
, va_list va_Alist
)
111 if (iop
->_flag
& _IOWRT
)
112 ret
= __doscan_u(iop
, fmt
, va_Alist
, 0);
115 ret
= __doscan_u(iop
, fmt
, va_Alist
, 0);
125 __wdoscan_u(FILE *iop
, const wchar_t *fmt
, va_list va_Alist
, int scflag
)
128 __doscan_u(FILE *iop
, const char *sfmt
, va_list va_Alist
, int scflag
)
133 wchar_t inchar
, size
;
134 int nmatch
= 0, len
, stow
;
137 int nmatch
= 0, len
, inchar
, stow
, size
;
140 unsigned char *bracket_str
= NULL
;
141 int chcount
, flag_eof
;
144 /* variables for postional parameters */
146 const wchar_t *sformat
= fmt
; /* save the beginning of the format */
148 const unsigned char *fmt
= (const unsigned char *)sfmt
;
149 const char *sformat
= sfmt
; /* save the beginning of the format */
151 int fpos
= 1; /* 1 if first postional parameter */
152 stva_list args
; /* used to step through the argument list */
153 stva_list sargs
; /* used to save start of the argument list */
154 stva_list arglst
[MAXARGS
];
156 * array giving the appropriate values
157 * for va_arg() to retrieve the
158 * corresponding argument:
159 * arglst[0] is the first argument
160 * arglst[1] is the second argument,etc.
162 /* Check if readable stream */
163 if (!(iop
->_flag
& (_IOREAD
| _IORW
))) {
169 * Initialize args and sargs to the start of the argument list.
170 * We don't know any portable way to copy an arbitrary C object
171 * so we use a system-specific routine(probably a macro) from
172 * stdarg.h. (Remember that if va_list is an array, in_args will
173 * be a pointer and &in_args won't be what we would want for
176 va_copy(args
.ap
, va_Alist
);
180 chcount
= 0; flag_eof
= 0;
183 * ****************************************************
184 * Main loop: reads format to determine a pattern,
185 * and then goes to read input stream
186 * in attempt to match the pattern.
187 * ****************************************************
190 if ((ch
= *fmt
++) == '\0') {
191 return (nmatch
); /* end of format */
196 while (iswspace(inchar
=
197 _wd_getwc(&chcount
, iop
)))
199 if (_wd_ungetwc(&chcount
, inchar
, iop
) == WEOF
)
204 if (ch
!= '%' || (ch
= *fmt
++) == '%') {
207 while (iswspace(inchar
=
208 _wd_getwc(&chcount
, iop
)))
210 if (_wd_ungetwc(&chcount
, inchar
, iop
)
215 if ((inchar
= _wd_getwc(&chcount
, iop
)) == ch
)
217 if (_wd_ungetwc(&chcount
, inchar
, iop
) != WEOF
) {
218 return (nmatch
); /* failed to match input */
225 while (isspace(inchar
= locgetc(chcount
)))
227 if (locungetc(chcount
, inchar
) == EOF
)
233 if (ch
!= '%' || (ch
= *fmt
++) == '%') {
236 while (isspace(inchar
=
239 if (locungetc(chcount
, inchar
) == EOF
)
243 if ((inchar
= locgetc(chcount
)) == ch
)
245 if (locungetc(chcount
, inchar
) != EOF
) {
246 return (nmatch
); /* failed to match input */
252 charswitch
: /* target of a goto 8-( */
261 for (len
= 0; ((ch
>= 0) && (ch
< 256) && isdigit(ch
));
263 len
= len
* 10 + ch
- '0';
265 for (len
= 0; isdigit(ch
); ch
= *fmt
++)
266 len
= len
* 10 + ch
- '0';
271 * positional parameter handling - the number
272 * specified in len gives the argument to which
273 * the next conversion should be applied.
274 * WARNING: This implementation of positional
275 * parameters assumes that the sizes of all pointer
276 * types are the same. (Code similar to that
277 * in the portable doprnt.c should be used if this
278 * assumption does not hold for a particular
282 if (_mkarglst(sformat
, sargs
, arglst
) != 0) {
288 if (len
<= MAXARGS
) {
289 args
= arglst
[len
- 1];
291 args
= arglst
[MAXARGS
- 1];
292 for (len
-= MAXARGS
; len
> 0; len
--)
293 (void) va_arg(args
.ap
, void *);
303 if ((size
= ch
) == 'l' || (size
== 'h') || (size
== 'L') ||
304 (size
== 'j') || (size
== 't') || (size
== 'z'))
307 if ((size
= ch
) == 'l' || (size
== 'h') || (size
== 'L') ||
308 (size
== 'w') || (size
== 'j') || (size
== 't') ||
312 if (size
== 'l' && ch
== 'l') {
313 size
= 'm'; /* size = 'm' if long long */
315 } else if (size
== 'h' && ch
== 'h') {
316 size
= 'b'; /* use size = 'b' if char */
318 } else if ((size
== 't') || (size
== 'z')) {
320 } else if (size
== 'j') {
322 /* check scflag for size of u/intmax_t (32-bit libc) */
323 if (!(scflag
& _F_INTMAX32
)) {
331 return (EOF
); /* unexpected end of format */
339 wchar_t *wbracket_str
;
342 /* p points to the address of '[' */
343 p
= (wchar_t *)fmt
- 1;
350 if (((c
= *fmt
) == ']') || (c
== '-')) {
354 while ((c
= *fmt
) != ']') {
356 return (EOF
); /* unexpected EOF */
364 wbracket_str
= (wchar_t *)
365 malloc(sizeof (wchar_t) * (len
+ 1));
366 if (wbracket_str
== NULL
) {
370 (void) wmemcpy(wbracket_str
,
371 (const wchar_t *)p
, len
);
372 *(wbracket_str
+ len
) = L
'\0';
373 if (negflg
&& *(wbracket_str
+ 1) == '^') {
374 *(wbracket_str
+ 1) = L
'!';
377 wlen
= wcslen(wbracket_str
);
378 clen
= wcstombs(NULL
, wbracket_str
, 0);
379 if (clen
== (size_t)-1) {
383 bracket_str
= (unsigned char *)
384 malloc(sizeof (unsigned char) * (clen
+ 1));
385 if (bracket_str
== NULL
) {
390 clen
= wcstombs((char *)bracket_str
, wbracket_str
,
393 if (clen
== (size_t)-1) {
405 p
= (unsigned char *)(fmt
- 1);
412 if (((c
= *fmt
) == ']') || (c
== '-')) {
416 while ((c
= *fmt
) != ']') {
419 } else if (isascii(c
)) {
423 i
= mblen((const char *)fmt
,
435 bracket_str
= (unsigned char *)
436 malloc(sizeof (unsigned char) * (len
+ 1));
437 if (bracket_str
== NULL
) {
441 (void) strncpy((char *)bracket_str
,
442 (const char *)p
, len
);
443 *(bracket_str
+ len
) = '\0';
445 *(bracket_str
+ 1) == '^') {
446 *(bracket_str
+ 1) = '!';
457 (void) memset(tab
, !t
, NCHARS
);
458 if ((c
= *fmt
) == ']' || c
== '-') {
463 while ((c
= *fmt
) != ']') {
469 if ((c
== '-') && (d
!= ']') &&
471 (void) memset(&tab
[b
], t
,
485 if ((ch
>= 0) && (ch
< 256) &&
486 isupper((int)ch
)) { /* no longer documented */
487 if (_lib_version
== c_issue_4
) {
488 if (size
!= 'm' && size
!= 'L')
491 ch
= _tolower((int)ch
);
493 if (ch
!= 'n' && !flag_eof
) {
494 if (ch
!= 'c' && ch
!= 'C' && ch
!= '[') {
495 while (iswspace(inchar
=
496 _wd_getwc(&chcount
, iop
)))
498 if (_wd_ungetwc(&chcount
, inchar
, iop
) == WEOF
)
504 if (isupper(ch
)) { /* no longer documented */
505 if (_lib_version
== c_issue_4
) {
506 if (size
!= 'm' && size
!= 'L')
511 if (ch
!= 'n' && !flag_eof
) {
512 if (ch
!= 'c' && ch
!= 'C' && ch
!= '[') {
513 while (isspace(inchar
= locgetc(chcount
)))
515 if (locungetc(chcount
, inchar
) == EOF
)
527 if ((size
== 'l') || (size
== 'C') || (size
== 'S'))
529 if ((size
== 'w') || (size
== 'l') || (size
== 'C') ||
533 size
= wstring(&chcount
, &flag_eof
, stow
,
534 (int)ch
, len
, iop
, &args
.ap
);
536 size
= string(&chcount
, &flag_eof
, stow
,
537 (int)ch
, len
, tab
, iop
, &args
.ap
);
542 size
= wbrstring(&chcount
, &flag_eof
, stow
,
543 (int)ch
, len
, iop
, bracket_str
, &args
.ap
);
548 size
= brstring(&chcount
, &flag_eof
, stow
,
549 (int)ch
, len
, iop
, bracket_str
, &args
.ap
);
553 size
= string(&chcount
, &flag_eof
, stow
,
554 ch
, len
, tab
, iop
, &args
.ap
);
562 if (size
== 'b') /* char */
563 *va_arg(args
.ap
, char *) = (char)chcount
;
564 else if (size
== 'h')
565 *va_arg(args
.ap
, short *) = (short)chcount
;
566 else if (size
== 'l')
567 *va_arg(args
.ap
, long *) = (long)chcount
;
568 else if (size
== 'm') /* long long */
569 *va_arg(args
.ap
, long long *) =
572 *va_arg(args
.ap
, int *) = (int)chcount
;
577 size
= number(&chcount
, &flag_eof
, stow
, (int)ch
,
578 len
, (int)size
, iop
, &args
.ap
);
584 return ((flag_eof
&& !nmatch
) ? EOF
: nmatch
);
589 return (nmatch
!= 0 ? nmatch
: EOF
); /* end of input */
592 /* ****************************************************************** */
593 /* Functions to read the input stream in an attempt to match incoming */
594 /* data to the current pattern from the main loop of _doscan(). */
595 /* ****************************************************************** */
597 number(int *chcount
, int *flag_eof
, int stow
, int type
, int len
, int size
,
598 FILE *iop
, va_list *listp
)
602 int c
, base
, inchar
, lookahead
;
603 int digitseen
= 0, floater
= 0, negflg
= 0;
605 long long lcval
= 0LL;
612 * lc = 0 corresponds to c90 mode: do not recognize
613 * hexadecimal fp strings; attempt to push back
614 * all unused characters read
616 * lc = -1 corresponds to c99 mode: recognize hexa-
617 * decimal fp strings; push back at most one
620 lc
= (__xpg6
& _C99SUSv3_recognize_hexfp
)? -1 : 0;
639 size
= 'l'; /* pointers are long in LP64 */
646 return (0); /* unrecognized conversion character */
651 * Handle floating point with
656 fp_exception_field_type efs
;
657 enum decimal_string_form form
;
665 file_to_decimal(&nb
, len
, lc
, &dr
, &form
, &echar
, iop
, &nread
);
668 * In C99 mode, the entire string read has to be
669 * accepted in order to qualify as a match
671 if (nb
!= buffer
+ nread
)
674 if (stow
&& (form
!= invalid_form
)) {
677 if (size
== 'L') { /* long double */
679 __hex_to_quadruple(&dr
, dm
.rd
,
680 va_arg(*listp
, quadruple
*), &efs
);
682 decimal_to_quadruple(
683 va_arg(*listp
, quadruple
*),
686 #elif defined(__i386) || defined(__amd64)
688 if (size
== 'L') { /* long double */
690 __hex_to_extended(&dr
, dm
.rd
,
691 va_arg(*listp
, extended
*), &efs
);
694 va_arg(*listp
, extended
*),
698 #error Unknown architecture
700 else if (size
== 'l') { /* double */
702 __hex_to_double(&dr
, dm
.rd
,
703 va_arg(*listp
, double *), &efs
);
706 va_arg(*listp
, double *),
710 __hex_to_single(&dr
, dm
.rd
,
711 va_arg(*listp
, single
*), &efs
);
713 decimal_to_single((single
*)
714 va_arg(*listp
, single
*),
717 if ((efs
& (1 << fp_overflow
)) != 0) {
720 if ((efs
& (1 << fp_underflow
)) != 0) {
724 (*chcount
) += nread
; /* Count characters read. */
725 c
= locgetc((*chcount
));
726 if (locungetc((*chcount
), c
) == EOF
)
728 return ((form
== invalid_form
) ? 0 : 1);
729 /* successful match if non-zero */
732 switch (c
= locgetc((*chcount
))) {
739 if ((c
= locgetc((*chcount
))) != '0')
744 * If %i or %x, the characters 0x or 0X may optionally precede
745 * the sequence of letters and digits (base 16).
747 if ((type
!= 'i' && type
!= 'x') || (len
<= 1))
749 if (((inchar
= locgetc((*chcount
))) == 'x') ||
751 lookahead
= readchar(iop
, chcount
);
752 if (isxdigit(lookahead
)) {
756 (void) locungetc((*chcount
), lookahead
);
757 /* Take into account the 'x' */
761 /* Take into account '0x' */
765 (void) locungetc((*chcount
), lookahead
);
766 (void) locungetc((*chcount
), inchar
);
769 /* inchar wans't 'x'. */
770 (void) locungetc((*chcount
), inchar
); /* Put it back. */
771 if (type
== 'i') /* Only %i accepts an octal. */
775 for (; --len
>= 0; *np
++ = (char)c
, c
= locgetc((*chcount
))) {
776 if (np
> numbuf
+ 62) {
780 if (isdigit(c
) || base
== 16 && isxdigit(c
)) {
781 int digit
= c
- (isdigit(c
) ? '0' :
782 isupper(c
) ? 'A' - 10 : 'a' - 10);
786 lcval
= base
* lcval
+ digit
;
793 if (stow
&& digitseen
) {
794 /* suppress possible overflow on 2's-comp negation */
795 if (negflg
&& lcval
!= (1ULL << 63))
799 *va_arg(*listp
, long long *) = lcval
;
802 *va_arg(*listp
, long *) = (long)lcval
;
805 *va_arg(*listp
, short *) = (short)lcval
;
808 *va_arg(*listp
, char *) = (char)lcval
;
811 *va_arg(*listp
, int *) = (int)lcval
;
815 if (locungetc((*chcount
), c
) == EOF
)
817 return (digitseen
); /* successful match if non-zero */
820 /* Get a character. If not using sscanf and at the buffer's end */
821 /* then do a direct read(). Characters read via readchar() */
822 /* can be pushed back on the input stream by locungetc((*chcount),) */
823 /* since there is padding allocated at the end of the stream buffer. */
825 readchar(FILE *iop
, int *chcount
)
830 if ((iop
->_flag
& _IOWRT
) || (iop
->_cnt
!= 0))
831 inchar
= locgetc((*chcount
));
833 if (read(FILENO(iop
), buf
, 1) != 1)
835 inchar
= (int)buf
[0];
842 string(int *chcount
, int *flag_eof
, int stow
, int type
, int len
, char *tab
,
843 FILE *iop
, va_list *listp
)
849 start
= ptr
= stow
? va_arg(*listp
, char *) : NULL
;
850 if (((type
== 'c') || (type
== 'C')) && len
== MAXINT
)
853 while ((ch
= locgetc((*chcount
))) != EOF
&&
854 !(((type
== 's') || (type
== 'S')) && isspace(ch
))) {
856 while ((ch
= locgetc((*chcount
))) != EOF
&&
857 !(((type
== 's') || (type
== 'S')) &&
858 isspace(ch
) || type
== '[' && tab
[ch
])) {
869 } else if (len
> 0 && locungetc((*chcount
), ch
) == EOF
)
872 return (0); /* no match */
873 if (stow
&& ((type
!= 'c') && (type
!= 'C')))
875 return (1); /* successful match */
878 /* This function initializes arglst, to contain the appropriate */
879 /* va_list values for the first MAXARGS arguments. */
880 /* WARNING: this code assumes that the sizes of all pointer types */
881 /* are the same. (Code similar to that in the portable doprnt.c */
882 /* should be used if this assumption is not true for a */
883 /* particular port.) */
887 _mkarglst(const wchar_t *fmt
, stva_list args
, stva_list arglst
[])
890 _mkarglst(const char *fmt
, stva_list args
, stva_list arglst
[])
894 #define STRCHR wcschr
895 #define STRSPN wcsspn
896 #define ATOI(x) _watoi((wchar_t *)x)
897 #define SPNSTR1 L"01234567890"
898 #define SPNSTR2 L"# +-.0123456789hL$"
900 #define STRCHR strchr
901 #define STRSPN strspn
902 #define ATOI(x) atoi(x)
903 #define SPNSTR1 "01234567890"
904 #define SPNSTR2 "# +-.0123456789hL$"
907 int maxnum
, curargno
;
913 while ((fmt
= STRCHR(fmt
, '%')) != NULL
) {
915 if (*fmt
== '*' || *fmt
== '%')
917 if (fmt
[n
= STRSPN(fmt
, SPNSTR1
)] == L
'$') {
918 /* convert to zero base */
919 curargno
= ATOI(fmt
) - 1;
923 if (maxnum
< curargno
)
925 curargno
++; /* default to next in list */
927 fmt
+= STRSPN(fmt
, SPNSTR2
);
930 fmt
++; /* has to be at least on item in scan list */
934 while (*fmt
!= ']') {
936 return (-1); /* bad format */
942 } else if (isascii(*fmt
)) {
945 i
= mblen((const char *)
957 if (maxnum
> MAXARGS
)
959 for (n
= 0; n
<= maxnum
; n
++) {
961 (void) va_arg(args
.ap
, void *);
968 * For wide character handling
973 wstring(int *chcount
, int *flag_eof
, int stow
, int type
,
974 int len
, FILE *iop
, va_list *listp
)
981 wstart
= ptr
= stow
? va_arg(*listp
, wchar_t *) : NULL
;
983 if ((type
== 'c') && len
== MAXINT
)
985 while (((wch
= _wd_getwc(chcount
, iop
)) != WEOF
) &&
986 !(type
== 's' && iswspace(wch
))) {
997 if (len
> 0 && _wd_ungetwc(chcount
, wch
, iop
) == WEOF
)
1001 return (0); /* no match */
1002 if (stow
&& (type
!= 'c'))
1004 return (1); /* successful match */
1009 wstring(int *chcount
, int *flag_eof
, int stow
, int type
, int len
, FILE *iop
,
1016 wstart
= ptr
= stow
? va_arg(*listp
, wchar_t *) : NULL
;
1018 if ((type
== 'c') && len
== MAXINT
)
1020 while (((wch
= _bi_getwc(iop
)) != EOF
) &&
1021 !(type
== 's' && (isascii(wch
) ? isspace(wch
) : 0))) {
1022 (*chcount
) += _scrwidth((wchar_t)wch
);
1033 if (len
> 0 && _bi_ungetwc(wch
, iop
) == EOF
)
1037 return (0); /* no match */
1038 if (stow
&& (type
!= 'c'))
1040 return (1); /* successful match */
1046 _wd_getwc(int *chcount
, FILE *iop
)
1051 if (!(iop
->_flag
& _IOWRT
)) {
1052 /* call from fwscanf, wscanf */
1053 wc
= __fgetwc_xpg5(iop
);
1057 /* call from swscanf */
1058 if (*iop
->_ptr
== '\0')
1060 len
= mbtowc((wchar_t *)&wc
, (const char *)iop
->_ptr
,
1071 _wd_ungetwc(int *chcount
, wchar_t wc
, FILE *iop
)
1075 char mbs
[MB_LEN_MAX
];
1080 if (!(iop
->_flag
& _IOWRT
)) {
1081 /* call from fwscanf, wscanf */
1082 ret
= __ungetwc_xpg5((wint_t)wc
, iop
);
1083 if (ret
!= (wint_t)wc
)
1088 /* call from swscanf */
1089 len
= wctomb(mbs
, wc
);
1094 return ((wint_t)wc
);
1099 _watoi(wchar_t *fmt
)
1105 if ((ch
>= 0) && (ch
< 256) && isdigit((int)ch
)) {
1107 while (((ch
= *++fmt
) >= 0) && (ch
< 256) &&
1119 wbrstring(int *chcount
, int *flag_eof
, int stow
, int type
,
1120 int len
, FILE *iop
, unsigned char *brstr
, va_list *listp
)
1124 char str
[MB_LEN_MAX
+ 1]; /* include null termination */
1125 wchar_t *ptr
, *start
;
1130 start
= ptr
= stow
? va_arg(*listp
, wchar_t *) : NULL
;
1133 while ((wch
= _wd_getwc(&dummy
, iop
)) != WEOF
) {
1135 while ((wch
= _bi_getwc(iop
)) != WEOF
) {
1137 i
= wctomb(str
, (wchar_t)wch
);
1142 if (fnmatch((const char *)brstr
, (const char *)str
,
1150 (*chcount
) += _scrwidth(wch
);
1168 if (len
> 0 && _wd_ungetwc(&dummy
, wch
, iop
) == WEOF
)
1170 if (len
> 0 && _bi_ungetwc(wch
, iop
) == WEOF
)
1175 return (0); /* no match */
1178 return (1); /* successful match */
1183 brstring(int *chcount
, int *flag_eof
, int stow
, int type
,
1184 int len
, FILE *iop
, unsigned char *brstr
, va_list *listp
)
1188 char str
[MB_LEN_MAX
+ 1]; /* include null termination */
1189 char *ptr
, *start
, *p
;
1192 start
= ptr
= stow
? va_arg(*listp
, char *) : NULL
;
1194 while ((wch
= _wd_getwc(&dummy
, iop
)) != WEOF
) {
1196 i
= wctomb(str
, (wchar_t)wch
);
1201 if (fnmatch((const char *)brstr
, (const char *)str
,
1227 if (len
> 0 && _wd_ungetwc(&dummy
, wch
, iop
) == WEOF
)
1231 return (0); /* no match */
1234 return (1); /* successful match */
1239 * Locally define getwc and ungetwc
1242 _bi_getwc(FILE *iop
)
1246 int i
, nbytes
, cur_max
;
1247 char buff
[MB_LEN_MAX
];
1249 if ((c
= wlocgetc()) == EOF
)
1252 if (isascii(c
)) /* ASCII code */
1257 cur_max
= (int)MB_CUR_MAX
;
1258 /* MB_CUR_MAX doen't exeed the value of MB_LEN_MAX */
1259 /* So we use MB_CUR_MAX instead of MB_LEN_MAX for */
1260 /* improving the performance. */
1261 for (i
= 1; i
< cur_max
; i
++) {
1264 (void) wlocungetc(c
);
1268 /* this still may be a valid multibyte character */
1274 if ((nbytes
= mbtowc(&intcode
, buff
, i
)) == -1) {
1276 * If mbtowc fails, the input was not a legal character.
1277 * ungetc all but one character.
1279 * Note: the number of pushback characters that
1280 * ungetc() can handle must be >= (MB_LEN_MAX - 1).
1281 * In Solaris 2.x, the number of pushback
1285 (void) wlocungetc((signed char)buff
[i
]);
1288 return (WEOF
); /* Illegal EUC sequence. */
1291 while (i
-- > nbytes
) {
1293 * Note: the number of pushback characters that
1294 * ungetc() can handle must be >= (MB_LEN_MAX - 1).
1295 * In Solaris 2.x, the number of pushback
1298 (void) wlocungetc((signed char)buff
[i
]);
1300 return ((int)intcode
);
1304 _bi_ungetwc(wint_t wc
, FILE *iop
)
1306 char mbs
[MB_LEN_MAX
];
1310 if ((wc
== WEOF
) || ((iop
->_flag
& _IOREAD
) == 0))
1313 n
= wctomb(mbs
, (wchar_t)wc
);
1317 if (iop
->_ptr
<= iop
->_base
) {
1318 if (iop
->_base
== NULL
) {
1321 if ((iop
->_ptr
== iop
->_base
) && (iop
->_cnt
== 0)) {
1323 } else if ((iop
->_ptr
- n
) < (iop
->_base
- PUSHBACK
)) {
1328 p
= (unsigned char *)(mbs
+n
-1); /* p points the last byte */
1329 /* if _IOWRT is set to iop->_flag, it means this is */
1330 /* an invocation from sscanf(), and in that time we */
1331 /* don't touch iop->_cnt. Otherwise, which means an */
1332 /* invocation from fscanf() or scanf(), we touch iop->_cnt */
1333 if ((iop
->_flag
& _IOWRT
) == 0) {
1334 /* scanf() and fscanf() */
1337 *--iop
->_ptr
= *(p
--);