150 lines
2.9 KiB
C
150 lines
2.9 KiB
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);
|
|
}
|
|
}
|