scanf (p1, p2, p3, p4)
	int p1, p2, p3, p4;
{
/* first arg can be a control string, a file id, or -1 */
	int ptrs[10], j, ip, flp, k;
	char *np;
	extern int cin;
extern (*_Igetc)(), (*_Iungc)(), cgetc(), ungetc(), _Igstr(), _Iungs();
extern char *_Iinpt;
ip = 0;
if (p1 == -1)
  {k = 1; _Iinpt = p2;}
else if (p1 >= 0 && p1 < 10)
  k = 0;
else
  k = -1;
if (k <= 0)
  {_Igetc = cgetc; _Iungc = ungetc;}
else
  {_Igetc = _Igstr; _Iungc = _Iungs;}
j = 0;
for (np = (&p2)[k]; *np; np++)
    if (*np == '%' && *(np+1) != '%' && *(np+1) != '*')
	ptrs[ip++] = (&p3)[(j++)+k];
return (_Iscan ((k==0 ?  p1 : cin), (&p2)[k], ptrs));
}

_Iscan (fileid, format, listp)
	char *format;
	int *listp;
{
	char ch, _Inxch();
	int nmatch;
	extern int _Isfil;
	_Isfil = fileid;
nmatch = 0;
while (1) switch (ch= *format++)
	{
	case '\0': return (nmatch);
	case '%': switch (_Isfrm(&format, *listp++))
			{
			case -1: listp--;
			case 0: break;
			case -2: return (nmatch > 0 ? nmatch : -1);
			default: nmatch++;
			}
	case ' ':
	case '\n':
	case '\t': break;
	default: if (ch != _Inxch())
			return(nmatch);
	}
}

int _Isfil 0;

_Ichar (cptr, len)
	char *cptr;
{
	char ch, _Inxch();
	extern int _Isfil, (*_Igetc)();

while (len--)
	{
	if ((ch = (*_Igetc)(_Isfil)) <= 0)
		return (-2);
	if (cptr == 0)
		return (-1);
	*cptr++ = ch;
	}
return (1);
}

_Iflot (fptr, length)
	float *fptr;
	int length;
{
	char temp[75];
	extern int _Inodg(), (*_Iungc)(), _Isfil;
	float x;
	int kk, ch;
	double atof();

if ((ch= _Inxch()) < 0)
	return(-2);
(*_Iungc)(ch, _Isfil);
if ((kk=_Isstr(temp, length, _Inodg)) <= 0)
	return (kk);
x = atof(temp);
if (fptr == 0)
	return (-1);
*fptr = x;
return (1);
}

_Inodg (ch)
char ch;
{
if (_Idigt(ch,10) >= 0) return (0);
switch (ch)
	{
	case 'E':
	case 'e':
	case '.': case '+': case '-':
		return (0);
	}
return (1);
}

_Isfrm (spec, pointer)
	char **spec;
	int pointer;
{
	int length, lflag, _Iestr(), _Ispnd(), longf;
	char ch;
length = lflag = longf = 0;
while (1)
   around: switch(ch = *((*spec)++))
	{
	case '*': pointer=0; break;
	case '0': case '1': case '2': case '3': case '4':
	case '5': case '6': case '7': case '8': case '9':
		length = length*10 + ch - '0' ;
		lflag++;
		break;
	case 'o': /* octal */
		return(_Iint(pointer, lflag ? length : 100, 8, longf));
	case 'x': /* hex */
		return(_Iint(pointer, lflag ? length : 100, 16, longf));
	case 'd': /* decimal */
		return (_Iint(pointer, lflag ? length : 100, 10, longf));
	case 'c': /* character */
		return (_Ichar(pointer, lflag ? length : 1));
	case 's': /* string */
		return (_Isstr(pointer, lflag ? length : 100, _Iestr));
	case 'f':
	case 'e': /* float */
		return (_Iflot(pointer, lflag ? length : 100));
	case 'l': /*  (long) double or int */
		switch(*(*spec))
			{
			case 'f': case 'F':
			case 'e': case 'E':
				(*spec)++;
				return (_Ilong (pointer, lflag ? length : 100));
			case 'x': case 'X': case 'o': case 'O':
			case 'd': case 'D':
				longf=1;
				goto around;
			default: goto bad;
			}
	case '[': /* special strings */
		_Imtab(spec);
		return (_Isstr (pointer, lflag ? length : 100, _Ispnd));
	case '%':
		if (ch=_Inxch() != '%')
			return(ch < 0 ? -2 : -1);
		return(-1);
	case '\0':
		_Ierr("scanf: bad format termination\n");
		bad:
	default: _Ierr ("scanf: format character %c", ch);
	}
}
