doscan.c revision d12182d8ece1c86804ccf0f3bceb9bf14d671f71
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
#include "lint.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"
/* if the _IOWRT flag is set, this must be a call from sscanf */
/*
* stva_list is used to subvert C's restriction that a variable with an
* array type can not appear on the left hand side of an assignment operator.
* By putting the array inside a structure, the functionality of assigning to
* the whole array through a simple assignment is achieved..
*/
typedef struct stva_list {
} stva_list;
unsigned char *, va_list *);
#ifdef _WIDE
unsigned char *, va_list *);
#endif
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
#ifndef _WIDE
int
{
int ret;
else {
}
return (ret);
}
#endif /* _WIDE */
/* ARGSUSED3 */
#ifdef _WIDE
int
#else /* _WIDE */
int
#endif /* _WIDE */
{
#ifdef _WIDE
#else /* _WIDE */
int ch;
#endif /* _WIDE */
unsigned char *bracket_str = NULL;
/* variables for postional parameters */
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
/*
* array giving the appropriate values
* for va_arg() to retrieve the
* corresponding argument:
* arglst[0] is the first argument
* arglst[1] is the second argument,etc.
*/
/* Check if readable stream */
return (EOF);
}
/*
* Initialize args and sargs to the start of the argument list.
* We don't know any portable way to copy an arbitrary C object
* so we use a system-specific routine(probably a macro) from
* stdarg.h. (Remember that if va_list is an array, in_args will
* be a pointer and &in_args won't be what we would want for
* memcpy.)
*/
/*
* ****************************************************
* Main loop: reads format to determine a pattern,
* and then goes to read input stream
* in attempt to match the pattern.
* ****************************************************
*/
for (; ; ) {
return (nmatch); /* end of format */
}
#ifdef _WIDE
if (!flag_eof) {
;
flag_eof = 1;
}
continue;
}
if (ch == '%') {
if (!flag_eof) {
;
== WEOF)
flag_eof = 1;
}
}
continue;
return (nmatch); /* failed to match input */
}
break;
}
#else /* _WIDE */
if (!flag_eof) {
;
flag_eof = 1;
}
continue;
}
if (ch == '%') {
if (!flag_eof) {
;
flag_eof = 1;
}
}
continue;
return (nmatch); /* failed to match input */
}
break;
}
#endif /* _WIDE */
charswitch: /* target of a goto 8-( */
if (ch == '*') {
stow = 0;
} else
stow = 1;
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
if (ch == '$') {
/*
* positional parameter handling - the number
* specified in len gives the argument to which
* the next conversion should be applied.
* WARNING: This implementation of positional
* parameters assumes that the sizes of all pointer
* types are the same. (Code similar to that
* in the portable doprnt.c should be used if this
* assumption does not hold for a particular
* port.)
*/
if (fpos) {
return (EOF);
} else {
fpos = 0;
}
}
} else {
}
len = 0;
goto charswitch;
}
if (len == 0)
#ifdef _WIDE
#else /* _WIDE */
(size == 'z'))
#endif /* _WIDE */
size = 'l';
} else if (size == 'j') {
#ifndef _LP64
if (!(scflag & _F_INTMAX32)) {
#endif
size = 'm';
#ifndef _LP64
}
#endif
}
if (ch == '\0') {
return (EOF); /* unexpected end of format */
}
#ifdef _WIDE
if (ch == '[') {
wchar_t c;
int negflg = 0;
wchar_t *p;
/* p points to the address of '[' */
len = 0;
if (*fmt == '^') {
len++;
fmt++;
negflg = 1;
}
len++;
fmt++;
}
while ((c = *fmt) != ']') {
if (c == '\0') {
return (EOF); /* unexpected EOF */
} else {
len++;
fmt++;
}
}
fmt++;
len += 2;
wbracket_str = (wchar_t *)
if (wbracket_str == NULL) {
return (EOF);
} else {
(void) wmemcpy(wbracket_str,
}
}
return (EOF);
}
bracket_str = (unsigned char *)
if (bracket_str == NULL) {
return (EOF);
}
wlen + 1);
return (EOF);
}
}
#else /* _WIDE */
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;
}
len++;
fmt++;
}
while ((c = *fmt) != ']') {
if (c == '\0') {
return (EOF);
} else if (isascii(c)) {
len++;
fmt++;
} else {
if (i <= 0) {
return (EOF);
} else {
len += i;
fmt += i;
}
}
}
fmt++;
len += 2;
bracket_str = (unsigned char *)
if (bracket_str == NULL) {
return (EOF);
} else {
(void) strncpy((char *)bracket_str,
(const char *)p, len);
if (negflg &&
}
}
} else {
int t = 0;
int b, c, d;
if (*fmt == '^') {
t++;
fmt++;
}
tab[c] = t;
fmt++;
}
while ((c = *fmt) != ']') {
if (c == '\0') {
return (EOF);
}
b = *(fmt - 1);
d = *(fmt + 1);
if ((c == '-') && (d != ']') &&
(b < d)) {
d - b + 1);
fmt += 2;
} else {
tab[c] = t;
fmt++;
}
}
fmt++;
}
}
#endif /* _WIDE */
#ifdef _WIDE
if (_lib_version == c_issue_4) {
size = 'l';
}
}
;
break;
}
}
#else /* _WIDE */
if (_lib_version == c_issue_4) {
size = 'l';
}
}
;
break;
}
}
#endif /* _WIDE */
switch (ch) {
case 'C':
case 'S':
case 'c':
case 's':
#ifdef _WIDE
#else /* _WIDE */
(size == 'S'))
#endif /* _WIDE */
{
} else {
}
break;
case '[':
if (size == 'l') {
bracket_str = NULL;
} else {
#ifdef _WIDE
bracket_str = NULL;
#else /* _WIDE */
#endif /* _WIDE */
}
break;
case 'n':
if (stow == 0)
continue;
else if (size == 'h')
else if (size == 'l')
(long long) chcount;
else
continue;
case 'i':
default:
break;
}
if (size)
else {
}
continue;
}
if (bracket_str)
}
/* ****************************************************************** */
/* Functions to read the input stream in an attempt to match incoming */
/* data to the current pattern from the main loop of _doscan(). */
/* ****************************************************************** */
static int
{
char numbuf[64];
int lc;
switch (type) {
case 'e':
case 'f':
case 'g':
/*
* lc = 0 corresponds to c90 mode: do not recognize
* hexadecimal fp strings; attempt to push back
* all unused characters read
*
* lc = -1 corresponds to c99 mode: recognize hexa-
* decimal fp strings; push back at most one
* unused character
*/
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
#endif /* _LP64 */
/* FALLTHROUGH */
case 'x':
base = 16;
break;
default:
return (0); /* unrecognized conversion character */
}
if (floater != 0) {
/*
* Handle floating point with
* file_to_decimal.
*/
enum decimal_string_form form;
char *echar;
int nread;
if (len > 1024)
len = 1024;
if (lc == -1) {
/*
* In C99 mode, the entire string read has to be
* accepted in order to qualify as a match
*/
form = invalid_form;
}
#if defined(__sparc)
if ((int)form < 0)
else
}
if ((int)form < 0)
else
}
#else
#endif
if ((int)form < 0)
else
} else { /* float */
if ((int)form < 0)
else
}
}
}
}
*flag_eof = 1;
/* successful match if non-zero */
}
case '-':
negflg++;
/* FALLTHROUGH */
case '+':
if (--len <= 0)
break;
break;
/* FALLTHROUGH */
case '0':
/*
* If %i or %x, the characters 0x or 0X may optionally precede
* the sequence of letters and digits (base 16).
*/
break;
(inchar == 'X')) {
base = 16;
if (len <= 2) {
/* Take into account the 'x' */
len -= 1;
} else {
c = lookahead;
/* Take into account '0x' */
len -= 2;
}
} else {
}
} else {
/* inchar wans't 'x'. */
base = 8;
}
}
return (0);
}
break;
if (stow)
digitseen++;
continue;
}
break;
}
/* suppress possible overflow on 2's-comp negation */
switch (size) {
case 'm':
break;
case 'l':
break;
case 'h':
break;
case 'b':
break;
default:
break;
}
}
*flag_eof = 1;
return (digitseen); /* successful match if non-zero */
}
/* Get a character. If not using sscanf and at the buffer's end */
/* then do a direct read(). Characters read via readchar() */
/* can be pushed back on the input stream by locungetc((*chcount),) */
/* since there is padding allocated at the end of the stream buffer. */
static int
{
int inchar;
char buf[1];
else {
return (EOF);
(*chcount) += 1;
}
return (inchar);
}
static int
{
int ch;
char *ptr;
char *start;
len = 1;
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
if (stow)
ptr++;
if (--len <= 0)
break;
}
(*flag_eof) = 1;
(*chcount) -= 1;
(*flag_eof) = 1;
return (0); /* no match */
*ptr = '\0';
return (1); /* successful match */
}
/* This function initializes arglst, to contain the appropriate */
/* va_list values for the first MAXARGS arguments. */
/* WARNING: this code assumes that the sizes of all pointer types */
/* are the same. (Code similar to that in the portable doprnt.c */
/* should be used if this assumption is not true for a */
/* particular port.) */
#ifdef _WIDE
static int
#else /* _WIDE */
static int
#endif /* _WIDE */
{
#ifdef _WIDE
#define SPNSTR1 L"01234567890"
#define SPNSTR2 L"# +-.0123456789hL$"
#else /* _WIDE */
#define SPNSTR1 "01234567890"
#define SPNSTR2 "# +-.0123456789hL$"
#endif /* _WIDE */
size_t n;
maxnum = -1;
curargno = 0;
fmt++; /* skip % */
continue;
/* convert to zero base */
fmt += n + 1;
}
curargno++; /* default to next in list */
if (*fmt == '[') {
int i;
fmt++; /* has to be at least on item in scan list */
if (*fmt == ']') {
fmt++;
}
while (*fmt != ']') {
if (*fmt == L'\0') {
return (-1); /* bad format */
#ifdef _WIDE
} else {
fmt++;
}
#else /* _WIDE */
fmt++;
} else {
i = mblen((const char *)
fmt, MB_CUR_MAX);
if (i <= 0) {
return (-1);
} else {
fmt += i;
}
}
#endif /* _WIDE */
}
}
}
for (n = 0; n <= maxnum; n++) {
}
return (0);
}
/*
* For wide character handling
*/
#ifdef _WIDE
static int
{
int dummy;
len = 1;
if (stow)
ptr++;
if (--len <= 0)
break;
}
*flag_eof = 1;
(*chcount) -= 1;
} else {
*flag_eof = 1;
}
return (0); /* no match */
*ptr = '\0';
return (1); /* successful match */
}
#else /* _WIDE */
static int
{
int wch;
len = 1;
if (stow)
ptr++;
if (--len <= 0)
break;
}
(*flag_eof) = 1;
(*chcount) -= 1;
} else {
(*flag_eof) = 1;
}
return (0); /* no match */
*ptr = '\0';
return (1); /* successful match */
}
#endif /* _WIDE */
#ifdef _WIDE
static wint_t
{
int len;
/* call from fwscanf, wscanf */
(*chcount)++;
return (wc);
} else {
/* call from swscanf */
return (WEOF);
if (len == -1)
return (WEOF);
(*chcount)++;
return (wc);
}
}
static wint_t
{
int len;
char mbs[MB_LEN_MAX];
return (WEOF);
/* call from fwscanf, wscanf */
return (WEOF);
(*chcount)--;
return (ret);
} else {
/* call from swscanf */
if (len == -1)
return (WEOF);
(*chcount)--;
}
}
static int
{
int n = 0;
n = ch - '0';
n *= 10;
n += ch - '0';
}
}
return (n);
}
#endif /* _WIDE */
/* ARGSUSED3 */
static int
{
int i;
#ifdef _WIDE
int dummy;
#endif /* _WIDE */
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
if (i == -1) {
return (0);
}
str[i] = '\0';
FNM_NOESCAPE)) {
break;
} else {
if (len > 0) {
#ifdef _WIDE
(*chcount)++;
#else /* _WIDE */
#endif /* _WIDE */
len--;
if (stow) {
}
ptr++;
if (len <= 0)
break;
} else {
break;
}
}
}
*flag_eof = 1;
} else {
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
*flag_eof = 1;
}
return (0); /* no match */
if (stow)
*ptr = L'\0';
return (1); /* successful match */
}
#ifdef _WIDE
static int
{
int i;
int dummy;
p = str;
if (i == -1) {
return (0);
}
str[i] = '\0';
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;
}
}
}
*flag_eof = 1;
} else {
*flag_eof = 1;
}
return (0); /* no match */
if (stow)
*ptr = '\0';
return (1); /* successful match */
}
#endif /* _WIDE */
/*
* Locally define getwc and ungetwc
*/
static int
{
int c;
char buff[MB_LEN_MAX];
return (WEOF);
if (isascii(c)) /* ASCII code */
return ((wint_t)c);
buff[0] = (char)c;
cur_max = (int)MB_CUR_MAX;
/* MB_CUR_MAX doen't exeed the value of MB_LEN_MAX */
/* So we use MB_CUR_MAX instead of MB_LEN_MAX for */
/* improving the performance. */
for (i = 1; i < cur_max; i++) {
c = wlocgetc();
if (c == '\n') {
(void) wlocungetc(c);
break;
}
if (c == EOF) {
/* this still may be a valid multibyte character */
break;
}
buff[i] = (char)c;
}
/*
* If mbtowc fails, the input was not a legal character.
* ungetc all but one character.
*
* Note: the number of pushback characters that
* ungetc() can handle must be >= (MB_LEN_MAX - 1).
* In Solaris 2.x, the number of pushback
* characters is 4.
*/
while (i-- > 1) {
(void) wlocungetc((signed char)buff[i]);
}
return (WEOF); /* Illegal EUC sequence. */
}
while (i-- > nbytes) {
/*
* Note: the number of pushback characters that
* ungetc() can handle must be >= (MB_LEN_MAX - 1).
* In Solaris 2.x, the number of pushback
* characters is 4.
*/
(void) wlocungetc((signed char)buff[i]);
}
return ((int)intcode);
}
static int
{
char mbs[MB_LEN_MAX];
unsigned char *p;
int n;
return (WEOF);
if (n <= 0)
return (WEOF);
return (WEOF);
}
return (WEOF);
}
}
/* if _IOWRT is set to iop->_flag, it means this is */
/* an invocation from sscanf(), and in that time we */
/* don't touch iop->_cnt. Otherwise, which means an */
/* invocation from fscanf() or scanf(), we touch iop->_cnt */
/* scanf() and fscanf() */
while (n--) {
}
} else {
/* sscanf() */
}
return (wc);
}