dos_compilers/Mix Power C v1/SCANF.C
2024-07-01 15:26:34 -07:00

556 lines
20 KiB
C

/* scanf */
/* Copyright (c) Mix Software 1988 */
#include "stdio.h"
#include "stdarg.h"
static va_list parms; /* pointer to parameters */
static int base; /* number base */
static int ch; /* input character */
scanf(fs) /* standard routine */
char *fs;
{
int getc();
int ungetc();
va_start(parms, fs);
return _input(stdin, fs, getc, ungetc);
}
fscanf(fp, fs) /* standard routine */
char *fp, *fs;
{
int getc();
int ungetc();
va_start(parms, fs);
return _input(fp, fs, getc, ungetc);
}
sscanf(s,fs) /* standard routine */
char *s, *fs;
{
int _mread();
int _mungetc();
va_start(parms, fs);
return _input(&s, fs, _mread, _mungetc);
}
cscanf(fs)
char *fs;
{
static int _getche();
static int _un_getche();
va_start(parms, fs);
return _input(stdin, fs, _getche, _un_getche);
}
_input(fp, format, read, ungetc) /* input routine for */
/* scanf, sscanf, fscanf */
char *fp; /* pointer to input */
char *format; /* pointer to format string */
int (*read)(); /* character read function */
int (*ungetc)(); /* character unget function */
{
char c; /* format string character */
char *bufptr; /* pointer to buffer */
char far *fptr; /* far pointer to character */
int value; /* value of current digit */
int asflag; /* assignment supression flag */
int sflag; /* sign flag */
int lflag; /* long flag */
int iflag; /* flag for %i format */
int Nflag; /* Near pointer flag */
int Fflag; /* Far pointer flag */
int i; /* loop counter */
int width; /* maximum field width */
int valid; /* valid real number format */
int caret; /* flag for %[^ format */
int count=0; /* character count */
int number=0; /* number of characters read */
union {
int i;
long l;
char *ptr;
char near *nptr;
char far *fptr;
struct {
int offset;
int segment;
} half;
} accum; /* accumulator */
char buffer[256]; /* floating point string buffer */
int _digit(); /* decode digit function */
int _atoi(); /* convert string to integer */
int isspace(); /* isspace function */
int isdigit(); /* isdigit function */
char *strchr(); /* search for character in string */
double atof(); /* atof function */
STRING *stods(); /* convert string to dynamic string */
while (c = *format++) {
if (isspace(c)) {
while (isspace(*format)) format++;
while (isspace(ch = (*read)(fp))) number++;
(*ungetc)(ch, fp);
continue;
}
if (c != '%') {
number++;
if ((ch = (*read)(fp)) == c) continue;
else {
if (ch == EOF) return EOF;
else {
(*ungetc)(ch,fp);
return count;
}
}
}
sflag = asflag = lflag = Nflag = Fflag = iflag = 0;
if ((*format) == '*') { /* check for assignment suppression */
++asflag;
++format;
}
if (isdigit(*format)) width = _atoi(&format);
else width = -1;
if (*format == 'N') {
format++;
Nflag++;
}
else if (*format == 'F') {
format++;
Fflag++;
}
if (*format == 'l' || *format == 'L') { /* check for double precision */
format++;
lflag++;
}
else if (*format == 'h') format++;
if (width == 0) {
format++;
continue;
}
switch (*format++) {
case 'o': /* unsigned octal */
base = 8;
goto decode;
case 'X':
case 'x': /* unsigned hexadecimal */
base = 16;
goto decode;
case 'i': /* signed decimal, 0 or 0x prefix OK */
iflag++;
base = 10;
goto decode;
case 'd': /* signed decimal */
case 'u':
base = 10;
decode:
while (isspace(ch=(*read)(fp))) number++;
if (ch == EOF) return EOF;
number++;
width--;
if (width && (ch == '+' || ch == '-')) {
if (ch == '-') ++sflag;
if ((ch = (*read)(fp)) == EOF) return EOF;
number++;
width--;
}
if (iflag) {
if ((ch == '0') && width) {
base = 8;
if ((ch = (*read)(fp)) == 'x' || ch == 'X') {
number++;
width--;
base = 16;
if (width) {
ch = (*read)(fp);
number++;
width--;
}
if (ch == EOF) return EOF;
}
else {
(*ungetc)(ch, fp);
ch = '0';
}
}
}
accum.l = _digit();
if (accum.i == -1) {
(*ungetc)(ch,fp);
return count;
}
while (width) {
ch = (*read)(fp);
if ((value = _digit()) == -1) {
(*ungetc)(ch, fp);
break;
}
width--;
number++;
if (lflag)
accum.l = accum.l * base + value;
else
accum.i = accum.i * base + value;
}
if (!asflag) {
if (lflag) {
if (sflag) accum.l = -accum.l;
#ifdef LARGE
if (Nflag) *(va_arg(parms, long near*)) = accum.l;
#else
if (Fflag) *(va_arg(parms, long far*)) = accum.l;
#endif
else *(va_arg(parms, long*)) = accum.l;
}
else {
if (sflag) accum.i = -accum.i;
#ifdef LARGE
if (Nflag) *(va_arg(parms, int near*)) = accum.i;
#else
if (Fflag) *(va_arg(parms, int far*)) = accum.i;
#endif
else *(va_arg(parms, int*)) = accum.i;
}
count++;
}
break;
case 's': /* string */
while (isspace(ch=(*read)(fp))) number++;
if (ch == EOF) return EOF;
if (!asflag) {
#ifdef LARGE
if (Nflag) fptr = va_arg(parms, char near*);
#else
if (Fflag) fptr = va_arg(parms, char far*);
#endif
else fptr = va_arg(parms, char*);
}
while (!isspace(ch) && ch != EOF && width) {
if (!asflag) *fptr++ = ch;
ch = (*read)(fp);
number++;
width--;
}
(*ungetc)(ch,fp);
if (!asflag) {
*fptr = '\0';
++count;
}
break;
case '[': /* string delimited by [character set] */
if (!asflag) {
#ifdef LARGE
if (Nflag) fptr = va_arg(parms, char near*);
#else
if (Fflag) fptr = va_arg(parms, char far*);
#endif
else fptr = va_arg(parms, char*);
}
i = caret = 0;
if (*format == '^') {
caret++;
format++;
}
if (*format == ']' || *format == '-')
buffer[i++] = *format++;
while (i < 255 && *format != ']') {
if (*format == '-') {
format++;
c = buffer[i-1];
if (*format != ']' && *format > c) {
for (c++; i < 255 && c <= *format; c++)
buffer[i++] = c;
format++;
}
else buffer[i++] = '-';
}
else buffer[i++] = *format++;
}
format++;
buffer[i] = '\0';
i = number;
while (((caret && strchr(buffer, ch=(*read)(fp))==NULL) ||
(!caret && strchr(buffer, ch=(*read)(fp))!=NULL)) &&
ch != EOF && width) {
if (!asflag) *fptr++ = ch;
number++;
width--;
}
(*ungetc)(ch,fp);
if (number == i) return count;
if (!asflag) {
*fptr = '\0';
++count;
}
break;
case 'c': /* character */
if ((ch = (*read)(fp)) == EOF) return EOF;
number++;
if (!asflag) {
#ifdef LARGE
if (Nflag) fptr = va_arg(parms, char near*);
#else
if (Fflag) fptr = va_arg(parms, char far*);
#endif
else fptr = va_arg(parms, char*);
*fptr = ch;
++count;
}
if (width > 0) {
width--;
while (width > 0) {
if ((ch = (*read)(fp)) == EOF) return EOF;
number++;
width--;
if (!asflag) *(++fptr) = ch;
}
}
break;
case 'n':
if (lflag) {
#ifdef LARGE
if (Nflag) *(va_arg(parms, int near*)) = number;
#else
if (Fflag) *(va_arg(parms, int far*)) = number;
#endif
else *(va_arg(parms, int*)) = number;
}
else {
#ifdef LARGE
if (Nflag) *(va_arg(parms, long near*)) = number;
#else
if (Fflag) *(va_arg(parms, long far*)) = number;
#endif
else *(va_arg(parms, long*)) = number;
}
break;
case 'p':
while (isspace(ch=(*read)(fp))) number++;
if (ch == EOF) return EOF;
number++;
width--;
base = 16;
accum.half.segment = 0;
accum.i = _digit();
if (accum.i == -1) {
(*ungetc)(ch,fp);
return count;
}
while (width) {
ch = (*read)(fp);
if ((value = _digit()) == -1) {
(*ungetc)(ch, fp);
break;
}
width--;
number++;
accum.l = (accum.l << 4) + value;
}
#ifdef LARGE
if (!Nflag && ch == ':') {
#else
if (Fflag && ch == ':') {
#endif
(*read)(fp); /* consume the ':' */
accum.half.segment = accum.half.offset;
accum.half.offset = 0;
while (width) {
ch = (*read)(fp);
if ((value = _digit()) == -1) {
(*ungetc)(ch, fp);
break;
}
width--;
number++;
accum.half.offset=(accum.half.offset << 4) + value;
}
}
if (!asflag) {
#ifdef LARGE
if (Nflag) *(va_arg(parms, char near**)) = accum.nptr;
#else
if (Fflag) *(va_arg(parms, char far**)) = accum.fptr;
#endif
else *(va_arg(parms, char **)) = accum.ptr;
count++;
}
break;
case 'e':
case 'E':
case 'f': /* floating point */
case 'g':
case 'G':
while (isspace(ch=(*read)(fp))) number++;
if (ch == EOF) return EOF;
valid = 0;
bufptr = buffer;
if (ch == '+' || ch == '-') {
*bufptr++ = ch;
ch = (*read)(fp);
number++;
width--;
}
while ((ch >= '0' && ch <= '9') && width) {
*bufptr++ = ch;
valid++;
ch = (*read)(fp);
number++;
width--;
}
if (ch == '.' && width) {
*bufptr++ = ch;
ch = (*read)(fp);
number++;
width--;
}
while ((ch >= '0' && ch <= '9') && width) {
*bufptr++ = ch;
valid++;
ch = (*read)(fp);
number++;
width--;
}
if ((ch == 'E' || ch == 'e') && valid && width) {
*bufptr++ = 'E';
ch = (*read)(fp);
number++;
width--;
if ((ch == '+' || ch == '-') && width) {
*bufptr++ = ch;
ch = (*read)(fp);
number++;
width--;
}
while ((ch >= '0' && ch <= '9') && width) {
*bufptr++ = ch;
ch = (*read)(fp);
number++;
width--;
}
}
(*ungetc)(ch, fp);
if (!valid) return count;
*bufptr = '\0';
if (!asflag) {
if (lflag) {
#ifdef LARGE
if (Nflag)
*(va_arg(parms, double near*)) = atof(buffer);
#else
if (Fflag)
*(va_arg(parms, double far*)) = atof(buffer);
#endif
else
*(va_arg(parms, double*)) = atof(buffer);
}
else {
#ifdef LARGE
if (Nflag)
*(va_arg(parms, float near*)) = atof(buffer);
#else
if (Fflag)
*(va_arg(parms, float far*)) = atof(buffer);
#endif
else
*(va_arg(parms, float*)) = atof(buffer);
}
++count;
}
break;
#ifdef DYNAMIC
case 'y': /* dynamic string */
while (isspace(ch=(*read)(fp))) number++;
if (ch == EOF) return EOF;
i = 0;
bufptr = buffer;
while (width && !isspace(ch) && ch != EOF) {
if (i < 255) *bufptr++ = ch;
ch = (*read)(fp);
number++;
width--;
}
*bufptr = '\0';
(*ungetc)(ch,fp);
if (!asflag) {
*(va_arg(parms, char**)) = stods(buffer);
++count;
}
break;
#endif
default :
number++;
if ((ch = (*read)(fp)) == *(format-1)) continue;
else {
if (ch == EOF) return EOF;
else {
(*ungetc)(ch,fp);
return count;
}
}
}
}
return count;
}
_digit() /* decode ch to binary */
{
int n;
if (ch >= '0' && ch <= '9') n = ch - 48;
else if (ch >= 'A' && ch <= 'F') n = ch - 55;
else if (ch >= 'a' && ch <= 'f') n = ch - 87;
else return -1;
if (n < base) return n;
else return -1;
}
_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 */
{
if (c != EOF) *(--(*s)) = c;
return c;
}
static _getche()
{
extern static int _un_getch;
int ch = _un_getch;
if (ch != EOF) {
_un_getch = EOF;
return ch;
}
else return getche();
}
static _un_getche(ch)
int ch;
{
extern static int _un_getch;
if (_un_getch != EOF) return EOF;
_un_getch = ch;
return ch;
}
static int _un_getch = EOF;