351 lines
13 KiB
C
351 lines
13 KiB
C
#include "stdio"
|
|
|
|
scanf(fs) /* standard routine */
|
|
char *fs;
|
|
{
|
|
int getc();
|
|
int ungetc();
|
|
return _input(stdin, &fs, getc, ungetc);
|
|
}
|
|
|
|
fscanf(fp, fs) /* standard routine */
|
|
char *fp, *fs;
|
|
{
|
|
int getc();
|
|
int ungetc();
|
|
return _input(fp, &fs, getc, ungetc);
|
|
}
|
|
|
|
sscanf(s,fs) /* standard routine */
|
|
char *s, *fs;
|
|
{
|
|
int _mread();
|
|
int _mungetc();
|
|
return _input(&s, &fs, _mread, _mungetc);
|
|
}
|
|
|
|
_input(fp, parms, read, ungetc) /* input routine for */
|
|
/* scanf, sscanf, fscanf */
|
|
char *fp; /* pointer to input */
|
|
char **parms; /* pointer to addr of parameters */
|
|
int (*read)(); /* character read function */
|
|
int (*ungetc)(); /* character unget function */
|
|
{
|
|
union { /* buffer for numeric & string storage */
|
|
int integer;
|
|
char string[81];
|
|
} buffer;
|
|
char *format; /* format string pointer */
|
|
char c; /* format string character */
|
|
char **ptr; /* pointer to pointer */
|
|
int base; /* number base */
|
|
int value; /* binary value of digit */
|
|
int pflag; /* real precision flag */
|
|
int asflag; /* assignment supression flag */
|
|
int sflag; /* sign flag */
|
|
int ch; /* input character */
|
|
int temp; /* temporary storage */
|
|
int i; /* loop counter */
|
|
int count; /* character count */
|
|
int width; /* maximum field width */
|
|
int status; /* status returned from the read */
|
|
int valid; /* valid real number format */
|
|
int (*acc)(); /* pointer to accumulate function */
|
|
int (*neg)(); /* pointer to negate function */
|
|
int (*asn)(); /* pointer to assign function */
|
|
int _digit(); /* decode digit function */
|
|
int _dint(); /* decode integer function */
|
|
int _dlong(); /* decode long function */
|
|
int _negint(); /* negate integer function */
|
|
int _neglong(); /* negate long function */
|
|
int _aint(); /* assign integer function */
|
|
int _along(); /* assign long function */
|
|
int _atoi(); /* convert string to integer */
|
|
int isspace(); /* whitespace function */
|
|
int isdigit(); /* digit function */
|
|
STRING *stods(); /* convert string to dynamic string */
|
|
|
|
format = *parms--; /* format points to format string */
|
|
count = 0; /* number of parameters read */
|
|
while (c = *format++) {
|
|
if (isspace(c)) continue; /* skip white space */
|
|
if (c != '%') {
|
|
while (isspace(ch = (*read)(fp)));
|
|
if (ch == c) continue;
|
|
else return (ch == EOF) ? EOF : count;
|
|
}
|
|
pflag = sflag = asflag = 0;
|
|
if ((*format) == '*') { /* check for assignment suppression */
|
|
++asflag;
|
|
++format;
|
|
}
|
|
acc = _dint;
|
|
neg = _negint;
|
|
asn = _aint;
|
|
width = isdigit(*format) ? _atoi(&format) : -1;
|
|
if (toupper(*format) == 'L') { /* check for double precision */
|
|
++pflag;
|
|
++format;
|
|
acc = _dlong;
|
|
neg = _neglong;
|
|
asn = _along;
|
|
}
|
|
c = *format++;
|
|
switch (toupper(c)) {
|
|
|
|
case 'H': /* signed decimal */
|
|
pflag++;
|
|
case 'D':
|
|
case 'U':
|
|
base = 10;
|
|
goto decode;
|
|
|
|
case 'O': /* unsigned octal */
|
|
base = 8;
|
|
goto decode;
|
|
|
|
case 'X': /* unsigned hexadecimal */
|
|
base = 16;
|
|
decode:
|
|
for (i=0; i<5; ++i) buffer.string[i] = '\0';
|
|
while ((ch=(*read)(fp))==' ' || ch == '\t'
|
|
|| ch == '\n');
|
|
if (ch == EOF) return EOF;
|
|
if (width && (ch == '+' || ch == '-')) {
|
|
if (ch == '-') ++sflag;
|
|
ch = (*read)(fp);
|
|
--width;
|
|
}
|
|
if (width && base == 16 && ch == '0') {
|
|
temp = (*read)(fp);
|
|
--width;
|
|
if (toupper(temp) == 'X' && width) {
|
|
ch = (*read)(fp);
|
|
--width;
|
|
}
|
|
else {
|
|
(*ungetc)(temp, fp);
|
|
++width;
|
|
}
|
|
}
|
|
if ((value = _digit(ch, base)) == -1) return count;
|
|
while (width && (value != -1)) {
|
|
(*acc)(&buffer.integer, value, base);
|
|
ch = (*read)(fp);
|
|
--width;
|
|
value = _digit(ch,base);
|
|
}
|
|
(*ungetc)(ch, fp);
|
|
if (sflag) (*neg)(&buffer.integer);
|
|
if (!asflag) {
|
|
(*asn)(&buffer.integer, *parms, pflag);
|
|
++count;
|
|
--parms;
|
|
}
|
|
break;
|
|
|
|
case 'S': /* string */
|
|
while ((ch=(*read)(fp))==' ' || ch == '\t'
|
|
|| ch == '\n');
|
|
if (ch == EOF) return EOF;
|
|
while (width && ch != ' ' && ch != '\t'
|
|
&& ch != '\n' && ch != EOF) {
|
|
if (!asflag) *(*parms)++ = ch;
|
|
ch = (*read)(fp);
|
|
--width;
|
|
}
|
|
(*ungetc)(ch, fp);
|
|
if (!asflag) {
|
|
*(*parms) = '\0';
|
|
++count;
|
|
--parms;
|
|
}
|
|
break;
|
|
|
|
case 'C': /* character */
|
|
if ((ch = (*read)(fp)) == EOF) return EOF;
|
|
else
|
|
if (!asflag) {
|
|
*(*parms) = ch;
|
|
++count;
|
|
--parms;
|
|
}
|
|
break;
|
|
|
|
case 'E':
|
|
case 'F': /* floating point */
|
|
while ((ch=(*read)(fp))==' ' || ch == '\t'
|
|
|| ch == '\n');
|
|
if (ch == EOF) return EOF;
|
|
i = 0;
|
|
valid = 0;
|
|
if (width && (ch == '+' || ch == '-')) {
|
|
buffer.string[i++] = ch;
|
|
ch = (*read)(fp);
|
|
--width;
|
|
}
|
|
while (width && ch >= '0' && ch <= '9') {
|
|
buffer.string[i++] = ch;
|
|
ch = (*read)(fp);
|
|
--width;
|
|
++valid;
|
|
}
|
|
if (width && ch == '.') {
|
|
buffer.string[i++] = ch;
|
|
ch = (*read)(fp);
|
|
--width;
|
|
while (width && ch >= '0' && ch <= '9') {
|
|
buffer.string[i++] = ch;
|
|
ch = (*read)(fp);
|
|
--width;
|
|
++valid;
|
|
}
|
|
}
|
|
if (width && (ch == 'E' || ch == 'e' || ch == 'D')) {
|
|
if (!valid) return count;
|
|
valid = 0;
|
|
buffer.string[i++] = 'E';
|
|
ch = (*read)(fp);
|
|
--width;
|
|
if (width && (ch == '+' || ch == '-')) {
|
|
buffer.string[i++] = ch;
|
|
ch = (*read)(fp);
|
|
--width;
|
|
}
|
|
while (width && isdigit(ch)) {
|
|
buffer.string[i++] = ch;
|
|
ch = (*read)(fp);
|
|
--width;
|
|
++valid;
|
|
}
|
|
}
|
|
(*ungetc)(ch, fp);
|
|
if (!valid) return count;
|
|
buffer.string[i] = '\0';
|
|
if (!asflag) {
|
|
_dreal(buffer.string, *parms, pflag);
|
|
++count;
|
|
--parms;
|
|
}
|
|
break;
|
|
|
|
case 'Y': /* dynamic string */
|
|
while ((ch=(*read)(fp))==' ' || ch == '\t'
|
|
|| ch == '\n');
|
|
if (ch == EOF) return EOF;
|
|
i = 0;
|
|
while (width && ch != ' ' && ch != '\t'
|
|
&& ch != '\n' && ch != EOF) {
|
|
if (i < 80) buffer.string[i++] = ch;
|
|
ch = (*read)(fp);
|
|
--width;
|
|
}
|
|
buffer.string[i] = '\0';
|
|
(*ungetc)(ch,fp);
|
|
if (!asflag) {
|
|
ptr = *parms;
|
|
*ptr = stods(buffer.string);
|
|
++count;
|
|
--parms;
|
|
}
|
|
break;
|
|
|
|
default :
|
|
return count;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
_negint(iptr) /* negate integer */
|
|
int *iptr; /* pointer to integer */
|
|
{
|
|
*iptr = -*iptr;
|
|
}
|
|
|
|
_aint(iptr1, iptr2, pflag) /* assign integer */
|
|
int *iptr1; /* pointer to fp */
|
|
int *iptr2; /* pointer to destination */
|
|
int pflag; /* short integer flag */
|
|
{
|
|
short *sptr;
|
|
if (pflag) {
|
|
sptr = iptr2;
|
|
*sptr = *iptr1;
|
|
}
|
|
else *iptr2 = *iptr1;
|
|
}
|
|
|
|
_neglong(lptr) /* negate long */
|
|
long *lptr; /* pointer to long integer */
|
|
{
|
|
*lptr = -*lptr;
|
|
}
|
|
|
|
_along(lptr1, lptr2) /* assign long */
|
|
long *lptr1; /* pointer to fp */
|
|
long *lptr2; /* pointer to destination */
|
|
{
|
|
*lptr2 = *lptr1;
|
|
}
|
|
|
|
_digit(ch, base) /* decode ch to binary */
|
|
int ch; /* character to decode */
|
|
int base; /* number base */
|
|
{
|
|
if (ch >= '0' && ch <= '9') ch -= 48;
|
|
else
|
|
if (isalpha(ch = toupper(ch))) ch -= 55;
|
|
else
|
|
return -1;
|
|
if (ch < base) return ch;
|
|
else return -1;
|
|
}
|
|
|
|
_dint(iptr, digit, base) /* decode an integer */
|
|
int *iptr; /* pointer to integer */
|
|
int digit; /* digit to add to integer */
|
|
int base; /* number base */
|
|
{
|
|
*iptr = *iptr * base + digit;
|
|
}
|
|
|
|
_dlong(lptr, digit, base) /* decode a long */
|
|
long *lptr; /* pointer to long */
|
|
int digit; /* digit to add to long */
|
|
int base; /* number base */
|
|
{
|
|
*lptr = *lptr * base + digit;
|
|
}
|
|
|
|
_dreal(s, fptr, pflag) /* decode a real */
|
|
char *s; /* pointer to decode string */
|
|
float *fptr; /* pointer to float */
|
|
int pflag; /* precision flag */
|
|
{
|
|
double atof(); /* string to double function */
|
|
double *dptr; /* pointer to double */
|
|
if (pflag) {
|
|
dptr = fptr;
|
|
*dptr = atof(s);
|
|
}
|
|
else
|
|
*fptr = (float) atof(s);
|
|
}
|
|
|
|
_mread(s) /* read character from string */
|
|
char **s; /* pointer to string */
|
|
{
|
|
if (*(*s) != '\0') return *(*s)++;
|
|
else return EOF;
|
|
}
|
|
|
|
_mungetc(c,s) /* unget character to string */
|
|
int c; /* dumy parameter */
|
|
char **s; /* pointer to string pointer */
|
|
{
|
|
--(*s);
|
|
return c;
|
|
}
|
|
|