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 + -
显示快捷键?