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

📄 output.c

📁 c语言编程软件vc6.0中文绿色版_vc6.0官方下载
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * Note: CPRFLAG and _UNICODE 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 defined (_UNICODE)

#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(wchar_t 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  /* defined (_UNICODE) */

#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  /* defined (_UNICODE) */

LOCAL(int) get_int_arg(va_list *pargptr);

LOCAL(short) get_short_arg(va_list *pargptr);

#if !LONG_IS_INT
LOCAL(long) get_long_arg(va_list *pargptr);
#endif  /* !LONG_IS_INT */

LOCAL(__int64) get_int64_arg(va_list *pargptr);

#ifdef _UNICODE
LOCAL(int) __cdecl _woutput(FILE *, const char *, va_list);
#endif  /* _UNICODE */

#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 __cdecl _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.
*
*Exceptions:
*
*******************************************************************************/

#ifdef CPRFLAG
LOCAL(int) output (
#elif defined (_UNICODE)
LOCAL(int) _woutput (
    FILE *stream,
#else  /* defined (_UNICODE) */
int __cdecl _output (
    FILE *stream,
#endif  /* defined (_UNICODE) */
    const char *format,
    va_list argptr
    )
{
    int hexadd;         /* offset to add to number to get 'a'..'f' */
    char 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 with -- 0 means default */
    int precision;      /* selected precision -- -1 means default */
    char prefix[2];     /* numeric prefix -- up to two characters */
    int prefixlen;      /* length of prefix -- 0 means no prefix */
    int capexp;         /* non-zero = 'E' exponent signifiet, zero = 'e' */
    int no_output;      /* non-zero = prodcue no output for this specifier */
    char *text;         /* pointer text to be printed, not zero terminated */
    int textlen;        /* length of the text in bytes to be printed */
    char buffer[BUFFERSIZE];    /* buffer for conversions */
#ifdef _UNICODE
    /* textlen is in multibyte or wide characters for _UNICODE versions */
    wchar_t wchar;      /* temp wchar_t */
    wchar_t *wchar_p;   /* temp wchar_t pointer */
    int bufferiswide;   /* non-zero = buffer contains wide chars already */
#endif  /* _UNICODE */
    int _tflag=0;

    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++) != '\0' && 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) {

        NORMAL_STATE:

        case ST_NORMAL:
            /* normal state -- just write character */
#ifndef _UNICODE
            if (isleadbyte((int)ch)) {
                WRITE_CHAR(ch, &charsout);
                ch = *format++;
                _ASSERTE (ch != '0'); /* UNDONE: don't fall off format string */
            }
            WRITE_CHAR(ch, &charsout);
#else  /* _UNICODE */
            format += (mbtowc (&wchar, format-1, MB_CUR_MAX) - 1);
            /* UNDONE: check for mbtowc failure */
            WRITE_CHAR(wchar, &charsout);
#endif  /* _UNICODE */
            break;

        case ST_PERCENT:
            /* set default value of conversion parameters */
            prefixlen = fldwidth = no_output = capexp = 0;
            flags = 0;
            precision = -1;
#ifdef _UNICODE
            bufferiswide = 0;
#endif  /* _UNICODE */
            break;

        case ST_FLAG:
            /* set flag based on which flag character */
            switch (ch) {
            case '-':
                flags |= FL_LEFT;       /* '-' => left justify */
                break;
            case '+':
                flags |= FL_SIGN;       /* '+' => force sign indicator */
                break;
            case ' ':
                flags |= FL_SIGNSP;     /* ' ' => force sign or space */
                break;
            case '#':
                flags |= FL_ALTERNATE;  /* '#' => alternate form */
                break;
            case '0':
                flags |= FL_LEADZERO;   /* '0' => pad with leading zeros */
                break;
            }
            break;

        case ST_WIDTH:
            /* update width value */
            if (ch == '*') {
                /* 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 - '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 == '*') {
                /* 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 - '0');
            }
            break;

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

#if !LONGDOUBLE_IS_DOUBLE
            case 'L':
                flags |= FL_LONGDOUBLE; /* 'L' => long double */
                break;
#endif  /* !LONGDOUBLE_IS_DOUBLE */

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

#if !SHORT_IS_INT
            case 'h':
                flags |= FL_SHORT;  /* 'h' => short int */
                break;
#endif  /* !SHORT_IS_INT */

            }
            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 doen in one place. */
            /* Look at those funky goto statements!                        */

            /*
             *  Generic string handling support:  %tc, %ts accept
             *  either chars or wide-chars depending on _tflag.
             *  _tflag == 1 means wide-chars.
             */
            if (ch == 't') {
                if (_tflag == 1)
                    ch = 'w';
                else {
                    ch = *format++;
                    _ASSERTE (ch!='0'); /* UNDONE: don't fall off format string */
                }
            }

            switch (ch) {

            case 'c': {
                /* print a single character specified by int argument */
                buffer[0] = (char) get_int_arg(&argptr); /* get char to print */
                text = buffer;
                textlen = 1;        /* print just a single character */
            }
            break;

            case '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 */

                text = get_ptr_arg(&argptr);
                if (text == NULL) {
                    /* null ptr passed, use special string */
                    text = nullstring;
                }

                /* 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;

                p = text;

                /* scan for null upto i characters */
#ifndef _UNICODE
                while (i-- && *p)
                    ++p;

                textlen = p - text;    /* length of the string */
#else  /* _UNICODE */
                for (textlen=0; textlen<i && *p; textlen++) {
                    if (isleadbyte((int)*p))
                        ++p;
                    ++p;
                }
                /* textlen now contains length in multibyte chars */
#endif  /* _UNICODE */
            }
            break;

            case 'w': {
                /* 'wc' print a wide character

⌨️ 快捷键说明

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