home *** CD-ROM | disk | FTP | other *** search
- static char sccs_id[] = "@(#) scan.c 3.0 " __DATE__ " HJR";
-
- /* scan.c (c) Copyright 1990 H.Rogers */
-
- /* Implements __scanf(fp,format,argp,cnt) which is called by all
- * scanf() functions to perform formatted input. __scanf() returns a count
- * of the number of characters read. *cnt is assigned to an item count. */
-
- /* A conversion is of the form "%[*][width][size]function".
- * For full details RTFM for scanf(3). */
-
- #include <stddef.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdarg.h>
- #include <stdio.h>
-
- __STDIOLIB__
-
- #define ungetc(c,f) \
- (((f)->i_ptr > (f)->i_base) ? ((f)->i_cnt++,*--(f)->i_ptr = (c)) : -1)
-
- /* To avoid truncation SCBUFSIZ should be 256+.
- * This library will *not* buffer overflow unless SCBUFSIZ < 4. */
-
- #define SCBUFSIZ 256 /* size of buffer for %feEgG & %[ */
-
-
- /* the prototypes for the input functions */
-
- static int __s_nin (FILE *, va_list *, const char **);
-
- static int __s_char (FILE *, va_list *, const char **);
- static int __s_str (FILE *, va_list *, const char **);
- static int __s_sdec (FILE *, va_list *, const char **);
- static int __s_sint (FILE *, va_list *, const char **);
- static int __s_uoct (FILE *, va_list *, const char **);
- static int __s_udec (FILE *, va_list *, const char **);
- static int __s_uhex (FILE *, va_list *, const char **);
- static int __s_fdbl (FILE *, va_list *, const char **);
- static int __s_ptr (FILE *, va_list *, const char **);
- static int __s_sdel (FILE *, va_list *, const char **);
-
-
- /* __scnt is set to the number of characters read by __scanf() and
- * is used by __s_nin() to output the number of characters read. */
-
- static size_t __scnt;
-
- static int __scflag; /* assignment suppression flag */
- static int __scsize; /* -1 = unspecified */
- static unsigned int __scwidth; /* width */
-
- static signed char __scfnc[32] = /* conversions */
- {
- -1, -1,
- 1, /* %c */
- 3, /* %d */
- 8, /* %eE */
- 8, /* %f */
- 8, /* %gG */
- -1,
- 4, /* %i */
- -1, -1, -1, -1,
- 0, /* %n */
- 5, /* %o */
- 9, /* %p */
- -1, -1,
- 2, /* %s */
- -1,
- 6, /* %u */
- -1, -1,
- 7, /* %xX */
- -1, -1, -1, -1, -1, -1, -1, -1
- };
-
- /* __scfn[] is the array of input functions called by __scanf() -
- * They return a value indicating whether they successfully interpreted
- * the input or not. 0 indicates failure; a +ve value is a count
- * of the number of characters read. */
-
- static int (*__scfn[]) (FILE *, va_list *, const char **) =
- {
- __s_nin, /* %n no. of characters read so far */
- __s_char, /* %c character */
- __s_str, /* %s string */
- __s_sdec, /* %d signed decimal */
- __s_sint, /* %i signed integer */
- __s_uoct, /* %o unsigned octal */
- __s_udec, /* %u unsigned decimal */
- __s_uhex, /* %xX unsigned hex */
- __s_fdbl, /* %feEgG float (double) */
- __s_ptr, /* %p unsigned hex value of pointer */
- __s_sdel /* %[ delimited string */
- };
-
-
- /* __scanf() */
-
- int
- __scanf (register FILE * f, const char *format, va_list ap, int *cnt)
- {
- register const char *s1 = format;
- register int n = 0;
- register int c;
-
- for (;;)
- {
- if (!(c = *s1++))
- goto ret;
-
- if (isspace (c))
- continue; /* white space in formatting string is ignored */
-
- if (c != '%')
- {
- register int m, l = 0;
-
- match:
- do
- {
- if ((l++, m = getc (f)) < 0)
- {
- if (!n)
- goto eof;
- goto ret;
- }
- }
- while (isspace (m));
- __scnt += l;
- if (m == c)
- continue;
- (void) ungetc (m, f);
- goto ret;
- }
- else
- {
- if (!(c = *s1++))
- goto ret;
- if (c == '%')
- goto match;
- }
-
- { /* we now have a % conversion */
- register int i, j;
- const char *s;
-
- /* looking for "%[*][width][size]function" */
-
- /* set __scflag */
-
- __scflag = 0;
- if (c == '*')
- {
- if (!(c = *s1++))
- goto ret;
- __scflag = 1;
- }
-
- /* set __scwidth */
-
- __scwidth = 0;
- if (isdigit (c))
- {
- __scwidth = (unsigned int) strtoul (s1 - 1, (char **) &s, 0);
- s1 = s;
- if (!(c = *s1++))
- goto ret;
- if (__scwidth > SCBUFSIZ)
- __scwidth = SCBUFSIZ;
- }
-
- /* set __scsize */
-
- switch (c)
- {
- case 'h':
- __scsize = 0;
- if (!(c = *s1++))
- goto ret;
- break;
- case 'l':
- __scsize = 1;
- if (!(c = *s1++))
- goto ret;
- break;
- case 'L':
- __scsize = 2;
- if (!(c = *s1++))
- goto ret;
- break;
- default:
- __scsize = -1;
- break;
- }
-
- /* call appropriate input function */
-
- i = (c == '[') ? 10 : __scfnc[(_tolower (c) - 'a') & 31];
-
- if (i >= 0)
- {
- s = s1;
- j = (*__scfn[i]) (f, (va_list *) (&ap), &s);
- s1 = s;
-
- if (j < 0 && !n)
- goto eof;
- else if (j <= 0)
- goto ret;
- else
- {
- __scnt += j;
- if (!__scflag)
- n++;
- }
- }
- else
- {
- if (!n)
- goto eof;
- goto ret;
- }
- }
- }
-
- ret:*cnt = n;
- return (__scnt);
-
- eof:*cnt = 0;
- return (-1);
- }
-
-
- /* __s_nin() */
-
- static int
- __s_nin (register FILE * f, va_list * ap, const char **e)
- {
- if (!__scflag)
- {
- switch (__scsize)
- {
- case 0:
- *va_arg (*ap, short *) = (short) __scnt;
- break;
- case 1:
- *va_arg (*ap, long *) = (long) __scnt;
- break;
- default:
- *va_arg (*ap, int *) = (int) __scnt;
- break;
- }
- }
-
- return (0);
- }
-
- /* __s_char() */
-
- static int
- __s_char (register FILE * f, va_list * ap, const char **e)
- {
- register unsigned int w;
- register int n = 0;
- register char *s;
- register int c;
-
- w = __scwidth;
- if (!w)
- w = 1; /* default - 1 char */
-
- s = __scflag ? 0 : va_arg (*ap, char *);
-
- while (w)
- {
- if ((c = getc (f)) < 0)
- return (n ? n : -1);
- if (s)
- *s++ = c;
- n++, w--;
- }
-
- return (n);
- }
-
- /* __s_str() */
-
- static int
- __s_str (register FILE * f, va_list * ap, const char **e)
- {
- register unsigned int w;
- register int n = 0;
- register char *s;
- register int c;
-
- w = __scwidth;
- if (!w)
- w = SCBUFSIZ;
-
- s = __scflag ? 0 : va_arg (*ap, char *);
-
- do
- {
- if ((c = getc (f)) < 0)
- {
- if (s)
- *s = 0;
- return (-1);
- }
- }
- while (isspace (c));
-
- while (!isspace (c) && w)
- {
- if (s)
- *s++ = c;
- n++, w--;
- if ((c = getc (f)) < 0)
- {
- if (s)
- *s = 0;
- return (n);
- }
- }
-
- if (s)
- *s = 0;
- (void) ungetc (c, f);
-
- return (n);
- }
-
- /* __s_sdec() */
-
- static int
- __s_sdec (register FILE * f, va_list * ap, const char **e)
- {
- register unsigned int w;
- register int n = 0;
- register int c;
- register int i = 0, i_ = 0;
-
- w = __scwidth;
- if (!w)
- w = SCBUFSIZ;
-
- do
- {
- if ((c = getc (f)) < 0)
- return (-1);
- }
- while (isspace (c));
-
- if (c == '+' || c == '-')
- {
- if (c == '-')
- i_ = 1;
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
-
- while (isdigit (c) && w)
- {
- i = i * 10 + (c - '0');
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
-
- (void) ungetc (c, f);
-
- ret:if (!__scflag && n)
- {
- if (i_)
- i = -i;
- switch (__scsize)
- {
- case 0:
- *va_arg (*ap, short *) = (short) i;
- break;
- case 1:
- *va_arg (*ap, long *) = (long) i;
- break;
- default:
- *va_arg (*ap, int *) = i;
- break;
- }
- }
-
- return (n);
- }
-
- /* __s_sint() */
-
- static int
- __s_sint (register FILE * f, va_list * ap, const char **e)
- {
- register unsigned int w;
- register int n = 0;
- register int c;
- register int i = 0, i_ = 0;
- register int b = 10;
-
- w = __scwidth;
- if (!w)
- w = SCBUFSIZ;
-
- do
- {
- if ((c = getc (f)) < 0)
- return (-1);
- }
- while (isspace (c));
-
- if (c == '+' || c == '-')
- {
- if (c == '-')
- i_ = 1;
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
-
- if (c == '0' && w)
- {
- b = 010;
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- if ((c == 'x' || c == 'X') && w)
- {
- b = 0x10;
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
- }
-
- switch (b)
- {
- case 010:
- while (c >= '0' && c < '8' && w)
- {
- i = i * b + (c - '0');
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
- break;
- case 10:
- while (isdigit (c) && w)
- {
- i = i * b + (c - '0');
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
- break;
- case 0x10:
- while (isxdigit (c) && w)
- {
- i = i * b + ((c > '9') ? ((c & 31) + 9) : (c - '0'));
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
- break;
- }
-
- (void) ungetc (c, f);
-
- ret:if (!__scflag && n)
- {
- if (i_)
- i = -i;
- switch (__scsize)
- {
- case 0:
- *va_arg (*ap, short *) = (short) i;
- break;
- case 1:
- *va_arg (*ap, long *) = (long) i;
- break;
- default:
- *va_arg (*ap, int *) = i;
- break;
- }
- }
-
- return (n);
- }
-
- /* __s_uoct() */
-
- static int
- __s_uoct (register FILE * f, va_list * ap, const char **e)
- {
- register unsigned int w;
- register int n = 0;
- register int c;
- register unsigned int i = 0;
-
- w = __scwidth;
- if (!w)
- w = SCBUFSIZ;
-
- do
- {
- if ((c = getc (f)) < 0)
- return (-1);
- }
- while (isspace (c));
-
- while (c >= '0' && c <= '7' && w)
- {
- i = i * 010 + (c - '0');
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
-
- (void) ungetc (c, f);
-
- ret:if (!__scflag && n)
- {
- switch (__scsize)
- {
- case 0:
- *va_arg (*ap, short *) = (short) i;
- break;
- case 1:
- *va_arg (*ap, long *) = (long) i;
- break;
- default:
- *va_arg (*ap, int *) = i;
- break;
- }
- }
-
- return (n);
- }
-
- /* __s_udec() */
-
- static int
- __s_udec (register FILE * f, va_list * ap, const char **e)
- {
- register unsigned int w;
- register int n = 0;
- register int c;
- register unsigned int i = 0;
-
- w = __scwidth;
- if (!w)
- w = SCBUFSIZ;
-
- do
- {
- if ((c = getc (f)) < 0)
- return (-1);
- }
- while (isspace (c));
-
- while (isdigit (c) && w)
- {
- i = i * 10 + (c - '0');
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
-
- (void) ungetc (c, f);
-
- ret:if (!__scflag && n)
- {
- switch (__scsize)
- {
- case 0:
- *va_arg (*ap, short *) = (short) i;
- break;
- case 1:
- *va_arg (*ap, long *) = (long) i;
- break;
- default:
- *va_arg (*ap, int *) = i;
- break;
- }
- }
-
- return (n);
- }
-
- /* __s_uhex() */
-
- static int
- __s_uhex (register FILE * f, va_list * ap, const char **e)
- {
- register unsigned int w;
- register int n = 0;
- register int c;
- register unsigned int i = 0;
-
- w = __scwidth;
- if (!w)
- w = SCBUFSIZ;
-
- do
- {
- if ((c = getc (f)) < 0)
- return (-1);
- }
- while (isspace (c));
-
- if (c == '0' && w)
- {
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- if ((c == 'x' || c == 'X') && w)
- {
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
- }
-
- while (isxdigit (c) && w)
- {
- i = i * 0x10 + (isdigit (c) ? (c - '0') : ((c & 7) + 9));
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
- }
-
- (void) ungetc (c, f);
-
- ret:if (!__scflag && n)
- {
- switch (__scsize)
- {
- case 0:
- *va_arg (*ap, short *) = (short) i;
- break;
- case 1:
- *va_arg (*ap, long *) = (long) i;
- break;
- default:
- *va_arg (*ap, int *) = i;
- break;
- }
- }
-
- return (n);
- }
-
- /* __s_fdbl() */
-
- static int
- __s_fdbl (register FILE * f, va_list * ap, const char **e)
- {
- register unsigned int w;
- register int n = 0;
- register int c;
- register double i;
- register char *s;
- register int l = 0;
-
- #define F_SIGN 0001
- #define F_DP 0002
- #define F_XP 0004
- #define F_XSIGN 0010
-
- if (!__scflag)
- {
- if (!(s = __sbuf))
- if (!(s = __sbuf = malloc (SCBUFSIZ)))
- return (0);
- }
- else
- s = 0;
-
- w = __scwidth;
- if (!w)
- w = SCBUFSIZ;
-
- do
- {
- if ((c = getc (f)) < 0)
- return (-1);
- }
- while (isspace (c));
-
- if ((c == '-' || c == '+') && !(l & F_SIGN))
- {
- l |= F_SIGN;
- goto l1;
- }
-
- if (!isdigit (c))
- goto l2;
-
- l1:
-
- if (!w)
- goto ret;
-
- if (s)
- *s++ = c;
- n++, w--;
- if ((c = getc (f)) < 0)
- goto ret;
-
- if (isdigit (c))
- goto l1;
-
- l2:
-
- if ((c == '-' || c == '+') && (l & F_XP) && !(l & F_XSIGN))
- {
- l |= F_XSIGN;
- goto l1;
- }
- if (c == '.' && !(l & F_DP))
- {
- l |= F_DP;
- goto l1;
- }
- if ((c == 'e' || c == 'E') && !(l & F_XP))
- {
- l |= F_XP;
- goto l1;
- }
-
- ret:if (c >= 0)
- (void) ungetc (c, f);
-
- if (!__scflag && n)
- {
- *s = 0;
- i = strtod (__sbuf, 0);
- switch (__scsize)
- {
- case 2:
- *va_arg (*ap, long double *) = (long double) i;
- break;
- case 1:
- *va_arg (*ap, double *) = i;
- break;
- default:
- *va_arg (*ap, float *) = (float) i;
- break;
- }
- }
-
- return (n);
-
- #undef F_SIGN
- #undef F_DP
- #undef F_XP
- #undef F_XSIGN
- }
-
- /* __s_ptr() */
-
- static int
- __s_ptr (register FILE * f, va_list * ap, const char **e)
- {
- return (__s_uhex (f, ap, e));
- }
-
- /* __s_sdel() */
-
- static int
- __s_sdel (register FILE * f, va_list * ap, const char **e)
- {
- register const char *o;
- register char *s, *d;
- register int w, n = 0, m = 0, c;
-
- if (!(d = __sbuf))
- if (!(d = __sbuf = malloc (SCBUFSIZ)))
- return (0);
-
- o = (*e);
- if (*o == '^')
- o++, m++;
-
- w = SCBUFSIZ;
- if (*o == ']')
- *d++ = *o++, w--;
-
- while (w--)
- {
- if (!(c = *o++) || c == ']')
- break;
- *d++ = c;
- }
-
- (*e) = o;
- *d = 0;
- d = __sbuf;
-
- w = __scwidth;
- if (!w)
- w = SCBUFSIZ;
-
- s = __scflag ? 0 : va_arg (*ap, char *);
-
- if ((c = getc (f)) < 0)
- {
- if (s)
- *s = 0;
- return (-1);
- }
-
- while (w--)
- {
- if (!strchr (d, c) ^ m)
- break;
- if (s)
- *s++ = c;
- n++;
- if ((c = getc (f)) < 0)
- goto ret;
- }
-
- (void) ungetc (c, f);
-
- ret:if (s)
- *s = 0;
-
- return (n);
- }
-