#include "lint.h"
#include <sys/types.h>
#include "mtlib.h"
#include "file64.h"
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#include <values.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <thread.h>
#include <synch.h>
#include <stdlib.h>
#include <fnmatch.h>
#include <limits.h>
#include <wchar.h>
#include <unistd.h>
#include "libc.h"
#include "stdiom.h"
#include "xpg6.h"
#define NCHARS (1 << BITSPERBYTE)
#define locgetc(cnt) (cnt += 1, (iop->_flag & _IOWRT) ? \
((*iop->_ptr == '\0') ? EOF : *iop->_ptr++) : \
GETC(iop))
#define locungetc(cnt, x) (cnt -= 1, (x == EOF) ? EOF : \
((iop->_flag & _IOWRT) ? *(--iop->_ptr) : \
(++iop->_cnt, *(--iop->_ptr))))
#define wlocgetc() ((iop->_flag & _IOWRT) ? \
((*iop->_ptr == '\0') ? EOF : *iop->_ptr++) : \
GETC(iop))
#define wlocungetc(x) ((x == EOF) ? EOF : \
((iop->_flag & _IOWRT) ? *(--iop->_ptr) : \
UNGETC(x, iop)))
#define MAXARGS 30
typedef struct stva_list {
va_list ap;
} stva_list;
static int number(int *, int *, int, int, int, int, FILE *, va_list *);
static int readchar(FILE *, int *);
static int string(int *, int *, int, int, int, char *, FILE *, va_list *);
static int wstring(int *, int *, int, int, int, FILE *, va_list *);
static int wbrstring(int *, int *, int, int, int, FILE *,
unsigned char *, va_list *);
#ifdef _WIDE
static int brstring(int *, int *, int, int, int, FILE *,
unsigned char *, va_list *);
#endif
static int _bi_getwc(FILE *);
static int _bi_ungetwc(wint_t, FILE *);
#ifdef _WIDE
static int _mkarglst(const wchar_t *, stva_list, stva_list[]);
static wint_t _wd_getwc(int *, FILE *);
static wint_t _wd_ungetwc(int *, wchar_t, FILE *);
static int _watoi(wchar_t *);
#else
static int _mkarglst(const char *, stva_list, stva_list[]);
#endif
#ifndef _WIDE
int
_doscan(FILE *iop, const char *fmt, va_list va_Alist)
{
int ret;
rmutex_t *lk;
if (iop->_flag & _IOWRT)
ret = __doscan_u(iop, fmt, va_Alist, 0);
else {
FLOCKFILE(lk, iop);
ret = __doscan_u(iop, fmt, va_Alist, 0);
FUNLOCKFILE(lk);
}
return (ret);
}
#endif
#ifdef _WIDE
int
__wdoscan_u(FILE *iop, const wchar_t *fmt, va_list va_Alist,
int scflag __unused)
#else
int
__doscan_u(FILE *iop, const char *sfmt, va_list va_Alist, int scflag __unused)
#endif
{
#ifdef _WIDE
wchar_t ch;
wchar_t inchar, size;
int nmatch = 0, len, stow;
#else
int ch;
int nmatch = 0, len, inchar, stow, size;
#endif
unsigned char *bracket_str = NULL;
int chcount, flag_eof;
char tab[NCHARS];
#ifdef _WIDE
const wchar_t *sformat = fmt;
#else
const unsigned char *fmt = (const unsigned char *)sfmt;
const char *sformat = sfmt;
#endif
int fpos = 1;
stva_list args;
stva_list sargs;
stva_list arglst[MAXARGS];
if (!(iop->_flag & (_IOREAD | _IORW))) {
errno = EBADF;
return (EOF);
}
va_copy(args.ap, va_Alist);
sargs = args;
chcount = 0; flag_eof = 0;
for (; ; ) {
if ((ch = *fmt++) == '\0') {
return (nmatch);
}
#ifdef _WIDE
if (iswspace(ch)) {
if (!flag_eof) {
while (iswspace(inchar =
_wd_getwc(&chcount, iop)))
;
if (_wd_ungetwc(&chcount, inchar, iop) == WEOF)
flag_eof = 1;
}
continue;
}
if (ch != '%' || (ch = *fmt++) == '%') {
if (ch == '%') {
if (!flag_eof) {
while (iswspace(inchar =
_wd_getwc(&chcount, iop)))
;
if (_wd_ungetwc(&chcount, inchar, iop)
== WEOF)
flag_eof = 1;
}
}
if ((inchar = _wd_getwc(&chcount, iop)) == ch)
continue;
if (_wd_ungetwc(&chcount, inchar, iop) != WEOF) {
return (nmatch);
}
break;
}
#else
if (isspace(ch)) {
if (!flag_eof) {
while (isspace(inchar = locgetc(chcount)))
;
if (locungetc(chcount, inchar) == EOF)
flag_eof = 1;
}
continue;
}
if (ch != '%' || (ch = *fmt++) == '%') {
if (ch == '%') {
if (!flag_eof) {
while (isspace(inchar =
locgetc(chcount)))
;
if (locungetc(chcount, inchar) == EOF)
flag_eof = 1;
}
}
if ((inchar = locgetc(chcount)) == ch)
continue;
if (locungetc(chcount, inchar) != EOF) {
return (nmatch);
}
break;
}
#endif
charswitch:
if (ch == '*') {
stow = 0;
ch = *fmt++;
} else
stow = 1;
#ifdef _WIDE
for (len = 0; ((ch >= 0) && (ch < 256) && isdigit(ch));
ch = *fmt++)
len = len * 10 + ch - '0';
#else
for (len = 0; isdigit(ch); ch = *fmt++)
len = len * 10 + ch - '0';
#endif
if (ch == '$') {
if (fpos) {
if (_mkarglst(sformat, sargs, arglst) != 0) {
return (EOF);
} else {
fpos = 0;
}
}
if (len <= MAXARGS) {
args = arglst[len - 1];
} else {
args = arglst[MAXARGS - 1];
for (len -= MAXARGS; len > 0; len--)
(void) va_arg(args.ap, void *);
}
len = 0;
ch = *fmt++;
goto charswitch;
}
if (len == 0)
len = MAXINT;
#ifdef _WIDE
if ((size = ch) == 'l' || (size == 'h') || (size == 'L') ||
(size == 'j') || (size == 't') || (size == 'z'))
ch = *fmt++;
#else
if ((size = ch) == 'l' || (size == 'h') || (size == 'L') ||
(size == 'w') || (size == 'j') || (size == 't') ||
(size == 'z'))
ch = *fmt++;
#endif
if (size == 'l' && ch == 'l') {
size = 'm';
ch = *fmt++;
} else if (size == 'h' && ch == 'h') {
size = 'b';
ch = *fmt++;
} else if ((size == 't') || (size == 'z')) {
size = 'l';
} else if (size == 'j') {
#ifndef _LP64
if (!(scflag & _F_INTMAX32)) {
#endif
size = 'm';
#ifndef _LP64
}
#endif
}
if (ch == '\0') {
return (EOF);
}
#ifdef _WIDE
if (ch == '[') {
wchar_t c;
size_t len;
int negflg = 0;
wchar_t *p;
wchar_t *wbracket_str;
size_t wlen, clen;
p = (wchar_t *)fmt - 1;
len = 0;
if (*fmt == '^') {
len++;
fmt++;
negflg = 1;
}
if (((c = *fmt) == ']') || (c == '-')) {
len++;
fmt++;
}
while ((c = *fmt) != ']') {
if (c == '\0') {
return (EOF);
} else {
len++;
fmt++;
}
}
fmt++;
len += 2;
wbracket_str = (wchar_t *)
malloc(sizeof (wchar_t) * (len + 1));
if (wbracket_str == NULL) {
errno = ENOMEM;
return (EOF);
} else {
(void) wmemcpy(wbracket_str,
(const wchar_t *)p, len);
*(wbracket_str + len) = L'\0';
if (negflg && *(wbracket_str + 1) == '^') {
*(wbracket_str + 1) = L'!';
}
}
wlen = wcslen(wbracket_str);
clen = wcstombs((char *)NULL, wbracket_str, 0);
if (clen == (size_t)-1) {
free(wbracket_str);
return (EOF);
}
bracket_str = (unsigned char *)
malloc(sizeof (unsigned char) * (clen + 1));
if (bracket_str == NULL) {
free(wbracket_str);
errno = ENOMEM;
return (EOF);
}
clen = wcstombs((char *)bracket_str, wbracket_str,
wlen + 1);
free(wbracket_str);
if (clen == (size_t)-1) {
free(bracket_str);
return (EOF);
}
}
#else
if (ch == '[') {
if (size == 'l') {
int c, len, i;
int negflg = 0;
unsigned char *p;
p = (unsigned char *)(fmt - 1);
len = 0;
if (*fmt == '^') {
len++;
fmt++;
negflg = 1;
}
if (((c = *fmt) == ']') || (c == '-')) {
len++;
fmt++;
}
while ((c = *fmt) != ']') {
if (c == '\0') {
return (EOF);
} else if (isascii(c)) {
len++;
fmt++;
} else {
i = mblen((const char *)fmt,
MB_CUR_MAX);
if (i <= 0) {
return (EOF);
} else {
len += i;
fmt += i;
}
}
}
fmt++;
len += 2;
bracket_str = (unsigned char *)
malloc(sizeof (unsigned char) * (len + 1));
if (bracket_str == NULL) {
errno = ENOMEM;
return (EOF);
} else {
(void) strncpy((char *)bracket_str,
(const char *)p, len);
*(bracket_str + len) = '\0';
if (negflg &&
*(bracket_str + 1) == '^') {
*(bracket_str + 1) = '!';
}
}
} else {
int t = 0;
int b, c, d;
if (*fmt == '^') {
t++;
fmt++;
}
(void) memset(tab, !t, NCHARS);
if ((c = *fmt) == ']' || c == '-') {
tab[c] = t;
fmt++;
}
while ((c = *fmt) != ']') {
if (c == '\0') {
return (EOF);
}
b = *(fmt - 1);
d = *(fmt + 1);
if ((c == '-') && (d != ']') &&
(b < d)) {
(void) memset(&tab[b], t,
d - b + 1);
fmt += 2;
} else {
tab[c] = t;
fmt++;
}
}
fmt++;
}
}
#endif
#ifdef _WIDE
if ((ch >= 0) && (ch < 256) &&
isupper((int)ch)) {
if (_lib_version == c_issue_4) {
if (size != 'm' && size != 'L')
size = 'l';
}
ch = _tolower((int)ch);
}
if (ch != 'n' && !flag_eof) {
if (ch != 'c' && ch != 'C' && ch != '[') {
while (iswspace(inchar =
_wd_getwc(&chcount, iop)))
;
if (_wd_ungetwc(&chcount, inchar, iop) == WEOF)
break;
}
}
#else
if (isupper(ch)) {
if (_lib_version == c_issue_4) {
if (size != 'm' && size != 'L')
size = 'l';
}
ch = _tolower(ch);
}
if (ch != 'n' && !flag_eof) {
if (ch != 'c' && ch != 'C' && ch != '[') {
while (isspace(inchar = locgetc(chcount)))
;
if (locungetc(chcount, inchar) == EOF)
break;
}
}
#endif
switch (ch) {
case 'C':
case 'S':
case 'c':
case 's':
#ifdef _WIDE
if ((size == 'l') || (size == 'C') || (size == 'S'))
#else
if ((size == 'w') || (size == 'l') || (size == 'C') ||
(size == 'S'))
#endif
{
size = wstring(&chcount, &flag_eof, stow,
(int)ch, len, iop, &args.ap);
} else {
size = string(&chcount, &flag_eof, stow,
(int)ch, len, tab, iop, &args.ap);
}
break;
case '[':
if (size == 'l') {
size = wbrstring(&chcount, &flag_eof, stow,
(int)ch, len, iop, bracket_str, &args.ap);
free(bracket_str);
bracket_str = NULL;
} else {
#ifdef _WIDE
size = brstring(&chcount, &flag_eof, stow,
(int)ch, len, iop, bracket_str, &args.ap);
free(bracket_str);
bracket_str = NULL;
#else
size = string(&chcount, &flag_eof, stow,
ch, len, tab, iop, &args.ap);
#endif
}
break;
case 'n':
if (stow == 0)
continue;
if (size == 'b')
*va_arg(args.ap, char *) = (char)chcount;
else if (size == 'h')
*va_arg(args.ap, short *) = (short)chcount;
else if (size == 'l')
*va_arg(args.ap, long *) = (long)chcount;
else if (size == 'm')
*va_arg(args.ap, long long *) =
(long long) chcount;
else
*va_arg(args.ap, int *) = (int)chcount;
continue;
case 'i':
default:
size = number(&chcount, &flag_eof, stow, (int)ch,
len, (int)size, iop, &args.ap);
break;
}
if (size)
nmatch += stow;
else {
return ((flag_eof && !nmatch) ? EOF : nmatch);
}
continue;
}
if (bracket_str)
free(bracket_str);
return (nmatch != 0 ? nmatch : EOF);
}
static int
number(int *chcount, int *flag_eof, int stow, int type, int len, int size,
FILE *iop, va_list *listp)
{
char numbuf[64];
char *np = numbuf;
int c, base, inchar, lookahead;
int digitseen = 0, floater = 0, negflg = 0;
int lc;
long long lcval = 0LL;
switch (type) {
case 'e':
case 'f':
case 'g':
lc = (__xpg6 & _C99SUSv3_recognize_hexfp)? -1 : 0;
floater = 1;
break;
case 'a':
lc = -1;
floater = 1;
break;
case 'd':
case 'u':
case 'i':
base = 10;
break;
case 'o':
base = 8;
break;
case 'p':
#ifdef _LP64
size = 'l';
#endif
case 'x':
base = 16;
break;
default:
return (0);
}
if (floater != 0) {
decimal_mode dm;
decimal_record dr;
fp_exception_field_type efs;
enum decimal_string_form form;
char *echar;
int nread;
char buffer[1024+1];
char *nb = buffer;
if (len > 1024)
len = 1024;
file_to_decimal(&nb, len, lc, &dr, &form, &echar, iop, &nread);
if (lc == -1) {
if (nb != buffer + nread)
form = invalid_form;
}
if (stow && (form != invalid_form)) {
#if defined(__sparc)
dm.rd = _QgetRD();
if (size == 'L') {
if ((int)form < 0)
__hex_to_quadruple(&dr, dm.rd,
va_arg(*listp, quadruple *), &efs);
else
decimal_to_quadruple(
va_arg(*listp, quadruple *),
&dm, &dr, &efs);
}
#elif defined(__i386) || defined(__amd64)
dm.rd = __xgetRD();
if (size == 'L') {
if ((int)form < 0)
__hex_to_extended(&dr, dm.rd,
va_arg(*listp, extended *), &efs);
else
decimal_to_extended(
va_arg(*listp, extended *),
&dm, &dr, &efs);
}
#else
#error Unknown architecture
#endif
else if (size == 'l') {
if ((int)form < 0)
__hex_to_double(&dr, dm.rd,
va_arg(*listp, double *), &efs);
else
decimal_to_double(
va_arg(*listp, double *),
&dm, &dr, &efs);
} else {
if ((int)form < 0)
__hex_to_single(&dr, dm.rd,
va_arg(*listp, single *), &efs);
else
decimal_to_single((single *)
va_arg(*listp, single *),
&dm, &dr, &efs);
}
if ((efs & (1 << fp_overflow)) != 0) {
errno = ERANGE;
}
if ((efs & (1 << fp_underflow)) != 0) {
errno = ERANGE;
}
}
(*chcount) += nread;
c = locgetc((*chcount));
if (locungetc((*chcount), c) == EOF)
*flag_eof = 1;
return ((form == invalid_form) ? 0 : 1);
}
switch (c = locgetc((*chcount))) {
case '-':
negflg++;
case '+':
if (--len <= 0)
break;
if ((c = locgetc((*chcount))) != '0')
break;
case '0':
if ((type != 'i' && type != 'x') || (len <= 1))
break;
if (((inchar = locgetc((*chcount))) == 'x') ||
(inchar == 'X')) {
lookahead = readchar(iop, chcount);
if (isxdigit(lookahead)) {
base = 16;
if (len <= 2) {
(void) locungetc((*chcount), lookahead);
len -= 1;
} else {
c = lookahead;
len -= 2;
}
} else {
(void) locungetc((*chcount), lookahead);
(void) locungetc((*chcount), inchar);
}
} else {
(void) locungetc((*chcount), inchar);
if (type == 'i')
base = 8;
}
}
for (; --len >= 0; *np++ = (char)c, c = locgetc((*chcount))) {
if (np > numbuf + 62) {
errno = ERANGE;
return (0);
}
if (isdigit(c) || base == 16 && isxdigit(c)) {
int digit = c - (isdigit(c) ? '0' :
isupper(c) ? 'A' - 10 : 'a' - 10);
if (digit >= base)
break;
if (stow)
lcval = base * lcval + digit;
digitseen++;
continue;
}
break;
}
if (stow && digitseen) {
if (negflg && lcval != (1ULL << 63))
lcval = -lcval;
switch (size) {
case 'm':
*va_arg(*listp, long long *) = lcval;
break;
case 'l':
*va_arg(*listp, long *) = (long)lcval;
break;
case 'h':
*va_arg(*listp, short *) = (short)lcval;
break;
case 'b':
*va_arg(*listp, char *) = (char)lcval;
break;
default:
*va_arg(*listp, int *) = (int)lcval;
break;
}
}
if (locungetc((*chcount), c) == EOF)
*flag_eof = 1;
return (digitseen);
}
static int
readchar(FILE *iop, int *chcount)
{
int inchar;
char buf[1];
if ((iop->_flag & _IOWRT) || (iop->_cnt != 0)) {
inchar = locgetc((*chcount));
} else {
if (_xread(iop, buf, 1) != 1)
return (EOF);
inchar = (int)buf[0];
(*chcount) += 1;
}
return (inchar);
}
static int
string(int *chcount, int *flag_eof, int stow, int type, int len,
char *tab __unused, FILE *iop, va_list *listp)
{
int ch;
char *ptr;
char *start;
start = ptr = stow ? va_arg(*listp, char *) : NULL;
if (((type == 'c') || (type == 'C')) && len == MAXINT)
len = 1;
#ifdef _WIDE
while ((ch = locgetc((*chcount))) != EOF &&
!(((type == 's') || (type == 'S')) && isspace(ch))) {
#else
while ((ch = locgetc((*chcount))) != EOF &&
!(((type == 's') || (type == 'S')) &&
isspace(ch) || type == '[' && tab[ch])) {
#endif
if (stow)
*ptr = (char)ch;
ptr++;
if (--len <= 0)
break;
}
if (ch == EOF) {
(*flag_eof) = 1;
(*chcount) -= 1;
} else if (len > 0 && locungetc((*chcount), ch) == EOF)
(*flag_eof) = 1;
if (ptr == start)
return (0);
if (stow && ((type != 'c') && (type != 'C')))
*ptr = '\0';
return (1);
}
#ifdef _WIDE
static int
_mkarglst(const wchar_t *fmt, stva_list args, stva_list arglst[])
#else
static int
_mkarglst(const char *fmt, stva_list args, stva_list arglst[])
#endif
{
#ifdef _WIDE
#define STRCHR wcschr
#define STRSPN wcsspn
#define ATOI(x) _watoi((wchar_t *)x)
#define SPNSTR1 L"01234567890"
#define SPNSTR2 L"# +-.0123456789hL$"
#else
#define STRCHR strchr
#define STRSPN strspn
#define ATOI(x) atoi(x)
#define SPNSTR1 "01234567890"
#define SPNSTR2 "# +-.0123456789hL$"
#endif
int maxnum, curargno;
size_t n;
maxnum = -1;
curargno = 0;
while ((fmt = STRCHR(fmt, '%')) != NULL) {
fmt++;
if (*fmt == '*' || *fmt == '%')
continue;
if (fmt[n = STRSPN(fmt, SPNSTR1)] == L'$') {
curargno = ATOI(fmt) - 1;
fmt += n + 1;
}
if (maxnum < curargno)
maxnum = curargno;
curargno++;
fmt += STRSPN(fmt, SPNSTR2);
if (*fmt == '[') {
fmt++;
if (*fmt == ']') {
fmt++;
}
while (*fmt != ']') {
if (*fmt == L'\0') {
return (-1);
#ifdef _WIDE
} else {
fmt++;
}
#else
} else if (isascii(*fmt)) {
fmt++;
} else {
int i;
i = mblen((const char *)
fmt, MB_CUR_MAX);
if (i <= 0) {
return (-1);
} else {
fmt += i;
}
}
#endif
}
}
}
if (maxnum > MAXARGS)
maxnum = MAXARGS;
for (n = 0; n <= maxnum; n++) {
arglst[n] = args;
(void) va_arg(args.ap, void *);
}
return (0);
}
#ifdef _WIDE
static int
wstring(int *chcount, int *flag_eof, int stow, int type,
int len, FILE *iop, va_list *listp)
{
wint_t wch;
wchar_t *ptr;
wchar_t *wstart;
wstart = ptr = stow ? va_arg(*listp, wchar_t *) : NULL;
if ((type == 'c') && len == MAXINT)
len = 1;
while (((wch = _wd_getwc(chcount, iop)) != WEOF) &&
!(type == 's' && iswspace(wch))) {
if (stow)
*ptr = wch;
ptr++;
if (--len <= 0)
break;
}
if (wch == WEOF) {
*flag_eof = 1;
(*chcount) -= 1;
} else {
if (len > 0 && _wd_ungetwc(chcount, wch, iop) == WEOF)
*flag_eof = 1;
}
if (ptr == wstart)
return (0);
if (stow && (type != 'c'))
*ptr = '\0';
return (1);
}
#else
static int
wstring(int *chcount, int *flag_eof, int stow, int type, int len, FILE *iop,
va_list *listp)
{
int wch;
wchar_t *ptr;
wchar_t *wstart;
wstart = ptr = stow ? va_arg(*listp, wchar_t *) : NULL;
if ((type == 'c') && len == MAXINT)
len = 1;
while (((wch = _bi_getwc(iop)) != EOF) &&
!(type == 's' && (isascii(wch) ? isspace(wch) : 0))) {
(*chcount) += _scrwidth((wchar_t)wch);
if (stow)
*ptr = wch;
ptr++;
if (--len <= 0)
break;
}
if (wch == EOF) {
(*flag_eof) = 1;
(*chcount) -= 1;
} else {
if (len > 0 && _bi_ungetwc(wch, iop) == EOF)
(*flag_eof) = 1;
}
if (ptr == wstart)
return (0);
if (stow && (type != 'c'))
*ptr = '\0';
return (1);
}
#endif
#ifdef _WIDE
static wint_t
_wd_getwc(int *chcount, FILE *iop)
{
wint_t wc;
int len;
if (!(iop->_flag & _IOWRT)) {
wc = __fgetwc_xpg5(iop);
(*chcount)++;
return (wc);
} else {
if (*iop->_ptr == '\0')
return (WEOF);
len = mbtowc((wchar_t *)&wc, (const char *)iop->_ptr,
MB_CUR_MAX);
if (len == -1)
return (WEOF);
iop->_ptr += len;
(*chcount)++;
return (wc);
}
}
static wint_t
_wd_ungetwc(int *chcount, wchar_t wc, FILE *iop)
{
wint_t ret;
int len;
char mbs[MB_LEN_MAX];
if (wc == WEOF)
return (WEOF);
if (!(iop->_flag & _IOWRT)) {
ret = __ungetwc_xpg5((wint_t)wc, iop);
if (ret != (wint_t)wc)
return (WEOF);
(*chcount)--;
return (ret);
} else {
len = wctomb(mbs, wc);
if (len == -1)
return (WEOF);
iop->_ptr -= len;
(*chcount)--;
return ((wint_t)wc);
}
}
static int
_watoi(wchar_t *fmt)
{
int n = 0;
wchar_t ch;
ch = *fmt;
if ((ch >= 0) && (ch < 256) && isdigit((int)ch)) {
n = ch - '0';
while (((ch = *++fmt) >= 0) && (ch < 256) &&
isdigit((int)ch)) {
n *= 10;
n += ch - '0';
}
}
return (n);
}
#endif
static int
wbrstring(int *chcount, int *flag_eof, int stow, int type __unused,
int len, FILE *iop, unsigned char *brstr, va_list *listp)
{
wint_t wch;
int i;
char str[MB_LEN_MAX + 1];
wchar_t *ptr, *start;
#ifdef _WIDE
int dummy;
#endif
start = ptr = stow ? va_arg(*listp, wchar_t *) : NULL;
#ifdef _WIDE
while ((wch = _wd_getwc(&dummy, iop)) != WEOF) {
#else
while ((wch = _bi_getwc(iop)) != WEOF) {
#endif
i = wctomb(str, (wchar_t)wch);
if (i == -1) {
return (0);
}
str[i] = '\0';
if (fnmatch((const char *)brstr, (const char *)str,
FNM_NOESCAPE)) {
break;
} else {
if (len > 0) {
#ifdef _WIDE
(*chcount)++;
#else
(*chcount) += _scrwidth(wch);
#endif
len--;
if (stow) {
*ptr = wch;
}
ptr++;
if (len <= 0)
break;
} else {
break;
}
}
}
if (wch == WEOF) {
*flag_eof = 1;
} else {
#ifdef _WIDE
if (len > 0 && _wd_ungetwc(&dummy, wch, iop) == WEOF)
#else
if (len > 0 && _bi_ungetwc(wch, iop) == WEOF)
#endif
*flag_eof = 1;
}
if (ptr == start)
return (0);
if (stow)
*ptr = L'\0';
return (1);
}
#ifdef _WIDE
static int
brstring(int *chcount, int *flag_eof, int stow, int type __unused,
int len, FILE *iop, unsigned char *brstr, va_list *listp)
{
wint_t wch;
int i;
char str[MB_LEN_MAX + 1];
char *ptr, *start, *p;
int dummy;
start = ptr = stow ? va_arg(*listp, char *) : NULL;
while ((wch = _wd_getwc(&dummy, iop)) != WEOF) {
p = str;
i = wctomb(str, (wchar_t)wch);
if (i == -1) {
return (0);
}
str[i] = '\0';
if (fnmatch((const char *)brstr, (const char *)str,
FNM_NOESCAPE)) {
break;
} else {
if (len >= i) {
(*chcount)++;
len -= i;
if (stow) {
while (i-- > 0) {
*ptr++ = *p++;
}
} else {
while (i-- > 0) {
ptr++;
}
}
if (len <= 0)
break;
} else {
break;
}
}
}
if (wch == WEOF) {
*flag_eof = 1;
} else {
if (len > 0 && _wd_ungetwc(&dummy, wch, iop) == WEOF)
*flag_eof = 1;
}
if (ptr == start)
return (0);
if (stow)
*ptr = '\0';
return (1);
}
#endif
static int
_bi_getwc(FILE *iop)
{
int c;
wchar_t intcode;
int i, nbytes, cur_max;
char buff[MB_LEN_MAX];
if ((c = wlocgetc()) == EOF)
return (WEOF);
if (isascii(c))
return ((wint_t)c);
buff[0] = (char)c;
cur_max = (int)MB_CUR_MAX;
for (i = 1; i < cur_max; i++) {
c = wlocgetc();
if (c == '\n') {
(void) wlocungetc(c);
break;
}
if (c == EOF) {
break;
}
buff[i] = (char)c;
}
if ((nbytes = mbtowc(&intcode, buff, i)) == -1) {
while (i-- > 1) {
(void) wlocungetc((signed char)buff[i]);
}
errno = EILSEQ;
return (WEOF);
}
while (i-- > nbytes) {
(void) wlocungetc((signed char)buff[i]);
}
return ((int)intcode);
}
static int
_bi_ungetwc(wint_t wc, FILE *iop)
{
char mbs[MB_LEN_MAX];
unsigned char *p;
int n;
if ((wc == WEOF) || ((iop->_flag & _IOREAD) == 0))
return (WEOF);
n = wctomb(mbs, (wchar_t)wc);
if (n <= 0)
return (WEOF);
if (iop->_ptr <= iop->_base) {
if (iop->_base == NULL) {
return (WEOF);
}
if ((iop->_ptr == iop->_base) && (iop->_cnt == 0)) {
++iop->_ptr;
} else if ((iop->_ptr - n) < (iop->_base - PUSHBACK)) {
return (WEOF);
}
}
p = (unsigned char *)(mbs+n-1);
if ((iop->_flag & _IOWRT) == 0) {
iop->_cnt += n;
while (n--) {
*--iop->_ptr = *(p--);
}
} else {
iop->_ptr -= n;
}
return (wc);
}