c/c++语言开发共享C语言学习趣事_MSCRT_IO_SourceFile

前些时候,贴了一段微软的printf代码,园子里的大侠们说要看看output的代码,这不最近有幸看了微软的 output代码,所以贴上来给园子里大侠看看。  &nbs

前些时候,贴了一段微软的printf代码,园子里的大侠们说要看看output的代码,这不最近有幸看了微软的

output代码,所以贴上来给园子里大侠看看。

    tip:

         源代码版权归微软所有,这里仅贴出来供大家看看。

?/***
*output.c – printf style output to a file
*
*   copyright (c) 1989-1991, microsoft corporation. all rights reserved.
*
*purpose:
*   this file contains the code that does all the work for the
*   printf family of functions.  it should not be called directly, only
*   by the *printf functions.  we don't make any assumtions about the
*   sizes of ints, longs, shorts, or long doubles, but if types do overlap,
*   we also try to be efficient.  we do assume that pointers are the same
*   size as either ints or longs.
*   if cprflag is defined, defines _cprintf instead.
*   **** doesn't currently do mthread locking ****
*
*revision history:
*   06-01-89  phg   module created
*   08-28-89  jcr   added cast to get rid of warning (no object changes)
*   02-15-90  gjf   fixed copyright
*   03-19-90  gjf   made calling type _calltype1 and added #include
*           <cruntime.h>.
*   03-26-90  gjf   changed local macro to incorporate _calltype4. placed
*           prototype for _output() in internal.h and #include-d
*           it.
*   08-01-90  sbm   compiles cleanly with -w3, moved _cfltcvt_tab and
*           typedefs double and longdouble to new header
*           <fltintrn.h>, formerly named <struct.h>
*   09-05-90  sbm   first attempt at adding cprflag and code to generate
*           cprintf.  anything in #ifdef cprflag untested.
*           still needs to have locking added for mthread case.
*   10-03-90  gjf   new-style function declarators.
*   01-02-91  srw   added _win32_ conditional for 'c' and 's' format chars.
*   01-16-91  gjf   ansi naming.
*   01-16-91  srw   added #include of maketabc.out (_win32_)
*   04-09-91  pnt   use the _cruiser_ mapping for _mac_
*   04-16-91  srw   fixed #include of maketabc.out (_win32_)
*   04-25-91  srw   made nullstring static
*   05-20-91  gjf   moved state table for win32 inline (_win32_).
*   09-12-91  jcr   bumped conversion buffer size to be ansi-compliant
*   09-17-91  ihj   add partial unicode (%ws, %wc) support
*   09-28-91  gjf   merged with crt32 and crtdll versions. for now, 9-17-91
*           change is built only for win32, not dosx32 (_win32_).
*   10-22-91  etc   complete wchar_t/mb support under _intl.  for now,
*           9-28-91 change is additionally under !_intl.  bug fix:
*           ints and pointers are longs.
*   11-19-91  etc   added support for _wsprintf, _vwsprintf with wprflag;
*           added %tc %ts (generic string handling).
*   12-05-91  gdp   bug fix: va_arg was used inconsistently for double
*   12-19-91  etc   added some comments on wsprintf optimization, undones;
*           check return on malloc.
*   03-25-92  djm   posix support
*   04-16-92  krs   support new iso {s|f}wprintf with unicode format string.
*   06-08-92  srw   modified to not use free and malloc for mbtowc conversion.
*   06-10-92  krs   fix glitch in previous change.
*   07-14-92  tvb   added alpha support (quad stuff).
*   07-17-92  krs   fix typo which broke wprflag support.
*   04-16-93  sks   fix bug in 's' option logic.
*   07-16-93  srw   alpha merge
*   08-17-93  cfw   avoid mapping tchar macros incorrectly if _mbcs defined.
*
*******************************************************************************/
 
/* temporary hack to minimize changes. this should go into fltintrn.h */
#if defined(_m_mrx000) || defined(_m_alpha) || defined(_m_ppc)
#define double double
#endif
 
 
#include <cruntime.h>
#include <limits.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <stdarg.h>
#include <cvt.h>
#include <conio.h>
#include <internal.h>
#include <fltintrn.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
 
/* inline keyword is non-ansi c7 extension */
/* consider: move to cruntime.h! */
#if !defined(_msc_ver) || defined(__stdc__)
#define __inline static
#else
/* undone: compiler is broken */
#define __inline static
#endif
 
#if defined(wprflag) && !defined(_unicode)
#define _unicode 1
#endif
#ifdef _mbcs    /* always want either unicode or sbcs for tchar.h */
#undef _mbcs
#endif
#include <tchar.h>
 
/* this macro defines a function which is private and as fast as possible: */
/* for example, in c 6.0, it might be static _fastcall <type> near. */
#define local(x) static x _calltype4
 
/* int/long/short/pointer sizes */
 
/* the following should be set depending on the sizes of various types */
#define long_is_int      1       /* 1 means long is same size as int */
#define short_is_int         0       /* 1 means short is same size as int */
#define longdouble_is_double 1       /* 1 means long double is same as double */
#define ptr_is_int       1       /* 1 means ptr is same size as int */
#define ptr_is_long      1       /* 1 means ptr is same size as long */
 
#if long_is_int
    #define get_long_arg(x) (long)get_int_arg(x)
#endif
 
#ifndef wprflag
#if short_is_int
    #define get_short_arg(x) (short)get_int_arg(x)
#endif
#endif
 
#if ptr_is_int
    #define get_ptr_arg(x) (void *)get_int_arg(x)
#elif ptr_is_long
    #define get_ptr_arg(x) (void *)get_long_arg(x)
#else
    #error size of pointer must be same as size of int or long
#endif
 
 
 
/* constants */
 
/* size of conversion buffer (ansi-specified minimum is 509) */
 
#define buffersize    512
 
#if (buffersize < cvtbufsize)
#error conversion buffer too small for max double.
#endif
 
/* flag definitions */
#define fl_sign       0x0001      /* put plus or minus in front */
#define fl_signsp     0x0002      /* put space or minus in front */
#define fl_left       0x0004      /* left justify */
#define fl_leadzero   0x0008      /* pad with leading zeros */
#define fl_long       0x0010      /* long value given */
#define fl_short      0x0020      /* short value given */
#define fl_signed     0x0040      /* signed data given */
#define fl_alternate  0x0080      /* alternate form requested */
#define fl_negative   0x0100      /* value is negative */
#define fl_forceoctal 0x0200      /* force leading '0' for octals */
#define fl_longdouble 0x0400      /* long double value given */
#define fl_widechar   0x0800      /* wide characters */
 
/* state definitions */
enum state {
    st_normal,          /* normal state; outputting literal chars */
    st_percent,         /* just read '%' */
    st_flag,            /* just read flag character */
    st_width,           /* just read width specifier */
    st_dot,         /* just read '.' */
    st_precis,          /* just read precision specifier */
    st_size,            /* just read size specifier */
    st_type         /* just read type specifier */
};
#define numstates (st_type + 1)
 
/* character type values */
enum chartype {
    ch_other,           /* character with no special meaning */
    ch_percent,         /* '%' */
    ch_dot,         /* '.' */
    ch_star,            /* '*' */
    ch_zero,            /* '0' */
    ch_digit,           /* '1'..'9' */
    ch_flag,            /* ' ', '+', '-', '#' */
    ch_size,            /* 'h', 'l', 'l', 'n', 'f', 'w' */
    ch_type         /* type specifying character */
};
 
/* static data (read only, since we are re-entrant) */
#if defined(wprflag) || defined(cprflag)
extern char *__nullstring;  /* string to print on null ptr */
extern wchar_t *__wnullstring;  /* string to print on null ptr */
#else   /* wprflag || cprflag */
char *__nullstring = "(null)";  /* string to print on null ptr */
wchar_t *__wnullstring = l"(null)";/* string to print on null ptr */
#endif  /* wprflag || cprflag */
 
/* the state table.  this table is actually two tables combined into one. */
/* the lower nybble of each byte gives the character class of any     */
/* character; while the uper nybble of the byte gives the next state      */
/* to enter.  see the macros below the table for details.                 */
/*                                                                        */
/* the table is generated by maketabc.c — use this program to make       */
/* changes.                                                               */
 
#if defined(wprflag) || defined(cprflag)
extern const char __lookuptable[];
#else   /* wprflag/cprflag */
#if defined(_cruiser_) || defined(_mac_)
 
/* table generated by maketabc.c built with -d_cruiser_.          */
 
const char __lookuptable[] = {
     0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
     0x10, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x10,
     0x04, 0x45, 0x45, 0x45, 0x05, 0x05, 0x05, 0x05,
     0x05, 0x35, 0x30, 0x00, 0x50, 0x00, 0x00, 0x00,
     0x00, 0x20, 0x20, 0x38, 0x50, 0x58, 0x07, 0x08,
     0x00, 0x30, 0x30, 0x30, 0x57, 0x50, 0x07, 0x00,
     0x00, 0x20, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00,
     0x08, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
     0x00, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, 0x08,
     0x07, 0x08, 0x00, 0x00, 0x07, 0x00, 0x08, 0x08,
     0x08, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07,
     0x08
};
 
#else   /* ndef _cruiser_ || _mac_ */
 
#if defined(_win32_) || defined(_posix_)
 
/* table generated by maketabc.c built with -d_win32_. defines additional */
/* format code %z for counted string.                     */
 
const char __lookuptable[] = {
     0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
     0x10, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x10,
     0x04, 0x45, 0x45, 0x45, 0x05, 0x05, 0x05, 0x05,
     0x05, 0x35, 0x30, 0x00, 0x50, 0x00, 0x00, 0x00,
     0x00, 0x20, 0x20, 0x38, 0x50, 0x58, 0x07, 0x08,
     0x00, 0x30, 0x30, 0x30, 0x57, 0x50, 0x07, 0x00,
     0x00, 0x20, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00,
     0x08, 0x60, 0x68, 0x60, 0x60, 0x60, 0x60, 0x00,
     0x00, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, 0x08,
     0x07, 0x08, 0x00, 0x00, 0x07, 0x00, 0x08, 0x08,
     0x08, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07,
     0x08
};
 
#else   /* ndef _win32_ */
 
#error error – only cruiser, win32, posix, or mac target supported!
 
#endif  /* _win32_ || _posix_ */
 
#endif  /* _cruiser_ || _mac_ */
 
#endif  /* wprflag || cprflag */
 
#define find_char_class(c)     
    ((c) < _t(' ') || (c) > _t('x') ?
        ch_other           
    :              
        __lookuptable[(c)-_t(' ')] & 0xf)
 
#define find_next_state(class, state)  
    (__lookuptable[(class) * numstates + (state)] >> 4)
 
 
/*
 * note: cprflag and wprflag cases are currently mutually exclusive.
 */
 
/* prototypes */
 
#ifdef cprflag
 
#define write_char(ch, pnw)     write_char(ch, pnw)
#define write_multi_char(ch, num, pnw)  write_multi_char(ch, num, pnw)
#define write_string(s, len, pnw)   write_string(s, len, pnw)
#define write_wstring(s, len, pnw)      write_wstring(s, len, pnw)
 
local(void) write_char(int ch, int *pnumwritten);
local(void) write_multi_char(int ch, int num, int *pnumwritten);
local(void) write_string(char *string, int len, int *numwritten);
local(void) write_wstring(wchar_t *string, int len, int *numwritten);
 
#elif wprflag
 
#define write_char(ch, pnw)     write_char(ch, stream, pnw)
#define write_multi_char(ch, num, pnw)  write_multi_char(ch, num, stream, pnw)
#define write_string(s, len, pnw)   write_string(s, len, stream, pnw)
 
local(void) write_char(int ch, file *f, int *pnumwritten);
local(void) write_multi_char(wchar_t ch, int num, file *f, int *pnumwritten);
local(void) write_string(wchar_t *string, int len, file *f, int *numwritten);
 
#else
 
#define write_char(ch, pnw)     write_char(ch, stream, pnw)
#define write_multi_char(ch, num, pnw)  write_multi_char(ch, num, stream, pnw)
#define write_string(s, len, pnw)   write_string(s, len, stream, pnw)
#define write_wstring(s, len, pnw)      write_wstring(s, len, stream, pnw)
 
local(void) write_char(int ch, file *f, int *pnumwritten);
local(void) write_multi_char(int ch, int num, file *f, int *pnumwritten);
local(void) write_string(char *string, int len, file *f, int *numwritten);
local(void) write_wstring(wchar_t *string, int len, file *f, int *numwritten);
 
#endif
 
__inline int _calltype4 get_int_arg(va_list *pargptr);
 
#ifndef wprflag
#if !short_is_int
__inline short _calltype4 get_short_arg(va_list *pargptr);
#endif
#endif
 
#if !long_is_int
__inline long _calltype4 get_long_arg(va_list *pargptr);
#endif
 
#ifdef _alpha_
__inline __int64 _calltype4 get_quad_arg(va_list *pargptr);
#endif
 
#ifdef cprflag
local(int) output(const char *, va_list);
 
/***
*int _cprintf(format, arglist) – write formatted output directly to console
*
*purpose:
*   writes formatted data like printf, but uses console i/o functions.
*
*entry:
*   char *format – format string to determine data formats
*   arglist – list of pointers to where to put data
*
*exit:
*   returns number of characters written
*
*exceptions:
*
*******************************************************************************/
 
int _calltype2 _cprintf (
    const char * format,
    …
    )
{
    va_list arglist;
 
    va_start(arglist, format);
 
    return output(format, arglist);
}
 
#endif  /* cprflag */
 
 
/***
*int _output(stream, format, argptr), static int output(format, argptr)
*
*purpose:
*   output performs printf style output onto a stream.  it is called by
*   printf/fprintf/sprintf/vprintf/vfprintf/vsprintf to so the dirty
*   work.  in multi-thread situations, _output assumes that the given
*   stream is already locked.
*
*   algorithm:
*   the format string is parsed by using a finite state automaton
*   based on the current state and the current character read from
*   the format string.  thus, looping is on a per-character basis,
*   not a per conversion specifier basis.  once the format specififying
*   character is read, output is performed.
*
*entry:
*   file *stream   – stream for output
*   char *format   – printf style format string
*   va_list argptr – pointer to list of subsidiary arguments
*
*exit:
*   returns the number of characters written, or -1 if an output error
*   occurs.
#ifdef wprflag
*   the wide-character flavour returns the number of wide-characters written.
#endif
*
*exceptions:
*
*******************************************************************************/
 
#ifdef cprflag
local(int) output (
#elif wprflag
int _calltype1 _woutput (
    file *stream,
#else
int _calltype1 _output (
    file *stream,
#endif
    const tchar *format,
    va_list argptr
    )
{
    int hexadd;     /* offset to add to number to get 'a'..'f' */
    tchar ch;       /* character just read */
    int flags;      /* flag word — see #defines above for flag values */
    enum state state;   /* current state */
    enum chartype chclass; /* class of current character */
    int radix;      /* current conversion radix */
    int charsout;   /* characters currently written so far, -1 = io error */
    int fldwidth;   /* selected field width — 0 means default */
    int precision;  /* selected precision  — -1 means default */
    tchar prefix[2];    /* numeric prefix — up to two characters */
    int prefixlen;  /* length of prefix — 0 means no prefix */
    int capexp;     /* non-zero = 'e' exponent signifient, zero = 'e' */
    int no_output;  /* non-zero = prodcue no output for this specifier */
    union {
    char *sz;   /* pointer text to be printed, not zero terminated */
    wchar_t *wz;
    } text; 
 
    int textlen;    /* length of the text in bytes/wchars to be printed.
               textlen is in multibyte or wide chars if wprflag */
    union {
    char sz[buffersize];
#ifdef wprflag
    wchar_t wz[buffersize];
#endif
    } buffer;
    wchar_t wchar;  /* temp wchar_t */
    int bufferiswide;   /* non-zero = buffer contains wide chars already */
 
    charsout = 0;       /* no characters written yet */
    state = st_normal;      /* starting state */
 
    /* main loop — loop while format character exist and no i/o errors */
    while ((ch = *format++) != _t('') && charsout >= 0) {
    chclass = find_char_class(ch);  /* find character class */
    state = find_next_state(chclass, state); /* find next state */
 
    /* execute code for each state */
    switch (state) {
 
    case st_normal:
        /* normal state — just write character */
#ifdef wprflag
        bufferiswide = 1;
#else
        bufferiswide = 0;
        if (isleadbyte((int)(unsigned char)ch)) {
        write_char(ch, &charsout);
        ch = *format++;
        assert (ch != _t('')); /* undone: don't fall off format string */
        }
#endif /* !wprflag */
        write_char(ch, &charsout);
        break;
 
    case st_percent:
        /* set default value of conversion parameters */
        prefixlen = fldwidth = no_output = capexp = 0;
        flags = 0;
        precision = -1;
        bufferiswide = 0;   /* default */
        break;
 
    case st_flag:
        /* set flag based on which flag character */
        switch (ch) {
        case _t('-'):
        flags |= fl_left;   /* '-' => left justify */
        break;
        case _t('+'):
        flags |= fl_sign;   /* '+' => force sign indicator */
        break;
        case _t(' '):
        flags |= fl_signsp; /* ' ' => force sign or space */
        break;
        case _t('#'):
        flags |= fl_alternate;  /* '#' => alternate form */
        break;
        case _t('0'):
        flags |= fl_leadzero;   /* '0' => pad with leading zeros */
        break;
        }
        break;
 
    case st_width:
        /* update width value */
        if (ch == _t('*')) {
        /* get width from arg list */
        fldwidth = get_int_arg(&argptr);
        if (fldwidth < 0) {
            /* ansi says neg fld width means '-' flag and pos width */
            flags |= fl_left;
            fldwidth = -fldwidth;
        }
        }
        else {
        /* add digit to current field width */
        fldwidth = fldwidth * 10 + (ch – _t('0'));
        }
        break;
 
    case st_dot:
        /* zero the precision, since dot with no number means 0
           not default, according to ansi */
        precision = 0;
        break;
 
    case st_precis:
        /* update precison value */
        if (ch == _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 – _t('0'));
        }
        break;
 
    case st_size:
        /* just read a size specifier, set the flags based on it */
        switch (ch) {
#if !long_is_int || !defined(_unicode)
        case _t('l'):
        flags |= fl_long;   /* 'l' => long int or wchar_t */
        break;
#endif
 
#if !longdouble_is_double || defined(_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 _t('l'):
        flags |= fl_longdouble; /* 'l' => long double */
        break;
#endif
 
#if !short_is_int || defined(_unicode)
        case _t('h'):
        flags |= fl_short;  /* 'h' => short int or char */
        break;
#endif
 
/* undone: support %wc and %ws for now only for compatibility */
        case _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 _t('c'):   /* iso wide character */
        if (!(flags & (fl_short|fl_long|fl_widechar)))
#ifdef wprflag
            /* consider: non-standard */
            flags |= fl_short;
#else
            flags |= fl_widechar;   /* iso std. */
#endif
        /* fall into 'c' case */
 
        case _t('c'): {
        /* print a single character specified by int argument */
#ifdef wprflag
        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] = '';
                }
            if (mbtowc(buffer.wz,tempchar,mb_cur_max) < 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   /* wprflag */
        if (flags & (fl_long|fl_widechar))
            {
            wchar = (wchar_t) get_short_arg(&argptr);
            /* convert to multibyte character */
            textlen = wctomb(buffer.sz, 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  /* wprflag */
        }
        break;
 
#if defined(_win32_) && !defined(_dosx32_)  /* undone: nt hack */
        case _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 = __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;
#endif
 
        case _t('s'):   /* iso wide character string */
#ifndef wprflag
        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 _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 wprflag
        if (flags & fl_short)
            {
            if (text.sz == null) /* null passed, use special string */
            text.sz = __nullstring;
            p = text.sz;
            for (textlen=0; textlen<i && *p; textlen++)
            {
            if (isleadbyte((int)*p))
                ++p;
            ++p;
            }
            /* textlen now contains length in multibyte chars */
            }
        else
            {
            if (text.wz == null) /* null passed, use special string */
            text.wz = __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   /* wprflag */
        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 = __wnullstring;
            bufferiswide = 1;
            pwch = text.wz;
            for (textlen=0; textlen<i && *pwch; pwch++)
            {
            if ((temp = wctomb(tchr, *pwch))<=0) break;
            textlen += temp;
            }
            /* textlen now contains length in bytes */
            }
        else
            {
            if (text.sz == null) /* null passed, use special string */
            text.sz = __nullstring;
            p = text.sz;
            while (i– && *p)
            ++p;
            textlen = p – text.sz;    /* length of the string */
            }
 
#endif  /* wprflag */
        }
        break;
 
 
        case _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 _t('e'):
        case _t('g'):
        capexp = 1;         /* capitalize exponent */
        ch += _t('a') – _t('a');    /* convert format char to lower */
        /* drop through */
        case _t('e'):
        case _t('f'):
        case _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 == _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 == _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 _t('d'):
        case _t('i'):
        /* signed decimal output */
        flags |= fl_signed;
        radix = 10;
        goto common_int;
 
        case _t('u'):
        radix = 10;
        goto common_int;
 
        case _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 _t('x'):
        /* unsigned upper hex output */
        hexadd = _t('a') – _t('9') – 1;     /* set hexadd for uppercase hex */
        goto common_hex;
 
        case _t('x'):
        /* unsigned lower hex output */
        hexadd = _t('a') – _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] = _t('0');
            prefix[1] = (tchar)(_t('x') – _t('a') + _t('9') + 1 + hexadd);  /* 'x' or 'x' */
            prefixlen = 2;
        }
        goto common_int;
 
        case _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. */
 
#ifdef _alpha_
        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 */
#ifdef _alpha_
        if (flags & fl_longdouble)
            l = get_quad_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;
        }
#ifdef _alpha_
        if ((flags & fl_longdouble) == 0) {
            /*
             * unless printing a full 64-bit value, insure values
             * here are not in cananical longword format to prevent
             * the sign extended upper 32-bits from being printed.
             */
            number &= 0xffffffff;
   &n

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/603933.html

(0)
上一篇 2021年5月12日
下一篇 2021年5月12日

精彩推荐