1989-05-30 13:34:25 +00:00
|
|
|
/*
|
|
|
|
* doscan.c - scan formatted input
|
|
|
|
*/
|
1994-06-24 14:02:31 +00:00
|
|
|
/* $Id$ */
|
1989-05-30 13:34:25 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "loc_incl.h"
|
|
|
|
|
2018-06-23 16:54:40 +00:00
|
|
|
#if ACKCONF_WANT_STDIO
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
#if _EM_WSIZE == _EM_PSIZE
|
|
|
|
#define set_pointer(flags) /* nothing */
|
|
|
|
#elif _EM_LSIZE == _EM_PSIZE
|
|
|
|
#define set_pointer(flags) (flags |= FL_LONG)
|
1990-05-03 10:50:23 +00:00
|
|
|
#else
|
|
|
|
#error garbage pointer size
|
2018-06-21 20:33:47 +00:00
|
|
|
#define set_pointer(flags) /* compilation might continue */
|
1990-05-03 10:50:23 +00:00
|
|
|
#endif
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
#define NUMLEN 512
|
|
|
|
#define NR_CHARS 256
|
1989-05-30 13:34:25 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
static char Xtable[NR_CHARS];
|
|
|
|
static char inp_buf[NUMLEN];
|
1989-05-30 13:34:25 +00:00
|
|
|
|
|
|
|
/* Collect a number of characters which constitite an ordinal number.
|
|
|
|
* When the type is 'i', the base can be 8, 10, or 16, depending on the
|
|
|
|
* first 1 or 2 characters. This means that the base must be adjusted
|
|
|
|
* according to the format of the number. At the end of the function, base
|
|
|
|
* is then set to 0, so strtol() will get the right argument.
|
|
|
|
*/
|
2018-06-21 20:33:47 +00:00
|
|
|
static char*
|
2019-06-15 11:07:10 +00:00
|
|
|
o_collect(register int c, char type, int width, int* basep, int (*get)(void), void (*unget)(int c))
|
1989-05-30 13:34:25 +00:00
|
|
|
{
|
2018-06-21 20:33:47 +00:00
|
|
|
register char* bufp = inp_buf;
|
1989-12-18 15:04:14 +00:00
|
|
|
register int base;
|
1989-05-30 13:34:25 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case 'i': /* i means octal, decimal or hexadecimal */
|
|
|
|
case 'p':
|
|
|
|
case 'x':
|
|
|
|
case 'X':
|
|
|
|
base = 16;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
case 'u':
|
|
|
|
base = 10;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
base = 8;
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
base = 2;
|
|
|
|
break;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (c == '-' || c == '+')
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
*bufp++ = c;
|
1995-04-18 13:56:20 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (width && c == '0' && base == 16)
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
*bufp++ = c;
|
1989-12-18 15:04:14 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
2018-06-21 20:33:47 +00:00
|
|
|
if (c != 'x' && c != 'X')
|
|
|
|
{
|
|
|
|
if (type == 'i')
|
|
|
|
base = 8;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
else if (width)
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
*bufp++ = c;
|
1989-12-18 15:04:14 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
else if (type == 'i')
|
|
|
|
base = 10;
|
1989-05-30 13:34:25 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
while (width)
|
|
|
|
{
|
1989-12-18 15:04:14 +00:00
|
|
|
if (((base == 10) && isdigit(c))
|
|
|
|
|| ((base == 16) && isxdigit(c))
|
|
|
|
|| ((base == 8) && isdigit(c) && (c < '8'))
|
2018-06-21 20:33:47 +00:00
|
|
|
|| ((base == 2) && isdigit(c) && (c < '2')))
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
*bufp++ = c;
|
1989-12-18 15:04:14 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
else
|
|
|
|
break;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (width && c != EOF)
|
2019-06-15 11:07:10 +00:00
|
|
|
unget(c);
|
2018-06-21 20:33:47 +00:00
|
|
|
if (type == 'i')
|
|
|
|
base = 0;
|
1989-12-18 15:04:14 +00:00
|
|
|
*basep = base;
|
|
|
|
*bufp = '\0';
|
|
|
|
return bufp - 1;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
|
|
|
|
2018-06-22 22:04:14 +00:00
|
|
|
#if ACKCONF_WANT_STDIO_FLOAT
|
1989-05-30 13:34:25 +00:00
|
|
|
/* The function f_collect() reads a string that has the format of a
|
|
|
|
* floating-point number. The function returns as soon as a format-error
|
|
|
|
* is encountered, leaving the offending character in the input. This means
|
|
|
|
* that 1.el leaves the 'l' in the input queue. Since all detection of
|
|
|
|
* format errors is done here, _doscan() doesn't call strtod() when it's
|
1989-12-18 15:04:14 +00:00
|
|
|
* not necessary, although the use of the width field can cause incomplete
|
|
|
|
* numbers to be passed to strtod(). (e.g. 1.3e+)
|
1989-05-30 13:34:25 +00:00
|
|
|
*/
|
2018-06-21 20:33:47 +00:00
|
|
|
static char*
|
2019-06-15 11:07:10 +00:00
|
|
|
f_collect(register int c, register int width, int (*get)(void), void (*unget)(int c))
|
1989-05-30 13:34:25 +00:00
|
|
|
{
|
2018-06-21 20:33:47 +00:00
|
|
|
register char* bufp = inp_buf;
|
1989-05-30 13:34:25 +00:00
|
|
|
int digit_seen = 0;
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (c == '-' || c == '+')
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
*bufp++ = c;
|
1989-12-18 15:04:14 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
while (width && isdigit(c))
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
digit_seen++;
|
|
|
|
*bufp++ = c;
|
1989-12-18 15:04:14 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
if (width && c == '.')
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
*bufp++ = c;
|
2018-06-21 20:33:47 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
2018-06-21 20:33:47 +00:00
|
|
|
while (width && isdigit(c))
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
digit_seen++;
|
|
|
|
*bufp++ = c;
|
1989-12-18 15:04:14 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (!digit_seen)
|
|
|
|
{
|
|
|
|
if (width && c != EOF)
|
2019-06-15 11:07:10 +00:00
|
|
|
unget(c);
|
1989-05-30 13:34:25 +00:00
|
|
|
return inp_buf - 1;
|
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
else
|
|
|
|
digit_seen = 0;
|
1989-05-30 13:34:25 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (width && (c == 'e' || c == 'E'))
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
*bufp++ = c;
|
1989-12-18 15:04:14 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
2018-06-21 20:33:47 +00:00
|
|
|
if (width && (c == '+' || c == '-'))
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
*bufp++ = c;
|
1989-12-18 15:04:14 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
while (width && isdigit(c))
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
digit_seen++;
|
|
|
|
*bufp++ = c;
|
1989-12-18 15:04:14 +00:00
|
|
|
if (--width)
|
2019-06-15 11:07:10 +00:00
|
|
|
c = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
if (!digit_seen)
|
|
|
|
{
|
|
|
|
if (width && c != EOF)
|
2019-06-15 11:07:10 +00:00
|
|
|
unget(c);
|
1989-05-30 13:34:25 +00:00
|
|
|
return inp_buf - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (width && c != EOF)
|
2019-06-15 11:07:10 +00:00
|
|
|
unget(c);
|
1989-12-18 15:04:14 +00:00
|
|
|
*bufp = '\0';
|
|
|
|
return bufp - 1;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
2018-06-22 22:04:14 +00:00
|
|
|
#endif
|
1989-05-30 13:34:25 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* the routine that does the scanning
|
|
|
|
*/
|
|
|
|
|
2019-06-15 11:07:10 +00:00
|
|
|
int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int c))
|
1989-05-30 13:34:25 +00:00
|
|
|
{
|
2018-06-21 20:33:47 +00:00
|
|
|
int done = 0; /* number of items done */
|
|
|
|
int nrchars = 0; /* number of characters read */
|
|
|
|
int conv = 0; /* # of conversions */
|
|
|
|
int base; /* conversion base */
|
|
|
|
unsigned long val; /* an integer value */
|
|
|
|
register char* str; /* temporary pointer */
|
|
|
|
char* tmp_string; /* ditto */
|
|
|
|
unsigned width; /* width of field */
|
|
|
|
int flags; /* some flags */
|
|
|
|
int reverse; /* reverse the checking in [...] */
|
|
|
|
int kind;
|
|
|
|
register int ic; /* the input character */
|
2018-06-22 22:04:14 +00:00
|
|
|
#if ACKCONF_WANT_STDIO_FLOAT
|
2018-06-21 20:33:47 +00:00
|
|
|
long double ld_val;
|
1989-05-30 13:34:25 +00:00
|
|
|
#endif
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (!*format)
|
|
|
|
return 0;
|
1990-03-28 16:33:05 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (isspace(*format))
|
|
|
|
{
|
1989-12-18 15:04:14 +00:00
|
|
|
while (isspace(*format))
|
2018-06-21 20:33:47 +00:00
|
|
|
format++; /* skip whitespace */
|
2019-06-15 11:07:10 +00:00
|
|
|
ic = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
nrchars++;
|
2018-06-21 20:33:47 +00:00
|
|
|
while (isspace(ic))
|
|
|
|
{
|
2019-06-15 11:07:10 +00:00
|
|
|
ic = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
nrchars++;
|
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
if (ic != EOF)
|
2019-06-15 11:07:10 +00:00
|
|
|
unget(ic);
|
1989-12-18 15:04:14 +00:00
|
|
|
nrchars--;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
if (!*format)
|
|
|
|
break; /* end of format */
|
1989-12-18 15:04:14 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (*format != '%')
|
|
|
|
{
|
2019-06-15 11:07:10 +00:00
|
|
|
ic = get();
|
1990-07-11 09:08:33 +00:00
|
|
|
nrchars++;
|
2018-06-21 20:33:47 +00:00
|
|
|
if (ic != *format++)
|
|
|
|
{
|
|
|
|
if (ic != EOF)
|
2019-06-15 11:07:10 +00:00
|
|
|
unget(ic);
|
1992-01-24 13:05:30 +00:00
|
|
|
nrchars--;
|
2018-06-21 20:33:47 +00:00
|
|
|
break; /* error */
|
1992-01-24 13:05:30 +00:00
|
|
|
}
|
1989-05-30 13:34:25 +00:00
|
|
|
continue;
|
|
|
|
}
|
1990-07-11 09:08:33 +00:00
|
|
|
format++;
|
2018-06-21 20:33:47 +00:00
|
|
|
if (*format == '%')
|
|
|
|
{
|
2019-06-15 11:07:10 +00:00
|
|
|
ic = get();
|
1990-07-11 09:08:33 +00:00
|
|
|
nrchars++;
|
2018-06-21 20:33:47 +00:00
|
|
|
if (ic == '%')
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
format++;
|
|
|
|
continue;
|
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
else
|
|
|
|
break;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
|
|
|
flags = 0;
|
2018-06-21 20:33:47 +00:00
|
|
|
if (*format == '*')
|
|
|
|
{
|
1990-07-11 09:08:33 +00:00
|
|
|
format++;
|
1989-05-30 13:34:25 +00:00
|
|
|
flags |= FL_NOASSIGN;
|
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
if (isdigit(*format))
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
flags |= FL_WIDTHSPEC;
|
2018-06-21 20:33:47 +00:00
|
|
|
for (width = 0; isdigit(*format);)
|
1989-05-30 13:34:25 +00:00
|
|
|
width = width * 10 + *format++ - '0';
|
|
|
|
}
|
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
switch (*format)
|
|
|
|
{
|
|
|
|
case 'h':
|
|
|
|
flags |= FL_SHORT;
|
|
|
|
format++;
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
flags |= FL_LONG;
|
|
|
|
format++;
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
flags |= FL_LONGDOUBLE;
|
|
|
|
format++;
|
|
|
|
break;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
|
|
|
kind = *format;
|
2018-06-21 20:33:47 +00:00
|
|
|
if ((kind != 'c') && (kind != '[') && (kind != 'n'))
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
2019-06-15 11:07:10 +00:00
|
|
|
ic = get();
|
1989-05-30 13:34:25 +00:00
|
|
|
nrchars++;
|
1990-07-11 09:08:33 +00:00
|
|
|
} while (isspace(ic));
|
2018-06-21 20:33:47 +00:00
|
|
|
if (ic == EOF)
|
|
|
|
break; /* outer while */
|
|
|
|
}
|
|
|
|
else if (kind != 'n')
|
|
|
|
{ /* %c or %[ */
|
2019-06-15 11:07:10 +00:00
|
|
|
ic = get();
|
2018-06-21 20:33:47 +00:00
|
|
|
if (ic == EOF)
|
|
|
|
break; /* outer while */
|
1990-07-11 09:08:33 +00:00
|
|
|
nrchars++;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
switch (kind)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
/* not recognized, like %q */
|
|
|
|
return conv || (ic != EOF) ? done : EOF;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
if (!(flags & FL_NOASSIGN))
|
|
|
|
{ /* silly, though */
|
|
|
|
if (flags & FL_SHORT)
|
|
|
|
*va_arg(ap, short*) = (short)nrchars;
|
|
|
|
else if (flags & FL_LONG)
|
|
|
|
*va_arg(ap, long*) = (long)nrchars;
|
|
|
|
else
|
|
|
|
*va_arg(ap, int*) = (int)nrchars;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p': /* pointer */
|
|
|
|
set_pointer(flags);
|
1990-05-03 10:50:23 +00:00
|
|
|
/* fallthrough */
|
2018-06-21 20:33:47 +00:00
|
|
|
case 'b': /* binary */
|
|
|
|
case 'd': /* decimal */
|
|
|
|
case 'i': /* general integer */
|
|
|
|
case 'o': /* octal */
|
|
|
|
case 'u': /* unsigned */
|
|
|
|
case 'x': /* hexadecimal */
|
|
|
|
case 'X': /* ditto */
|
|
|
|
if (!(flags & FL_WIDTHSPEC) || width > NUMLEN)
|
|
|
|
width = NUMLEN;
|
|
|
|
if (!width)
|
|
|
|
return done;
|
|
|
|
|
2019-06-15 11:07:10 +00:00
|
|
|
str = o_collect(ic, kind, width, &base, get, unget);
|
2018-06-21 20:33:47 +00:00
|
|
|
if (str < inp_buf
|
|
|
|
|| (str == inp_buf
|
|
|
|
&& (*str == '-'
|
|
|
|
|| *str == '+')))
|
|
|
|
return done;
|
|
|
|
|
|
|
|
/*
|
1990-07-11 09:08:33 +00:00
|
|
|
* Although the length of the number is str-inp_buf+1
|
|
|
|
* we don't add the 1 since we counted it already
|
|
|
|
*/
|
2018-06-21 20:33:47 +00:00
|
|
|
nrchars += str - inp_buf;
|
1990-07-11 09:08:33 +00:00
|
|
|
|
1989-05-30 13:34:25 +00:00
|
|
|
if (!(flags & FL_NOASSIGN))
|
2018-06-21 20:33:47 +00:00
|
|
|
{
|
|
|
|
if (kind == 'd' || kind == 'i')
|
|
|
|
val = strtol(inp_buf, &tmp_string, base);
|
|
|
|
else
|
|
|
|
val = strtoul(inp_buf, &tmp_string, base);
|
|
|
|
if (flags & FL_LONG)
|
|
|
|
*va_arg(ap, unsigned long*) = (unsigned long)val;
|
|
|
|
else if (flags & FL_SHORT)
|
|
|
|
*va_arg(ap, unsigned short*) = (unsigned short)val;
|
|
|
|
else
|
|
|
|
*va_arg(ap, unsigned*) = (unsigned)val;
|
1989-12-18 15:04:14 +00:00
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
if (!(flags & FL_WIDTHSPEC))
|
|
|
|
width = 1;
|
1989-05-30 13:34:25 +00:00
|
|
|
if (!(flags & FL_NOASSIGN))
|
2018-06-21 20:33:47 +00:00
|
|
|
str = va_arg(ap, char*);
|
|
|
|
if (!width)
|
|
|
|
return done;
|
|
|
|
|
|
|
|
while (width && ic != EOF)
|
|
|
|
{
|
|
|
|
if (!(flags & FL_NOASSIGN))
|
|
|
|
*str++ = (char)ic;
|
|
|
|
if (--width)
|
|
|
|
{
|
2019-06-15 11:07:10 +00:00
|
|
|
ic = get();
|
2018-06-21 20:33:47 +00:00
|
|
|
nrchars++;
|
|
|
|
}
|
1989-12-18 15:04:14 +00:00
|
|
|
}
|
1989-05-30 13:34:25 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (width)
|
|
|
|
{
|
|
|
|
if (ic != EOF)
|
2019-06-15 11:07:10 +00:00
|
|
|
unget(ic);
|
2018-06-21 20:33:47 +00:00
|
|
|
nrchars--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
if (!(flags & FL_WIDTHSPEC))
|
|
|
|
width = 0xffff;
|
|
|
|
if (!(flags & FL_NOASSIGN))
|
|
|
|
str = va_arg(ap, char*);
|
|
|
|
if (!width)
|
|
|
|
return done;
|
|
|
|
|
|
|
|
while (width && ic != EOF && !isspace(ic))
|
|
|
|
{
|
|
|
|
if (!(flags & FL_NOASSIGN))
|
|
|
|
*str++ = (char)ic;
|
|
|
|
if (--width)
|
|
|
|
{
|
2019-06-15 11:07:10 +00:00
|
|
|
ic = get();
|
2018-06-21 20:33:47 +00:00
|
|
|
nrchars++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* terminate the string */
|
|
|
|
if (!(flags & FL_NOASSIGN))
|
|
|
|
*str = '\0';
|
|
|
|
if (width)
|
|
|
|
{
|
|
|
|
if (ic != EOF)
|
2019-06-15 11:07:10 +00:00
|
|
|
unget(ic);
|
2018-06-21 20:33:47 +00:00
|
|
|
nrchars--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '[':
|
|
|
|
if (!(flags & FL_WIDTHSPEC))
|
|
|
|
width = 0xffff;
|
|
|
|
if (!width)
|
|
|
|
return done;
|
|
|
|
|
|
|
|
if (*++format == '^')
|
|
|
|
{
|
|
|
|
reverse = 1;
|
|
|
|
format++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
reverse = 0;
|
1989-05-30 13:34:25 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
for (str = Xtable; str < &Xtable[NR_CHARS]; str++)
|
|
|
|
*str = 0;
|
1989-05-30 13:34:25 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (*format == ']')
|
|
|
|
Xtable[*format++] = 1;
|
1990-07-11 09:08:33 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
while (*format && *format != ']')
|
|
|
|
{
|
|
|
|
Xtable[*format++] = 1;
|
|
|
|
if (*format == '-')
|
|
|
|
{
|
1989-05-30 13:34:25 +00:00
|
|
|
format++;
|
2018-06-21 20:33:47 +00:00
|
|
|
if (*format
|
|
|
|
&& *format != ']'
|
|
|
|
&& *(format) >= *(format - 2))
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
for (c = *(format - 2) + 1; c <= *format; c++)
|
|
|
|
Xtable[c] = 1;
|
|
|
|
format++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Xtable['-'] = 1;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
if (!*format || !(Xtable[ic] ^ reverse))
|
|
|
|
{
|
|
|
|
if (ic != EOF)
|
2019-06-15 11:07:10 +00:00
|
|
|
unget(ic);
|
2018-06-21 20:33:47 +00:00
|
|
|
return done;
|
|
|
|
}
|
1990-07-11 09:08:33 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (!(flags & FL_NOASSIGN))
|
|
|
|
str = va_arg(ap, char*);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (!(flags & FL_NOASSIGN))
|
|
|
|
*str++ = (char)ic;
|
|
|
|
if (--width)
|
|
|
|
{
|
2019-06-15 11:07:10 +00:00
|
|
|
ic = get();
|
2018-06-21 20:33:47 +00:00
|
|
|
nrchars++;
|
|
|
|
}
|
|
|
|
} while (width && ic != EOF && (Xtable[ic] ^ reverse));
|
1989-12-18 15:04:14 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (width)
|
|
|
|
{
|
|
|
|
if (ic != EOF)
|
2019-06-15 11:07:10 +00:00
|
|
|
unget(ic);
|
2018-06-21 20:33:47 +00:00
|
|
|
nrchars--;
|
|
|
|
}
|
1989-05-30 13:34:25 +00:00
|
|
|
if (!(flags & FL_NOASSIGN))
|
2018-06-21 20:33:47 +00:00
|
|
|
{ /* terminate string */
|
|
|
|
*str = '\0';
|
1989-12-18 15:04:14 +00:00
|
|
|
}
|
2018-06-21 20:33:47 +00:00
|
|
|
break;
|
2018-06-22 22:04:14 +00:00
|
|
|
#if ACKCONF_WANT_STDIO_FLOAT
|
2018-06-21 20:33:47 +00:00
|
|
|
case 'e':
|
|
|
|
case 'E':
|
|
|
|
case 'f':
|
|
|
|
case 'g':
|
|
|
|
case 'G':
|
|
|
|
if (!(flags & FL_WIDTHSPEC) || width > NUMLEN)
|
|
|
|
width = NUMLEN;
|
|
|
|
|
|
|
|
if (!width)
|
|
|
|
return done;
|
2019-06-15 11:07:10 +00:00
|
|
|
str = f_collect(ic, width, get, unget);
|
2018-06-21 20:33:47 +00:00
|
|
|
|
|
|
|
if (str < inp_buf
|
|
|
|
|| (str == inp_buf
|
|
|
|
&& (*str == '-'
|
|
|
|
|| *str == '+')))
|
|
|
|
return done;
|
|
|
|
|
|
|
|
/*
|
1990-07-11 09:08:33 +00:00
|
|
|
* Although the length of the number is str-inp_buf+1
|
|
|
|
* we don't add the 1 since we counted it already
|
|
|
|
*/
|
2018-06-21 20:33:47 +00:00
|
|
|
nrchars += str - inp_buf;
|
1990-07-11 09:08:33 +00:00
|
|
|
|
2018-06-21 20:33:47 +00:00
|
|
|
if (!(flags & FL_NOASSIGN))
|
|
|
|
{
|
|
|
|
ld_val = strtod(inp_buf, &tmp_string);
|
|
|
|
if (flags & FL_LONGDOUBLE)
|
|
|
|
*va_arg(ap, long double*) = (long double)ld_val;
|
|
|
|
else if (flags & FL_LONG)
|
|
|
|
*va_arg(ap, double*) = (double)ld_val;
|
|
|
|
else
|
|
|
|
*va_arg(ap, float*) = (float)ld_val;
|
|
|
|
}
|
|
|
|
break;
|
1989-05-30 13:34:25 +00:00
|
|
|
#endif
|
2018-06-21 20:33:47 +00:00
|
|
|
} /* end switch */
|
1990-07-11 09:08:33 +00:00
|
|
|
conv++;
|
2018-06-21 20:33:47 +00:00
|
|
|
if (!(flags & FL_NOASSIGN) && kind != 'n')
|
|
|
|
done++;
|
1990-07-11 09:08:33 +00:00
|
|
|
format++;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
1990-04-04 15:52:01 +00:00
|
|
|
return conv || (ic != EOF) ? done : EOF;
|
1989-05-30 13:34:25 +00:00
|
|
|
}
|
2018-06-23 16:54:40 +00:00
|
|
|
|
|
|
|
#endif
|