⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vfscanf.cxx

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 CXX
📖 第 1 页 / 共 3 页
字号:
                case 'f':
                    /* no need to fix base here */
                    if (base <= 10)
                        break;  /* not legal here */
                    flags &= ~(SIGNOK | PFXOK | NDIGITS);
                    goto ok;

                    /* sign ok only as first character */
                case '+':
                case '-':
                    if (flags & SIGNOK)
                    {
                        flags &= ~SIGNOK;
                        goto ok;
                    }
                    break;

                    /* x ok iff flag still set & 2nd char */
                case 'x':
                case 'X':
                    if (flags & PFXOK && p == buf + 1)
                    {
                        base = 16;/* if %i */
                        flags &= ~PFXOK;
                        goto ok;
                    }
                    break;
                }

                /*
                 * If we got here, c is not a legal character
                 * for a number.  Stop accumulating digits.
                 */
                break;
            ok:
                /*
                 * c is legal: store it and look at the next.
                 */
                *p++ = c;
                INC_CURR_POS;
                if (SPACE_LEFT == 0)
#ifndef REDHAT_NEC
                    if (REFILL)
#endif
                        break;          /* EOF */
            }
            /*
             * If we had only a sign, it is no good; push back the sign.
             * If the number ends in `x', it was [sign] '0' 'x', so push
             * back the x and treat it as [sign] '0'.
             */
            if (flags & NDIGITS)
            {
                if (p > buf)
                    _CAST_VOID ungetc (*(u_char *)-- p, fp);
                goto match_failure;
            }
            c = ((u_char *) p)[-1];
            if (c == 'x' || c == 'X')
            {
                --p;
                /*(void)*/ ungetc (c, fp);
            }
            if ((flags & SUPPRESS) == 0)
            {
                u_long res;

                *p = 0;
                res = (*ccfn) (buf, (char **) NULL, base);
                if (flags & POINTER)
                    *(va_arg (ap, char **)) = (char *) (CYG_ADDRESS) res;
                else if (flags & SHORT)
                {
                    sp = va_arg (ap, short *);
                    *sp = res;
                }
                else if (flags & LONG)
                {
                    lp = va_arg (ap, long *);
                    *lp = res;
                }
                else
                {
                    ip = va_arg (ap, int *);
                    *ip = res;
                }
                nassigned++;
            }
            nread += p - buf;
            break;

        case CT_FLOAT:
            /* scan a floating point number as if by strtod */

#ifdef hardway
            if (width == 0 || width > sizeof (buf) - 1)
                width = sizeof (buf) - 1;
#else
            /* size_t is unsigned, hence this optimisation */
            if (--width > sizeof (buf) - 2)
                width = sizeof (buf) - 2;
            width++;
#endif // ifdef hardway

            flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
            for (p = buf; width; width--)
            {
                c = *CURR_POS;
                /*
                 * This code mimicks the integer conversion
                 * code, but is much simpler.
                 */
                switch (c)
                {

                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    flags &= ~(SIGNOK | NDIGITS);
                    goto fok;

                case '+':
                case '-':
                    if (flags & SIGNOK)
                    {
                        flags &= ~SIGNOK;
                        goto fok;
                    }
                    break;
                case '.':
                    if (flags & DPTOK)
                    {
                        flags &= ~(SIGNOK | DPTOK);
                        goto fok;
                    }
                    break;
                case 'e':
                case 'E':
                    /* no exponent without some digits */
                    if ((flags & (NDIGITS | EXPOK)) == EXPOK)
                    {
                        flags =
                            (flags & ~(EXPOK | DPTOK)) |
                            SIGNOK | NDIGITS;
                        goto fok;
                    }
                    break;
                }
                break;
            fok:
                *p++ = c;
                INC_CURR_POS;
                if (SPACE_LEFT == 0)
#ifndef REDHAT_NEC
                    if (REFILL)
#endif
                        break;          /* EOF */
            }
            /*
             * If no digits, might be missing exponent digits
             * (just give back the exponent) or might be missing
             * regular digits, but had sign and/or decimal point.
             */
            if (flags & NDIGITS)
            {
                if (flags & EXPOK)
                {
                    /* no digits at all */
                    while (p > buf)
                        ungetc (*(u_char *)-- p, fp);
                    goto match_failure;
                }
                /* just a bad exponent (e and maybe sign) */
                c = *(u_char *)-- p;
                if (c != 'e' && c != 'E')
                {
                    _CAST_VOID ungetc (c, fp); /* sign */
                    c = *(u_char *)-- p;
                }
                _CAST_VOID ungetc (c, fp);
            }
            if ((flags & SUPPRESS) == 0)
            {
                double res;

                *p = 0;
#ifdef CYGSEM_LIBC_STDIO_SCANF_FLOATING_POINT
                res = atof (buf);
#else
                res = 0.0;
#endif
                if (flags & LONG)
                {
                    dp = va_arg (ap, double *);
                    *dp = res;
                }
                else if (flags & LONGDBL)
                {
                    ldp = va_arg (ap, long double *);
                    *ldp = res;
                }
                else
                {
                    flp = va_arg (ap, float *);
                    *flp = res;
                }
                nassigned++;
            }
            nread += p - buf;
            break;
        }
    }

input_failure:
    return nassigned ? nassigned : -1;
match_failure:
    return nassigned;
} // vfscanf()

/*
 * Fill in the given table from the scanset at the given format
 * (just after `[').  Return a pointer to the character past the
 * closing `]'.  The table has a 1 wherever characters should be
 * considered part of the scanset.
 */

/*static*/
u_char *
__sccl (char *tab, u_char *fmt)
{
    int c, n, v;

    /* first `clear' the whole table */
    c = *fmt++;                 /* first char hat => negated scanset */
    if (c == '^')
    {
        v = 1;                  /* default => accept */
        c = *fmt++;             /* get new first char */
    }
    else
        v = 0;                  /* default => reject */
    /* should probably use memset here */
    for (n = 0; n < 256; n++)
        tab[n] = v;
    if (c == 0)
        return fmt - 1;         /* format ended before closing ] */

    /*
     * Now set the entries corresponding to the actual scanset to the
     * opposite of the above.
     *
     * The first character may be ']' (or '-') without being special; the
     * last character may be '-'.
     */

    v = 1 - v;
    for (;;)
    {
        tab[c] = v;             /* take character c */
    doswitch:
        n = *fmt++;             /* and examine the next */
        switch (n)
        {

        case 0:         /* format ended too soon */
            return fmt - 1;

        case '-':
            /*
             * A scanset of the form [01+-] is defined as `the digit 0, the
             * digit 1, the character +, the character -', but the effect
             * of a scanset such as [a-zA-Z0-9] is implementation defined.
             * The V7 Unix scanf treats `a-z' as `the letters a through z',
             * but treats `a-a' as `the letter a, the character -, and the
             * letter a'.
             *
             * For compatibility, the `-' is not considerd to define a
             * range if the character following it is either a close
             * bracket (required by ANSI) or is not numerically greater
             * than the character we just stored in the table (c).
             */
            n = *fmt;
            if (n == ']' || n < c)
            {
                c = '-';
                break;          /* resume the for(;;) */
            }
            fmt++;
            do
            {                   /* fill in the range */
                tab[++c] = v;
            }
            while (c < n);
#if 1                   /* XXX another disgusting compatibility hack */
            /*
             * Alas, the V7 Unix scanf also treats formats such
             * as [a-c-e] as `the letters a through e'. This too
             * is permitted by the standard....
             */
            goto doswitch;
#else
            c = *fmt++;
            if (c == 0)
                return fmt - 1;
            if (c == ']')
                return fmt;
#endif

            break;


        case ']':               /* end of scanset */
            return fmt;

        default:                /* just another character */
            c = n;
            break;
        }
    }
    /* NOTREACHED */
} // __sccl()

#endif // if defined(CYGFUN_LIBC_STDIO_ungetc)

// EOF vfscanf.cxx

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -