Logo Search packages:      
Sourcecode: linux86 version File versions  Download package

scanf.c

/*
 * This file based on scanf.c from 'Dlibs' on the atari ST  (RdeBath)
 *
 * 19-OCT-88: Dale Schumacher
 * > John Stanley has again been a great help in debugging, particularly
 * > with the printf/scanf functions which are his creation.  
 *
 *    Dale Schumacher                         399 Beacon Ave.
 *    (alias: Dalnefre')                      St. Paul, MN  55104
 *    dal@syntel.UUCP                         United States of America
 *  "It's not reality that's important, but how you perceive things."
 *
 */

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
#include <stdarg.h>
#define va_strt      va_start
#else
#include <varargs.h>
#define va_strt(p,i) va_start(p)
#endif

#ifdef L_scanf
#if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
int scanf(const char * fmt, ...)
#else
int scanf(fmt, va_alist)
__const char *fmt;
va_dcl
#endif
{
  va_list ptr;
  int rv;
  va_strt(ptr, fmt);
  rv = vfscanf(stdin,fmt,ptr);
  va_end(ptr);
  return rv;
}
#endif

#ifdef L_sscanf
#if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
int sscanf(char * sp, const char * fmt, ...)
#else
int sscanf(sp, fmt, va_alist)
char * sp;
__const char *fmt;
va_dcl
#endif
{
static FILE  string[1] =
{
   {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1,
    _IOFBF | __MODE_READ}
};

  va_list ptr;
  int rv;
  va_strt(ptr, fmt);
  string->bufpos = sp;
  rv = vfscanf(string,fmt,ptr);
  va_end(ptr);
  return rv;
}
#endif

#ifdef L_fscanf
#if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
int fscanf(FILE * fp, const char * fmt, ...)
#else
int fscanf(fp, fmt, va_alist)
FILE * fp;
__const char *fmt;
va_dcl
#endif
{
  va_list ptr;
  int rv;
  va_strt(ptr, fmt);
  rv = vfscanf(fp,fmt,ptr);
  va_end(ptr);
  return rv;
}
#endif

#ifdef L_vscanf
int vscanf(fmt, ap)
__const char *fmt;
va_list ap;
{
  return vfscanf(stdin,fmt,ap);
}
#endif

#ifdef L_vsscanf
int vsscanf(sp, fmt, ap)
char * sp;
__const char *fmt;
{
static FILE  string[1] =
{
   {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1,
    _IOFBF | __MODE_READ}
};

  string->bufpos = sp;
  return vfscanf(string,fmt,ap);
}
#endif

#ifdef L_vfscanf
/* #define  skip()      do{c=getc(fp); if (c<1) goto done;}while(isspace(c))*/

#define     skip()      while(isspace(c)) { if ((c=getc(fp))<1) goto done; }

#if FLOATS
/* fp scan actions */
#define F_NADA    0     /* just change state */
#define F_SIGN    1     /* set sign */
#define F_ESIGN   2     /* set exponent's sign */
#define F_INT     3     /* adjust integer part */
#define F_FRAC    4     /* adjust fraction part */
#define F_EXP     5     /* adjust exponent part */
#define F_QUIT    6

#define NSTATE    8
#define FS_INIT         0     /* initial state */
#define FS_SIGNED 1     /* saw sign */
#define FS_DIGS         2     /* saw digits, no . */
#define FS_DOT          3     /* saw ., no digits */
#define FS_DD           4     /* saw digits and . */
#define FS_E            5     /* saw 'e' */
#define FS_ESIGN  6     /* saw exp's sign */
#define FS_EDIGS  7     /* saw exp's digits */

#define FC_DIG          0
#define FC_DOT          1
#define FC_E            2
#define FC_SIGN         3

/* given transition,state do what action? */
int fp_do[][NSTATE] = {
      {F_INT,F_INT,F_INT,
       F_FRAC,F_FRAC,
       F_EXP,F_EXP,F_EXP},    /* see digit */
      {F_NADA,F_NADA,F_NADA,
       F_QUIT,F_QUIT,F_QUIT,F_QUIT,F_QUIT},     /* see '.' */
      {F_QUIT,F_QUIT,
       F_NADA,F_QUIT,F_NADA,
       F_QUIT,F_QUIT,F_QUIT}, /* see e/E */
      {F_SIGN,F_QUIT,F_QUIT,F_QUIT,F_QUIT,
       F_ESIGN,F_QUIT,F_QUIT},      /* see sign */
};
/* given transition,state what is new state? */
int fp_ns[][NSTATE] = {
      {FS_DIGS,FS_DIGS,FS_DIGS,
       FS_DD,FS_DD,
       FS_EDIGS,FS_EDIGS,FS_EDIGS}, /* see digit */
      {FS_DOT,FS_DOT,FS_DD,
       },   /* see '.' */
      {0,0,
       FS_E,0,FS_E,
      },    /* see e/E */
      {FS_SIGNED,0,0,0,0,
       FS_ESIGN,0,0},   /* see sign */
};
/* which states are valid terminators? */
int fp_sval[NSTATE] = {
      0,0,1,0,1,0,0,1
};
#endif

vfscanf(fp, fmt, ap)
register FILE *fp;
register char *fmt;
va_list ap;

{
   register long n;
   register int c, width, lval, cnt = 0;
   int   store, neg, base, wide1, endnull, rngflag, c2;
   register unsigned char *p;
   unsigned char delim[128], digits[17], *q;
#if FLOATS
   long  frac, expo;
   int   eneg, fraclen, fstate, trans;
   double fx, fp_scan();
#endif

   if (!*fmt)
      return (0);

   c = getc(fp);
   while (c > 0)
   {
      store = 0;
      if (*fmt == '%')
      {
       n = 0;
       width = -1;
       wide1 = 1;
       base = 10;
       lval = (sizeof(long) == sizeof(int));
       store = 1;
       endnull = 1;
       neg = -1;

       strcpy(delim, "\011\012\013\014\015 ");
       strcpy(digits, "0123456789ABCDEF");

       if (fmt[1] == '*')
       {
          endnull = store = 0;
          ++fmt;
       }

       while (isdigit(*++fmt))/* width digit(s) */
       {
          if (width == -1)
             width = 0;
          wide1 = width = (width * 10) + (*fmt - '0');
       }
       --fmt;
       fmtnxt:
       ++fmt;
       switch (tolower(*fmt)) /* tolower() is a MACRO! */
       {
       case '*':
          endnull = store = 0;
          goto fmtnxt;

       case 'l':        /* long data */
          lval = 1;
          goto fmtnxt;
       case 'h':        /* short data */
          lval = 0;
          goto fmtnxt;

       case 'i':        /* any-base numeric */
          base = 0;
          goto numfmt;

       case 'b':        /* unsigned binary */
          base = 2;
          goto numfmt;

       case 'o':        /* unsigned octal */
          base = 8;
          goto numfmt;

       case 'x':        /* unsigned hexadecimal */
          base = 16;
          goto numfmt;

       case 'd':        /* SIGNED decimal */
          neg = 0;
          /* FALL-THRU */

       case 'u':        /* unsigned decimal */
        numfmt:skip();

          if (isupper(*fmt))
             lval = 1;

          if (!base)
          {
             base = 10;
             neg = 0;
             if (c == '%')
             {
              base = 2;
              goto skip1;
             }
             else if (c == '0')
             {
              c = getc(fp);
              if (c < 1)
                 goto savnum;
              if ((c != 'x')
                  && (c != 'X'))
              {
                 base = 8;
                 digits[8] = '\0';
                 goto zeroin;
              }
              base = 16;
              goto skip1;
             }
          }

          if ((neg == 0) && (base == 10)
            && ((neg = (c == '-')) || (c == '+')))
          {
           skip1:
             c = getc(fp);
             if (c < 1)
              goto done;
          }

          digits[base] = '\0';
          p = ((unsigned char *)
             strchr(digits, toupper(c)));

          if ((!c || !p) && width)
             goto done;

          while (p && width-- && c)
          {
             n = (n * base) + (p - digits);
             c = getc(fp);
           zeroin:
             p = ((unsigned char *)
                strchr(digits, toupper(c)));
          }
        savnum:
          if (store)
          {
             if (neg == 1)
              n = -n;
             if (lval)
              *va_arg(ap, long*) = n;
             else
              *va_arg(ap, short*) = n;
             ++cnt;
          }
          break;

#if FLOATS
       case 'e':        /* float */
       case 'f':
       case 'g':
          skip();

          if (isupper(*fmt))
             lval = 1;

          fstate = FS_INIT;
          neg = 0;
          eneg = 0;
          n = 0;
          frac = 0;
          expo = 0;
          fraclen = 0;

          while (c && width--)
          {
             if (c >= '0' && c <= '9')
              trans = FC_DIG;
             else if (c == '.')
              trans = FC_DOT;
             else if (c == '+' || c == '-')
              trans = FC_SIGN;
             else if (tolower(c) == 'e')
              trans = FC_E;
             else
              goto fdone;

             switch (fp_do[trans][fstate])
             {
             case F_SIGN:
              neg = (c == '-');
              break;
             case F_ESIGN:
              eneg = (c == '-');
              break;
             case F_INT:
              n = 10 * n + (c - '0');
              break;
             case F_FRAC:
              frac = 10 * frac + (c - '0');
              fraclen++;
              break;
             case F_EXP:
              expo = 10 * expo + (c - '0');
              break;
             case F_QUIT:
              goto fdone;
             }
             fstate = fp_ns[trans][fstate];
             c = getc(fp);
          }

        fdone:
          if (!fp_sval[fstate])
             goto done;
          if (store)
          {
             fx = fp_scan(neg, eneg, n, frac, expo, fraclen);
             if (lval)
              *va_arg(ap, double *) = fx;
             else
              *va_arg(ap, float *) = fx;
             ++cnt;
          }
          break;
#endif

       case 'c':        /* character data */
          width = wide1;
          lval = endnull = 0;
          delim[0] = '\0';
          goto strproc;

       case '[':        /* string w/ delimiter set */

          /* get delimiters */
          p = delim;

          if (*++fmt == '^')
          {
             fmt++;
             lval = 0;
          }
          else
             lval = 1;

          rngflag = 2;
          if ((*fmt == ']') || (*fmt == '-'))
          {
             *p++ = *fmt++;
             rngflag = 0;
          }

          while (*fmt != ']')
          {
             if (*fmt == '\0')
              goto done;
             switch (rngflag)
             {
             case 1:
              c2 = *(p - 2);
              if (c2 <= *fmt)
              {
                 p -= 2;
                 while (c2 < *fmt)
                  *p++ = c2++;
                 rngflag = 2;
                 break;
              }
              /* fall thru intentional */

             case 0:
              rngflag = (*fmt == '-');
              break;

             case 2:
              rngflag = 0;
             }

             *p++ = *fmt++;
          }

          *p = '\0';
          goto strproc;

       case 's':        /* string data */
          lval = 0;
          skip();
        strproc:
          /* process string */
          p = va_arg(ap, unsigned char *);

          /* if the 1st char fails, match fails */
          if (width)
          {
             q = ((unsigned char *)
                strchr(delim, c));
             if ((c < 1) || lval == (q==0))
             {
              if (endnull)
                 *p = '\0';
              goto done;
             }
          }

          for (;;)            /* FOREVER */
          {
             if (store)
              *p++ = c;
             if (((c = getc(fp)) < 1) ||
               (--width == 0))
              break;

             q = ((unsigned char *)
                strchr(delim, c));
             if (lval == (q==0))
                break;
          }

          if (store)
          {
             if (endnull)
              *p = '\0';
             ++cnt;
          }
          break;

       case '\0':       /* early EOS */
          --fmt;
          /* FALL THRU */

       default:
          goto cmatch;
       }
      }
      else if (isspace(*fmt)) /* skip whitespace */
      {
       skip();
      }
      else
      {                       /* normal match char */
       cmatch:
       if (c != *fmt)
          break;
       c = getc(fp);
      }

      if (!*++fmt)
       break;
   }

 done:                        /* end of scan */
   if ((c == EOF) && (cnt == 0))
      return (EOF);

   if( c != EOF )
      ungetc(c, fp);
   return (cnt);
}

#endif


Generated by  Doxygen 1.6.0   Back to index