/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#include "sfhdr.h"
/* The main engine for reading formatted data
**
** Written by Kiem-Phong Vo.
*/
/*
* pull in a private strtold()
*/
#include "sfstrtof.h"
/* refresh stream buffer - taking care of unseekable/share streams too */
#if __STD_C
#else
Sfio_t* f;
int* peek;
#endif
{
{ if(*peek) /* try peeking for a share stream if possible */
if(SFFILBUF(f,-1) > 0)
return;
}
*peek = 0; /* can't peek, back to normal reads */
}
(void)SFFILBUF(f,-1);
}
}
/* buffer used during scanning of a double value or a multi-byte
character. the fields mirror certain local variables in sfvscanf. */
typedef struct _scan_s
Sfio_t *f; /* stream being scanned */
} Scan_t;
/* ds != 0 for scanning double values */
#if __STD_C
#else
void* arg;
int flag;
#endif
{
if (flag)
return 0;
}
/* if width >= 0, do not allow to exceed width number of bytes */
return 0;
}
return 0;
}
}
else return ((int)(*sc->d++));
}
/* structure to match characters in a character class */
typedef struct _accept_s
int yes;
#if _has_multibyte
#endif
} Accept_t;
#if __STD_C
#else
char* form; /* format string */
int flags; /* SFFMT_LONG for wchar_t */
#endif
{
int c, endc, n;
form += 1;
}
for(c = 0; c <= SF_MAXCHAR; ++c)
form += 1;
}
if(flags&SFFMT_LONG)
return NIL(char*);
#if _has_multibyte
goto one_char;
#endif
for(; c <= endc; ++c)
n = 3;
}
else
{ one_char:
#if _has_multibyte /* true multi-byte chars must be checked differently */
return NIL(char*);
if(n == 1)
#endif
}
}
return (char*)(form+1);
}
#if _has_multibyte
#if __STD_C
#else
#endif
{
int endc, c, n;
return 0;
goto one_char;
n = 3;
}
else
{ one_char:
}
}
}
#if _has_multibyte == 1
#else
#endif
#if __STD_C
#else
int fmt; /* %s, %c, %[ */
#endif
{
int n, v;
char b[16]; /* assuming that SFMBMAX <= 16! */
/* shift left data so that there will be more room to back up on error.
this won't help streams with small buffers - c'est la vie! */
}
for(n = 0; n < SFMBMAX; )
goto no_match;
else b[n++] = v;
goto no_match; /* malformed multi-byte char */
else
{ /* multi-byte char converted successfully */
if(fmt == 'c')
return 1;
else if(fmt == 's')
return 1;
else goto no_match;
}
else if(fmt == '[')
return 1;
else goto no_match;
}
else /* if(fmt == '1') match a single wchar_t */
return 1;
else goto no_match;
}
}
}
no_match: /* this unget is lossy on a stream with small buffer */
return 0;
}
#endif /*_has_multibyte*/
#if __STD_C
#else
Sfio_t* f; /* file to be scanned */
#endif
{
char *sp;
char *oform;
#if _has_multibyte
#endif
char* t_str;
/* local buffering system */
int peek;
(int)(*d++) : -1 )
SFMTXDECL(f);
SFCVINIT(); /* initialize conversion tables */
SFMTXENTER(f,-1);
SFMTXRETURN(f, -1);
SFLOCK(f,0);
SFinit(f); /* initialize local buffering system */
argn = -1;
{ if(fmt != '%')
fmt = -1;
for(;;)
goto loop_fmt;
goto loop_fmt;
}
}
}
else
{ match_1:
#if _has_multibyte
goto pop_fmt;
if(n > 1)
if(v == 0)
goto pop_fmt;
form += n-1;
}
else
#endif
{ if(inp < 0)
goto done;
goto pop_fmt;
}
}
continue;
}
if(*form == '%')
{ form += 1;
goto match_1;
}
if(*form == '\0')
goto pop_fmt;
if(*form == '*')
{ flags = SFFMT_SKIP;
form += 1;
}
else flags = 0;
/* matching some pattern */
argp = -1;
loop_flags: /* LOOP FOR FLAGS, WIDTH, BASE, TYPE */
{
case LEFTP : /* get the type which is enclosed in balanced () */
for(v = 1;;)
{ switch(*form++)
{
case 0 : /* not balanceable, retract */
n_str = 0;
goto loop_flags;
case LEFTP : /* increasing nested level */
v += 1;
continue;
case RIGHTP : /* decreasing nested level */
if((v -= 1) != 0)
continue;
if(*t_str != '*' )
else
if(*t_str == '$')
{ if(!fp &&
goto pop_fmt;
}
if(fp)
}
LEFTP, 0, 0, 0,0,0,
NIL(char*),0);
if(n < 0)
goto pop_fmt;
goto t_arg;
}
else
{ t_arg:
}
}
goto loop_flags;
}
}
case '#' : /* alternative format */
flags |= SFFMT_ALTER;
goto loop_flags;
case '.' : /* width & base */
dot += 1;
goto dot_size;
}
else if(*form == '*')
if(*form == '$')
{ form += 1;
if(!fp &&
goto pop_fmt;
}
if(fp)
NIL(char*), 0);
goto pop_fmt;
v = argv.i;
}
if(v < 0)
v = 0;
goto dot_set;
}
else goto loop_flags;
case '0' : case '1' : case '2' : case '3' : case '4' :
case '5' : case '6' : case '7' : case '8' : case '9' :
dot_size :
if(*form == '$')
{ form += 1;
goto pop_fmt;
argp = v-1;
goto loop_flags;
}
dot_set :
width = v;
else if(dot == 2)
base = v;
goto loop_flags;
case 'z' : /* ssize_t or object size */
case 'I' : /* object size */
if(*form == '*')
if(*form == '$')
{ form += 1;
if(!fp &&
goto pop_fmt;
}
if(fp) /* use position list */
NIL(char*), 0);
goto pop_fmt;
}
}
else if (fmt == 'z')
goto loop_flags;
case 'l' :
if(*form == 'l')
{ form += 1;
flags |= SFFMT_LLONG;
}
else flags |= SFFMT_LONG;
goto loop_flags;
case 'h' :
if(*form == 'h')
{ form += 1;
flags |= SFFMT_SSHORT;
}
else flags |= SFFMT_SHORT;
goto loop_flags;
case 'L' :
goto loop_flags;
case 'j' :
goto loop_flags;
case 't' :
goto loop_flags;
case QUOTE :
if(thousand > 0)
flags |= SFFMT_THOUSAND;
goto loop_flags;
}
/* set object size for scalars */
if(flags & SFFMT_TYPES)
{ if(flags&SFFMT_LONG)
size = sizeof(long);
else if(flags&SFFMT_SHORT)
size = sizeof(short);
else if(flags&SFFMT_SSHORT)
size = sizeof(char);
else if(flags&SFFMT_TFLAG)
else if(flags&SFFMT_ZFLAG)
else if(flags&SFFMT_IFLAG)
{ if(size <= 0 ||
}
else if(size < 0)
size = sizeof(int);
}
size = sizeof(double);
else if(flags&SFFMT_LDOUBLE)
size = sizeof(Sfdouble_t);
else if(flags&SFFMT_IFLAG)
{ if(size <= 0)
size = sizeof(Sfdouble_t);
}
else if(size < 0)
size = sizeof(float);
}
{
#if _has_multibyte
sizeof(wchar_t) : sizeof(int);
} else
#endif
if(size < 0)
size = sizeof(int);
}
}
if(fp)
{ n_assign += 1;
}
else flags |= SFFMT_SKIP;
}
if(v < 0)
goto pop_fmt;
else if(v > 0) /* extf comsumed v input bytes */
{ n_input += v;
n_assign += 1;
continue;
}
else /* if(v == 0): extf did not use input stream */
}
}
goto pop_fmt;
if(fmt == '!')
{ if(!fp)
else goto pop_fmt;
continue;
continue;
}
else /* stack a new environment */
goto done;
argn = -1;
}
}
continue;
}
/* get the address to assign value */
{
#if !_ast_intmax_long
else
#endif
if(size == sizeof(long) )
else if(size == sizeof(short) )
continue;
}
/* if get here, start scanning input */
if(width == 0)
/* define the first input character */
else
}
if(inp < 0)
goto done;
{ if(inp >= 0)
goto pop_fmt;
}
if(value)
{
#if !_ast_fltmax_double
if(size == sizeof(Sfdouble_t))
else
#endif
if(size == sizeof(double))
n_assign += 1;
}
}
{ if(inp == '-')
goto pop_fmt;
}
else goto int_cvt;
}
{ int_cvt:
{ if(inp == '-')
flags |= SFFMT_MINUS;
break;
}
if(inp < 0)
goto done;
if(fmt == 'o')
base = 8;
base = 16;
{ base = 8;
base = 16;
}
inp = '0';
}
}
/* now convert */
if(base == 16)
shift = 4;
goto pop_fmt;
}
{ /* skip leading 0x or 0X */
}
goto base_shift;
}
else if(base == 10)
{ for(n = v = 0;; )
{ /* fast base 10 conversion */
n += 1;
}
{ if((v && n != 3) || (!v && n > 3) )
break;
v = 1; n = 0;
}
else break;
break;
}
if (!n && !v)
goto pop_fmt;
}
goto pop_fmt;
if(--width > 0 &&
goto base_conv;
}
}
else
{ /* other bases */
goto pop_fmt;
}
base_conv: /* check for power of 2 conversions */
{ if(base < 8)
else if(base < 32)
base_shift: do
} while(--width > 0 &&
}
else
{ do
} while(--width > 0 &&
}
}
if(flags&SFFMT_MINUS)
if(value)
{ n_assign += 1;
if(fmt == 'p')
#if _more_void_int
#else
#endif
#if !_ast_intmax_long
#endif
else if(size == sizeof(long))
}
else if(size == sizeof(short))
}
else if(size == sizeof(char) )
}
else
}
}
}
goto do_string;
}
{ do_string:
if(value)
{ if(size < 0)
if(fmt != 'c')
size -= 1;
#if _has_multibyte
if(flags&SFFMT_LONG)
else
#endif
}
else size = 0;
goto pop_fmt;
}
n = 0; /* count number of scanned characters */
#if _has_multibyte
if(flags&SFFMT_LONG)
break;
if((n += 1) <= size)
}
}
else
#endif
if(fmt == 's')
{ do
break;
if((n += 1) <= size)
}
else if(fmt == 'c')
{ do
{ if((n += 1) <= size)
}
else /* if(fmt == '[') */
{ do
{ if(n > 0 || (flags&SFFMT_ALTER) )
break;
else
goto pop_fmt;
}
}
if((n += 1) <= size)
}
{ n_assign += 1;
{
#if _has_multibyte
if(flags&SFFMT_LONG)
else
#endif
*argv.s = 0;
}
}
}
}
if(fp)
}
goto loop_fmt;
}
}
goto loop_fmt;
}
done:
if(fp)
}
SFend(f);
SFOPEN(f,0);
n_assign = -1;
SFMTXRETURN(f,n_assign);
}