MiniUnix/usr/source/iolib/scan1.c
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 : 0), (&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 0: listp--; break;
case -1: return (nmatch > 0 ? nmatch : -1);
default: nmatch++;
}
case ' ':
case '\n':
case '\t': break;
default: if (ch != _Inxch())
return(nmatch);
}
}
int _Isfil 0;
_Ichar (cptr)
char *cptr;
{
char ch, _Inxch();
if ((ch = _Inxch()) < 0)
return (-1);
if (cptr == 0)
return (0);
*cptr = ch;
return (1);
}
_Iflot (fptr, length)
float *fptr;
int length;
{
char temp[75];
int _Inodg();
float x;
double atof();
if (_Isstr(temp, length, _Inodg) < 0)
return (-1);
x = atof(temp);
if (fptr == 0)
return (0);
*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();
char ch;
length = lflag = 0;
while (1) 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));
case 'x': /* hex */
return(_Iint(pointer, lflag ? length : 100, 16));
case 'd': /* decimal */
return (_Iint(pointer, lflag ? length : 100, 10));
case 'c': /* character */
return (_Ichar(pointer));
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':
return (_Ilong (pointer, lflag ? length : 100));
default: printf(2, "long not yet implemented\n");
return(0);
}
case '[': /* special strings */
_Imtab(spec);
return (_Isstr (pointer, lflag ? length : 100, _Ispnd));
case '%':
if (_Inxch() != '%')
return (-1);
return(0);
case '\0':
_Ierr("scanf: bad format termination\n");
default: _Ierr ("scanf: format character %c", ch);
}
}