output.c

来自「不错的东西 请查看 WINCE OS」· C语言 代码 · 共 1,334 行 · 第 1/3 页

C
1,334
字号
            if (ch == CRT_T('*')) {
                /* get precision from arg list */
                precision = get_int_arg(&argptr);
                if (precision < 0)
                    precision = -1; /* neg precision means default */
            }
            else {
                /* add digit to current precision */
                precision = precision * 10 + (ch - CRT_T('0'));
            }
            break;

        case ST_SIZE:
            /* just read a size specifier, set the flags based on it */
            switch (ch) {
#if !LONG_IS_INT || !defined(CRT_UNICODE)
            case CRT_T('l'):
                flags |= FL_LONG;   /* 'l' => long int or wchar_t */
                break;
#endif

#if !LONGDOUBLE_IS_DOUBLE || defined(_M_ALPHA)
            /*
             * Alpha has native 64-bit integer registers and operations.
             * The int and long types are 32 bits and an Alpha specific
             * __int64 type is 64 bits.  We also use the 'L' flag for
             * integer arguments to indicate 64-bit conversions (%Lx).
             */

            case CRT_T('L'):
                flags |= FL_I64;    /* 'L' => __int64 */
                break;
#endif

            case CRT_T('I'):
                /*
                 * In order to handle the I64 size modifier, we depart from
                 * the simple deterministic state machine. The code below
                 * scans
                 */
                if ( (*format == CRT_T('6')) && (*(format + 1) == CRT_T('4')) ) {
                    format += 2;
                    flags |= FL_I64;    /* I64 => __int64 */
                }
                else {
                    state = ST_NORMAL;
                    goto NORMAL_STATE;
                }
                break;

#if !SHORT_IS_INT || defined(CRT_UNICODE)
            case CRT_T('h'):
                flags |= FL_SHORT;  /* 'h' => short int or char */
                break;
#endif

/* UNDONE: support %wc and %ws for now only for compatibility */
            case CRT_T('w'):
                flags |= FL_WIDECHAR;  /* 'w' => wide character */
                break;

            }
            break;

        case ST_TYPE:
            /* we have finally read the actual type character, so we       */
            /* now format and "print" the output.  We use a big switch     */
            /* statement that sets 'text' to point to the text that should */
            /* be printed, and 'textlen' to the length of this text.       */
            /* Common code later on takes care of justifying it and        */
            /* other miscellaneous chores.  Note that cases share code,    */
            /* in particular, all integer formatting is done in one place. */
            /* Look at those funky goto statements!                        */

            switch (ch) {

            case CRT_T('C'):   /* ISO wide character */
                if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
#ifdef CRT_UNICODE
                    flags |= FL_SHORT;
#else
                    flags |= FL_WIDECHAR;   /* ISO std. */
#endif
                /* fall into 'c' case */

            case CRT_T('c'): {
                /* print a single character specified by int argument */
#ifdef CRT_UNICODE
                bufferiswide = 1;
                wchar = (wchar_t) get_int_arg(&argptr);
                if (flags & FL_SHORT) {
                    /* format multibyte character */
                    /* this is an extension of ANSI */
                    char tempchar[2];
#ifdef _OUT
                    if (isleadbyte(wchar >> 8)) {
                        tempchar[0] = (wchar >> 8);
                        tempchar[1] = (wchar & 0x00ff);
                    }
                    else
#endif /* _OUT */
                    {
                        tempchar[0] = (char)(wchar & 0x00ff);
                        tempchar[1] = '\0';
                    }

                                        if (change_to_widechar(buffer.wz,tempchar,1) <= 0) {
                        /* ignore if conversion was unsuccessful */
                        no_output = 1;
                    }
                } else {
                    buffer.wz[0] = wchar;
                }
                text.wz = buffer.wz;
                textlen = 1;    /* print just a single character */
#else   /* CRT_UNICODE */
            if (flags & (FL_LONG|FL_WIDECHAR)) {
                wchar = (wchar_t) get_short_arg(&argptr);
                /* convert to multibyte character */
                // textlen = wctomb(buffer.sz, wchar); ...ARULM
                textlen = change_to_multibyte(buffer.sz, MB_LEN_MAX, wchar);

                /* check that conversion was successful */
                if (textlen <= 0)
                    no_output = 1;
                } else {
                    /* format multibyte character */
                    /* this is an extension of ANSI */
                    unsigned short temp;
                    temp = (unsigned short) get_int_arg(&argptr);
#ifdef _OUT
                    if (isleadbyte(temp >> 8)) {
                        buffer.sz[0] = temp >> 8;
                        buffer.sz[1] = temp & 0x00ff;
                        textlen = 2;
                    } else
#endif /* _OUT */
                    {
                        buffer.sz[0] = (char) temp;
                        textlen = 1;
                    }
                }
                text.sz = buffer.sz;
#endif  /* CRT_UNICODE */
            }
            break;

            case CRT_T('Z'): {
                /* print a Counted String

                int i;
                char *p;       /* temps */
                struct string {
                    short Length;
                    short MaximumLength;
                    char *Buffer;
                } *pstr;

                pstr = get_ptr_arg(&argptr);
                if (pstr == NULL || pstr->Buffer == NULL) {
                    /* null ptr passed, use special string */
                    text.sz = (char*)__nullstring;
                    textlen = strlen(text.sz);
                } else {
                    if (flags & FL_WIDECHAR) {
                        text.wz = (wchar_t *)pstr->Buffer;
                        textlen = pstr->Length / sizeof(wchar_t);
                        bufferiswide = 1;
                    } else {
                        bufferiswide = 0;
                        text.sz = pstr->Buffer;
                        textlen = pstr->Length;
                    }
                }
            }
            break;

            case CRT_T('S'):   /* ISO wide character string */
#ifndef CRT_UNICODE
                if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
                    flags |= FL_WIDECHAR;
#else
                if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
                    flags |= FL_SHORT;
#endif

            case CRT_T('s'): {
                /* print a string --                            */
                /* ANSI rules on how much of string to print:   */
                /*   all if precision is default,               */
                /*   min(precision, length) if precision given. */
                /* prints '(null)' if a null string is passed   */

                int i;
                char *p;       /* temps */
                wchar_t *pwch;

                /* At this point it is tempting to use strlen(), but */
                /* if a precision is specified, we're not allowed to */
                /* scan past there, because there might be no null   */
                /* at all.  Thus, we must do our own scan.           */

                i = (precision == -1) ? INT_MAX : precision;
                text.sz = get_ptr_arg(&argptr);

/* UNDONE: handle '#' case properly */
                /* scan for null upto i characters */
#ifdef CRT_UNICODE
                if (flags & FL_SHORT) {
                    if (text.sz == NULL) /* NULL passed, use special string */
                        text.sz = (char*)__nullstring;
                    p = text.sz;
                    for (textlen=0; textlen<i && *p; textlen++) {
                        if (isleadbyte(*p))
                            ++p;
                        ++p;
                    }
                    /* textlen now contains length in multibyte chars */
                } else {
                    if (text.wz == NULL) /* NULL passed, use special string */
                        text.wz = (wchar_t*)__wnullstring;
                    bufferiswide = 1;
                    pwch = text.wz;
                    while (i-- && *pwch)
                        ++pwch;
                    textlen = pwch - text.wz;       /* in wchar_ts */
                    /* textlen now contains length in wide chars */
                }
#else   /* CRT_UNICODE */
                if (flags & (FL_LONG|FL_WIDECHAR)) {
                    size_t temp;
                    char tchr[MB_LEN_MAX];
                    if (text.wz == NULL) /* NULL passed, use special string */
                        text.wz = (wchar_t*)__wnullstring;
                    bufferiswide = 1;
                    pwch = text.wz;
                    for (textlen=0; textlen<i && *pwch; pwch++) {
                        // if ((temp = wctomb(tchr, *pwch))<=0) ...ARULM
                        if ((temp = change_to_multibyte(tchr, MB_LEN_MAX, *pwch)) <= 0)
                            break;
                        textlen += temp;
                    }
                    /* textlen now contains length in bytes */
                } else {
                    if (text.sz == NULL) /* NULL passed, use special string */
                        text.sz = (char*)__nullstring;
                    p = text.sz;
                    while (i-- && *p)
                        ++p;
                    textlen = p - text.sz;    /* length of the string */
                }

#endif  /* CRT_UNICODE */
            }
            break;


            case CRT_T('n'): {
                /* write count of characters seen so far into */
                /* short/int/long thru ptr read from args */

                void *p;        /* temp */

                p = get_ptr_arg(&argptr);

                /* store chars out into short/long/int depending on flags */
#if !LONG_IS_INT
                if (flags & FL_LONG)
                    *(long *)p = charsout;
                else
#endif

#if !SHORT_IS_INT
                if (flags & FL_SHORT)
                    *(short *)p = (short) charsout;
                else
#endif
                    *(int *)p = charsout;

                no_output = 1;              /* force no output */
            }
            break;


            case CRT_T('E'):
            case CRT_T('G'):
                capexp = 1;                 /* capitalize exponent */
                ch += CRT_T('a') - CRT_T('A');    /* convert format char to lower */
                /* DROP THROUGH */
            case CRT_T('e'):
            case CRT_T('f'):
            case CRT_T('g'): {
                /* floating point conversion -- we call cfltcvt routines */
                /* to do the work for us.                                */
                flags |= FL_SIGNED;         /* floating point is signed conversion */
                text.sz = buffer.sz;        /* put result in buffer */

                /* compute the precision value */
                if (precision < 0)
                    precision = 6;          /* default precision: 6 */
                else if (precision == 0 && ch == CRT_T('g'))
                    precision = 1;          /* ANSI specified */

#if !LONGDOUBLE_IS_DOUBLE
                /* do the conversion */
                if (flags & FL_LONGDOUBLE) {
                    LONGDOUBLE tmp;
                    tmp=va_arg(argptr, LONGDOUBLE);
                    /* Note: assumes ch is in ASCII range */
                    _cldcvt(&tmp, text.sz, (char)ch, precision, capexp);
                } else
#endif
                {
                    DOUBLE tmp;
                    tmp=va_arg(argptr, DOUBLE);
                    /* Note: assumes ch is in ASCII range */
                    _cfltcvt(&tmp,text.sz, (char)ch, precision, capexp);
                }

                /* '#' and precision == 0 means force a decimal point */
                if ((flags & FL_ALTERNATE) && precision == 0)
                    _forcdecpt(text.sz);

                /* 'g' format means crop zero unless '#' given */
                if (ch == CRT_T('g') && !(flags & FL_ALTERNATE))
                    _cropzeros(text.sz);

                /* check if result was negative, save '-' for later */
                /* and point to positive part (this is for '0' padding) */
                if (*text.sz == '-') {
                    flags |= FL_NEGATIVE;
                    ++text.sz;
                }

                textlen = strlen(text.sz);     /* compute length of text */
            }
            break;

            case CRT_T('d'):
            case CRT_T('i'):
                /* signed decimal output */
                flags |= FL_SIGNED;
                radix = 10;
                goto COMMON_INT;

            case CRT_T('u'):
                radix = 10;
                goto COMMON_INT;

            case CRT_T('p'):
                /* write a pointer -- this is like an integer or long */
                /* except we force precision to pad with zeros and */
                /* output in big hex. */

                precision = 2 * sizeof(void *);     /* number of hex digits needed */
#if !PTR_IS_INT
                flags |= FL_LONG;                   /* assume we're converting a long */
#endif
                /* DROP THROUGH to hex formatting */

            case CRT_T('X'):
                /* unsigned upper hex output */
                hexadd = CRT_T('A') - CRT_T('9') - 1;     /* set hexadd for uppercase hex */
                goto COMMON_HEX;

            case CRT_T('x'):
                /* unsigned lower hex output */
                hexadd = CRT_T('a') - CRT_T('9') - 1;     /* set hexadd for lowercase hex */
                /* DROP THROUGH TO COMMON_HEX */

            COMMON_HEX:
                radix = 16;
                if (flags & FL_ALTERNATE) {
                    /* alternate form means '0x' prefix */
                    prefix[0] = CRT_T('0');
                    prefix[1] = (CRT_TCHAR)(CRT_T('x') - CRT_T('a') + CRT_T('9') + 1 + hexadd);  /* 'x' or 'X' */
                    prefixlen = 2;
                }
                goto COMMON_INT;

            case CRT_T('o'):
                /* unsigned octal output */
                radix = 8;
                if (flags & FL_ALTERNATE) {
                    /* alternate form means force a leading 0 */
                    flags |= FL_FORCEOCTAL;
                }
                /* DROP THROUGH to COMMON_INT */

            COMMON_INT: {
                /* This is the general integer formatting routine. */
                /* Basically, we get an argument, make it positive */
                /* if necessary, and convert it according to the */
                /* correct radix, setting text and textlen */
                /* appropriately. */

#if _INTEGRAL_MAX_BITS >= 64
                unsigned __int64 number;    /* number to convert */
                int digit;              /* ascii value of digit */
                __int64 l;              /* temp long value */
#else
                unsigned long number;   /* number to convert */
                int digit;              /* ascii value of digit */
                long l;                 /* temp long value */
#endif

                /* 1. read argument into l, sign extend as needed */
#if _INTEGRAL_MAX_BITS >= 64
                if (flags & FL_I64)
                    l = get_int64_arg(&argptr);
                else
#endif

#if !LONG_IS_INT
                if (flags & FL_LONG)
                    l = get_long_arg(&argptr);
                else
#endif

#if !SHORT_IS_INT
                if (flags & FL_SHORT) {
                    if (flags & FL_SIGNED)
                        l = (short) get_int_arg(&argptr); /* sign extend */
                    else
                        l = (unsigned short) get_int_arg(&argptr);    /* zero-extend*/
                } else
#endif
                {
                    if (flags & FL_SIGNED)
                        l = get_int_arg(&argptr); /* sign extend */
                    else
                        l = (unsigned int) get_int_arg(&argptr);    /* zero-extend*/
                }

                /* 2. check for negative; copy into number */
                if ( (flags & FL_SIGNED) && l < 0) {
                    number = -l;
                    flags |= FL_NEGATIVE;   /* remember negative sign */
                } else {
                    number = l;
                }

#if _INTEGRAL_MAX_BITS >= 64
                if ( (flags & FL_I64) == 0 ) {

⌨️ 快捷键说明

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