#include	"stdio.h"

#define	SPC	01
#define	STP	02

char	*_getccl();

char	_sctab[128] {
	0,0,0,0,0,0,0,0,
	0,SPC,SPC,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	SPC,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
};

_doscan(iop, fmt, argp)
register char *fmt;
register int *argp;
{
	register int ch;
	int nmatch, len, ch1;
	int *ptr, fileended;

	nmatch = 0;
	fileended = 0;
	for (;;) switch (ch = *fmt++) {
	case '\0': 
		return (nmatch);
	case '%': 
		if ((ch = *fmt++) == '%')
			goto def;
		ptr = 0;
		if (ch != '*')
			ptr = *argp++;
		else
			ch = *fmt++;
		len = 0;
		while (ch>='0' && ch <='9') {
			len = len*10 + ch - '0';
			ch = *fmt++;
		}
		if (len == 0)
			len = 30000;
		if (ch=='l') {
			ch = *fmt++;
			if (ch>='a' && ch<='z')
				ch =+ 'A'-'a';
		} else if (ch=='[')
			fmt = _getccl(fmt);
		if (ch == '\0')
			_error("scanf\n");
		if (_innum(ptr, ch, len, iop, &fileended) && ptr)
			nmatch++;
		if (fileended)
			return(nmatch? nmatch: -1);
		break;

	case ' ':
	case '\n':
	case '\t': 
		break;

	default: 
	def:
		if (ch != (ch1 = getc(iop)))
			return(ch1==EOF? -1: nmatch);
	}
}

_innum(ptr, type, len, iop, eofptr)
int *ptr, *eofptr;
struct _iobuf *iop;
{
	extern double atof();
	struct { double *dblptr;};
	struct { long *longptr;};
	struct { float *fltptr;};
	register char *np;
	char numbuf[64];
	register c, base;
	int expseen, scale, size, negflg, c1, ndigit;
	long lcval;

	if (type=='c' || type=='s' || type=='[')
		return(_instr(ptr, type, len, iop, eofptr));
	lcval = 0;
	ndigit = 0;
	size = 0;
	if (type>='A' && type <='Z') {
		size++;
		type =+ 'a'-'A';
	}
	scale = 0;
	if (type=='e'||type=='f')
		scale++;
	base = 10;
	if (type=='o')
		base = 8;
	else if (type=='x')
		base = 16;
	np = numbuf;
	expseen = 0;
	negflg = 0;
	while ((c = getc(iop))==' ' || c=='\t' || c=='\n');
	if (c=='-') {
		negflg++;
		*np++ = c;
		c = getc(iop);
		len--;
	} else if (c=='+') {
		len--;
		c = getc(iop);
	}
	for ( ; --len>=0; *np++ = c, c = getc(iop)) {
		if ('0'<=c && c<='9'
		 || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) {
			ndigit++;
			if (base==8)
				lcval =<<3;
			else if (base==10)
				lcval = ((lcval<<2) + lcval)<<1;
			else
				lcval =<< 4;
			c1 = c;
			if ('0'<=c && c<='9')
				c =- '0';
			else if ('a'<=c && c<='f')
				c =- 'a'-10;
			else
				c =- 'A'-10;
			lcval =+ c;
			c = c1;
			continue;
		} else if (c=='.') {
			if (base!=10 || scale==0)
				break;
			ndigit++;
			continue;
		} else if ((c=='e'||c=='E') && expseen==0) {
			if (base!=10 || scale==0 || ndigit==0)
				break;
			expseen++;
			*np++ = c;
			c = getc(iop);
			if (c!='+'&&c!='-'&&('0'>c||c>'9'))
				break;
		} else
			break;
	}
	if (negflg)
		lcval = -lcval;
	if (c != EOF) {
		ungetc(c, iop);
		*eofptr = 0;
	} else
		*eofptr = 1;
	if (ptr==NULL || np==numbuf)
		return(0);
	*np++ = 0;
	if (scale==0)
		if (size)
			*ptr.longptr = lcval;
		else
			*ptr = lcval;
	else
		if (size)
			*ptr.dblptr = atof(numbuf);
		else
			*ptr.fltptr = atof(numbuf);
	return(1);
}

_instr(ptr, type, len, iop, eofptr)
register char *ptr;
register struct _iobuf *iop;
int *eofptr;
{
	register ch;
	register char *optr;
	int ignstp;

	*eofptr = 0;
	optr = ptr;
	if (type=='c' && len==30000)
		len = 1;
	ignstp = 0;
	if (type=='s')
		ignstp = SPC;
	while (_sctab[ch = getc(iop)] & ignstp)
		if (ch==EOF)
			break;
	ignstp = SPC;
	if (type=='c')
		ignstp = 0;
	else if (type=='[')
		ignstp = STP;
	while (--len>=0 && ch>=0 && (_sctab[ch]&ignstp)==0) {
		if (ptr)
			*ptr++ = ch;
		ch = getc(iop);
	}
	if (ch != EOF) {
		ungetc(ch, iop);
		*eofptr = 0;
	} else
		*eofptr = 1;
	if (ptr && ptr!=optr) {
		if (type!='c')
			*ptr++ = '\0';
		return(1);
	}
	return(0);
}

char *
_getccl(s)
register char *s;
{
	register c, t;

	t = 0;
	if (*s == '^') {
		t++;
		s++;
	}
	for (c = 0; c < 128; c++)
		if (t)
			_sctab[c] =& ~STP;
		else
			_sctab[c] =| STP;
	while (((c = *s++)&0177) != ']') {
		if (t)
			_sctab[c++] =| STP;
		else
			_sctab[c++] =& ~STP;
		if (c==0)
			return(--s);
	}
	return(s);
}
