home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
c
/
jplc1.arc
/
UNFORMAT.C
< prev
next >
Wrap
Text File
|
1988-07-22
|
6KB
|
266 lines
/* 1.1 01-08-86 (unformat.c)
************************************************************************
* Robert C. Tausworthe *
* Jet Propulsion Laboratory *
* Pasadena, CA 91009 1986 *
************************************************************************/
#include "defs.h"
#include "stdtyp.h"
#include "stdio.h"
#define NEXT TRUE /* Forward direction for getting chars. */
#define BACK FALSE /* Reverse direction for getting chars. */
#define LONGTYP TRUE /* Value to signal long or double. */
#define NORMTYP FALSE /* Value to denote normal width number. */
#define SHORTTYP -TRUE /* Value to denote short rather than int*/
/*----------------------------------------------------------------------*/
LOCAL int width;
LOCAL int (*xgetc)();
STRING index();
/************************************************************************/
unformat(getch, fmt, arglist) /* Perform scanf() on getch input medium,
using format fmt and argument list
pointed to by arglist. Returns number of
matched and assigned input items, or
EOF if input finished before fmt. */
/*----------------------------------------------------------------------*/
int (*getch)(); /* Note: getch(NEXT) performs a */
FAST STRING fmt; /* getc(medium), and getch(BACK) does */
int **arglist; /* an ungetc(c, medium). */
{
FAST int c;
double nxtfloat(), d;
long nxtnumber(), val;
int count, base;
STRING s;
BOOL suppress, numtyp;
char wkbuf[MAXLINE];
count = 0;
xgetc = getch;
/*\p*/
while (c = *fmt++)
{ if (c IS '%')
{ numtyp = NORMTYP;
suppress = FALSE;
width = MAXLINE;
if (*fmt IS '*')
{ ++fmt;
suppress = TRUE;
}
if (isdigit(*fmt))
{ width = 0;
do
{ width *= 10;
width += (*fmt - '0');
} while (isdigit(*++fmt));
}
if (*fmt IS 'l')
{ numtyp = LONGTYP;
++fmt;
}
if (*fmt IS 'h')
{ numtyp = SHORTTYP;
++fmt;
}
if (index("DOXEF", c = *fmt++))
numtyp = LONGTYP;
switch (c = tolower(c))
{ case ' ':
fmt--;
if (numtyp IS SHORTTYP)
c = 'd';
else
break;
case 'd':
case 'o':
case 'x':
base = (c IS 'd'? 10 : (c IS 'o' ? 8 : 16));
if (eatblanks())
return (count ? count : EOF);
val = nxtnumber(base);
if (NOT suppress)
{ if (numtyp IS LONGTYP)
*(long *)(*arglist++) = val;
else if (numtyp IS SHORTTYP)
*(short *)(*arglist++) = val;
else
**arglist++ = val;
++count;
}
break;
/*\p*/
case 'e':
case 'f':
if (eatblanks())
return (count ? count : EOF);
d = nxtfloat(wkbuf);
if (NOT suppress)
{ if (numtyp IS LONGTYP)
*(double *)(*arglist++) = d;
else
*(float *)(*arglist++) = d;
++count;
}
break;
case '[':
case 's':
if (c IS '[')
{ if (*fmt IS '^' OR *fmt IS '~')
{ numtyp = NORMTYP;
++fmt;
}
else
numtyp = LONGTYP;
for (s = wkbuf;(c = *fmt++) ISNT ']';)
*s++ = c;
*s = NULL;
}
else
{ numtyp = NORMTYP;
strcpy(wkbuf, " \t\n");
}
if (eatblanks())
return (count ? count : EOF);
if (NOT suppress)
s = (STRING) *arglist++;
while (width--)
{ if ((c = (*xgetc)(NEXT)) IS EOF)
break;
if (numtyp IS NORMTYP ?
(index(wkbuf, c) ISNT NULL) :
(index(wkbuf, c) IS NULL))
{ (*xgetc)(BACK);
break;
}
if (NOT suppress)
*s++ = c;
}
if (NOT suppress)
{ *s = NULL;
++count;
}
break;
/*\p*/
case 'c':
if ((c = (*xgetc)(NEXT)) IS EOF)
return (count ? count : EOF);
if (NOT suppress)
{ *(STRING)(*arglist++) = c;
++count;
}
break;
case '%':
goto match;
}
}
else if (isspace(c))
{ if (eatblanks())
return (count ? count : EOF);
}
else
{
match: if (eatblanks())
return (count ? count : EOF);
if ((*xgetc)(NEXT) ISNT c)
return count;
}
}
return count;
}
/************************************************************************/
LOCAL BOOL
eatblanks() /* Get characters from input medium until no longer
whitespace. Return FALSE normally, or TRUE at
end of line. */
/*----------------------------------------------------------------------*/
{
char c;
while (isspace(c = (*xgetc)(NEXT)))
;
if ((*xgetc)(BACK) IS EOF)
return TRUE;
else
return FALSE;
}
/*\p*********************************************************************/
LOCAL double
nxtfloat(buffer) /* Get the next ascii e-form or f-form from the
input medium, and return its value. Store
the ascii form in buffer. */
/*----------------------------------------------------------------------*/
STRING buffer;
{
FAST int c;
FAST STRING s;
TBOOL decmlpt, sign, exp;
double atof();
s = buffer;
sign = exp = decmlpt = FALSE;
while (width--)
{ c = (*xgetc)(NEXT);
if (NOT sign AND (c IS '-' OR c IS '+'))
sign = TRUE;
else if (NOT decmlpt AND c IS '.')
sign = decmlpt = TRUE;
else if (NOT exp AND (c IS 'e' OR c IS 'E'))
{ sign = FALSE;
exp = decmlpt = TRUE;
}
else if (NOT isdigit(c))
{ (*xgetc)(BACK);
break;
}
*s++ = c;
}
*s = 0;
return atof(buffer);
}
/*\p*********************************************************************/
LOCAL long
nxtnumber(base) /* Get the ascii string of a number with given
base from input medium, return its value. */
/*----------------------------------------------------------------------*/
{
int c;
long value;
BOOL minus;
LOCAL char digits[] = "0123456789abcdef";
if (width <= 0)
return 0L;
value = 0;
minus = FALSE;
if ((c = (*xgetc)(NEXT)) IS '-')
{ minus = TRUE;
--width;
}
else if (c IS '+')
--width;
else
(*xgetc)(BACK);
while (width--)
{ c = index(digits, tolower((*xgetc)(NEXT))) - digits;
if (c < 0 OR c >= base)
{ (*xgetc)(BACK);
break;
}
value *= base;
value += c;
}
return (minus ? -value : value);
}