Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

282 lines
9.0 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*****************************************************************************
*
* _ d o s c a n F u n c t i o n
* -------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "_doscan" is the common subroutine to "scanf", "fscanf", and
* "sscanf".
*
* Calling sequence:
* ret = _doscan(sp,fmt,aps)
* Where:
* WORD ret number items matched AND assigned
* EOF when encountered on stream sp
* FILE *sp pointer to input stream
* BYTE *fmt input specification string
* BYTE **aps pointer to (pointers to) arguments
*
* Edits:
* 3/15/84 sw Fix Atof / Nofloat problem
* 1/11/84 whf fix "%1s" bug
* 12/02/83 HY ???
*****************************************************************************/
#include "stdio.h"
#include "ctype.h"
#define INFINITY 32767
#define NXTNI(d) if( ((d)=getc(sp)) == EOF ) return(EOF)
WORD _doscan(sp,fmt,aps) /****************************/
REG FILE *sp; /* Stream ptr */
BYTE *fmt; /* Input format spec ptr */
BYTE **aps; /* Argument ptrs ptr */
{ /****************************/
REG BYTE c; /* Spec character */
REG WORD ni; /* Input char */
BOOLEAN noassign, /* Suppress assignment flag */
invert, /* Invert flag (_ismember) */
numfound, /* Number found flag */
longf, /* Long ptr flag */
shortf; /* Short ptr flag */
REG WORD width; /* Max field width */
WORD tval, /* Temp val holder */
base, /* For numeric conversion */
nitems; /* Number items mtchd & assd*/
LONG val, /* For numeric conversion */
locval; /* Local value area */
BYTE locbuf[BUFSIZ], /* Local buffer area */
*db, /* Destination ptr */
setbuf[128], /* Area for '[...]' sets */
*sb; /* Ptr into setbuf */
DOUBLE _atof(); /* */
/****************************/
nitems = 0; /* */
while( c = *fmt++ )
{
if( isspace(c) ) /* if space in spec str */
{ /* */
do{ /* deblank leading blanks */
c = *fmt++; /* */
} while( isspace(c) ); /* */
do{ /* deblank input stream */
NXTNI(ni); /* */
} while( isspace(ni) ); /* read past space in input */
ungetc(ni,sp); /* back up once */
if( c == NULL ) /* check for this here */
break; /* */
} /* c points to non space */
/****************************/
if( c != '%' ) /* match spec char (non'%')?*/
{ /* */
NXTNI(ni); /* grab from input */
if( ni != c ) /* & test */
{ /* */
ungetc(ni,sp); /* nope, put it back */
return(nitems); /* return early */
} /* */
continue; /* yup, do the next char */
} else /****************************/
c = *fmt++; /* look for an assignment */
noassign = FALSE; /* assume we will assign */
if( c == '*' ) /* unless they say otherwise*/
{
noassign++;
c = *fmt++;
}
width = INFINITY; /* assume no special width */
while( c >= '0' && c <= '9' ) /* unless they say otherwise*/
{
if( width == INFINITY )
width = 0;
width = 10 * width + (c - '0');
c = *fmt++;
}
longf = FALSE; /* assume ptrs not to LONGs */
shortf = FALSE; /* and not to SHORTs */
if( c == 'l' ) /* unless they say otherwise*/
{
longf++;
c = *fmt++;
} else if( c=='h' )
{
shortf++;
c = *fmt++;
}
/****************************/
switch( c ) /* which conversion char? */
{ /****************************/
case 'D': /* decimal input */
case 'd':
base = 10; goto procnum;
case 'O': /* octal input */
case 'o':
base = 8; goto procnum;
case 'X': /* hex input */
case 'x':
base = 16;
procnum: /****************************/
if( isupper(c) ) /* upper case means long */
longf++;
do{
NXTNI(ni); /* grab a char from input */
} while( isspace(ni) ); /* until non-blank */
if( noassign )
db = &locval; /* got to put it somewhere */
else db = *aps++; /* like to put it here */
invert = FALSE; /* assume pos number */
if( ni=='+' || ni=='-' ) { /* leading plus or minus */
if( ni == '-' )
invert++;
width--;
NXTNI(ni);
}
val = 0L; /* initial value */
numfound = FALSE; /* assume guilty til proven */
while( width-- > 0 ) { /* for each char ************/
tval = ni = toupper(ni); /* should work for numbers */
if( tval<'0' || tval>'F')
break;
if( tval>'9' && tval<'A')
break;
tval -= '0';
if( tval>9 )
tval = tval+('0'-'A'+10);
if( tval >= base )
break;
numfound++; /* is a number */
val = base * val + tval; /* */
NXTNI(ni); /* next input, please */
} /* *********************/
ungetc(ni,sp); /* back off input */
if( numfound == FALSE ) /* was it there? */
return(nitems); /* no, too bad */
if( invert ) /* leading minus? */
val = -val; /* */
if( longf ) /* store this value */
*( long *)db = val; /* somewhere */
else if( shortf ) /* */
*( short *)db = val; /* somehow */
else /* */
*( int *)db = val; /* sometime */
if( !noassign ) /* increment only if assign */
nitems++; /* */
break; /****************************/
case 's': /* string input */
case 'c': /* char input */
case '[': /* input 'one of' */
NXTNI(ni); /* grab a character */
if( c== 's' ) /* scan string **************/
{
sb = " \t\n"; /* point set to white chars */
while(_ismem(ni,sb,FALSE)) /* keep reading whitespace */
NXTNI(ni); /* if there is any */
invert = TRUE; /* after, read until whites */
} else if( c == 'c' ) /* scan char ****************/
{
sb = ""; /* Null set */
if( width == INFINITY ) /* handle default width */
width = 1;
invert = TRUE; /* invert "_ismem" func */
} else /* scan set *****************/
{ /* must be a '[' */
invert = FALSE;
if( (c = *fmt++) == '^' ) /* invert "_ismem" ??? */
{
invert = TRUE;
c = *fmt++;
}
for( sb=setbuf; c != NULL && c != ']'; sb++, c = *fmt++)
*sb = c;
*sb = NULL;
sb = setbuf;
}
if( noassign )
db = locbuf; /* give rtn somewhere to pt */
else db = *aps++; /* o.w. grab the desired ptr*/
while( width-- > 0 && _ismem(ni,sb,invert) )
{
*db++ = ni;
NXTNI(ni);
}
ungetc(ni,sp); /* we've always read 1 past */
if( c != 'c' ) /* not char type? */
*db = NULL; /* then null terminate */
if( !noassign )
nitems++; /* successful assignment */
break; /****************************/
/****************************/
case 'E': /*********** not fully implemented **********/
case 'e':
case 'F':
case 'f':
if( isupper(c) ) /* upper case means long */
longf++;
do {
NXTNI(ni); /* grab a char from input */
} while( isspace(ni) ); /* until non-blank */
if( noassign )
db = &locval; /* got to put it somewhere */
else db = *aps++; /* like to put it here */
sb = setbuf; /* setup up addr to hold string */
while (width-- > 0)
{
*sb++ = ni;
if ((ni < '0' || ni > '9') && (ni != '.')
&& (ni != 'e')
&& (ni != 'E')
&& (ni != '-')
&& (ni != '+'))
break;
NXTNI(ni);
}
ungetc(ni,sp);
*--sb = '\0';
if (longf)
*(double *)db = _atof(setbuf);
else
*(float *)db = (float) _atof(setbuf);
if (!noassign)
nitems++;
break;
case '%':
default:
NXTNI(ni);
if( ni != c ) /* must match c */
{
ungetc(ni,sp);
return(nitems);
}
break;
} /***** end switch ***********/
} /***** end while loop *******/
return(nitems); /* */
} /****************************/
/****************************/
MLOCAL WORD _ismem(c,set,invert) /* is_member of a set */
BYTE c; /* candidate for set element*/
BYTE *set; /* null terminated string */
BOOLEAN invert; /* invert sense of function */
{ /****************************/
REG WORD rv; /* temp return val */
rv = strchr(set,c); /* look for c in set */
return( invert ? !rv : rv ); /* return (maybe inverted) #*/
} /****************************/
return( invert ? !rv : rv ); /* return (maybe inverted) #*/
} /****************************/
return( invert ? !rv : rv ); /* return (maybe inverted) #*/
} /****************************/