📄 xprintf.c
字号:
char c; /* format char */
char buf[NDIG+5]; /* temp buffer for output */
/* used to be coded as "BUFSIZ" */
int pad_field; /* count used to shift "prec" inside "field" */
int prefix_cnt; /* used to indicate -, +, ' ', or '0x' prefix */
int prec_flag; /* used to indicated that precision was specified */
int char_flag; /* use to indicate %s or %c conversion */
SHORTARG_DCL /* true if arg is short ('h') */
LONGARG_DCL /* true if arg is long ('l') */
LONGDBL_DCL /* true if 'L' flag */
LEFTJ_DCL /* true if left-justified */
PLUS_DCL /* true if to print +/- for signed value */
SPACE_DCL /* prepend ' ' if needed for signed value */
ALT_DCL /* true if to use alternate form ('#') */
PADCHAR_DCL /* for padding */
nc = 0;
while ((c = *fmt) != 0) {
fmt++;
if (c != '%') {
(*trans)(c,fp);
nc++;
}
else {
prefix_cnt = 0; /* reset */
char_flag = 0; /* reset */
LEFTJ_EXP (leftj = 0); /* default is right-justified */
PLUS_EXP (plus = 0);
SPACE_EXP (space = 0);
ALT_EXP (alt = 0);
PADCHAR_EXP (padchar = ' '); /* default is blank padding */
for (;;) { /* ANSI says flags in any order */
switch (*fmt) {
#ifndef EXCLUDE_FORMAT_IO_MINUS_FLAG
case '-' :
leftj++; /* to be left-justified */
PADCHAR_EXP(padchar = ' '); /* suppress 0 pad */
fmt++;
continue;
#endif /* EXCLUDE_FORMAT_IO_MINUS_FLAG */
#ifndef EXCLUDE_FORMAT_IO_ZERO_FLAG
case '0' : /* cannot be both - and 0 */
if (LEFTJ_EXP (leftj) == 0)
PADCHAR_EXP(padchar = '0');/*to be zero filled*/
fmt++;
continue;
#endif /* EXCLUDE_FORMAT_IO_ZERO_FLAG */
#ifndef EXCLUDE_FORMAT_IO_PLUS_FLAG
case '+' : /* print +/- for signed value */
plus++;
SPACE_EXP (space = 0); /* suppress space */
fmt++;
continue;
#endif /* EXCLUDE_FORMAT_IO_PLUS_FLAG */
#ifndef EXCLUDE_FORMAT_IO_SPACE_FLAG
case ' ' : /* cannot be both + and ' ' */
if (PLUS_EXP (plus) == 0)
space++;
fmt++;
continue;
#endif /* EXCLUDE_FORMAT_IO_SPACE_FLAG */
#ifndef EXCLUDE_FORMAT_IO_SHARP_FLAG
case '#' :
alt++; /* use alternate form */
fmt++;
continue;
#endif /* EXCLUDE_FORMAT_IO_SHARP_FLAG */
}
break; /* break loop if no flag */
} /* for (;;) */
#ifndef EXCLUDE_FORMAT_IO_STAR_OPT
if (*fmt == '*') {
width = va_arg (arg, int); /* get width from arg */
if (width < 0) {
width = -width; /* -ve width means left-j */
LEFTJ_EXP (leftj++);
}
fmt++;
}
else
#endif /* EXCLUDE_FORMAT_IO_STAR_OPT */
{
width = 0;
while (*fmt >= '0' && *fmt <= '9') {
width = width * 10 + (*fmt - '0');
fmt++;
}
}
prec = -1; /* no precision yet */
prec_flag = 0; /* reset */
if (*fmt == '.') {
prec_flag = 1; /* indicate a precision was specified */
fmt++;
#ifndef EXCLUDE_FORMAT_IO_STAR_OPT
if (*fmt == '*') {
prec = va_arg (arg, int); /* get prec from arg */
fmt++;
}
else
#endif /* EXCLUDE_FORMAT_IO_STAR_OPT */
{
prec = 0;
while (*fmt >= '0' && *fmt <= '9') {
prec = prec * 10 + (*fmt - '0');
fmt++;
}
}
}
SHORTARG_EXP (shortarg = 0); /* set defaults */
LONGARG_EXP (longarg = 0);
LONGDBL_EXP (longdbl = 0);
#ifndef EXCLUDE_FORMAT_IO_l_OPT /* set option flags */
if (*fmt == 'l') {
longarg++;
fmt++;
goto opt_fin;
}
#endif /* EXCLUDE_FORMAT_IO_l_OPT */
#ifndef EXCLUDE_FORMAT_IO_h_OPT
if (*fmt == 'h') {
shortarg++;
fmt++;
goto opt_fin;
}
#endif /* EXCLUDE_FORMAT_IO_h_OPT */
#ifndef EXCLUDE_FORMAT_IO_L_OPT
if (*fmt == 'L') {
longdbl++;
fmt++;
goto opt_fin;
}
#endif /* EXCLUDE_FORMAT_IO_L_OPT */
opt_fin:
str = buf;
switch (c = *fmt++) {
#ifndef EXCLUDE_FORMAT_IO_STR_FMT
case 's': /* string */
char_flag = 1; /* character-type conversion */
str = va_arg (arg, char *);
if (str == 0)
str = "(null)";
for (len = 0; str[len] != 0; len++) ;
if (prec < len && prec >= 0) /* limit string */
len = prec;
break;
#endif /* EXCLUDE_FORMAT_IO_STR_FMT */
#ifndef EXCLUDE_FORMAT_IO_CHAR_FMT
case 'c': /* character */
char_flag = 1; /* character-type conversion */
buf[0] = va_arg (arg, int); /* char is passed as int */
buf[1] = '\0';
len = 1;
break;
#endif /* EXCLUDE_FORMAT_IO_CHAR_FMT */
#if (!defined(EXCLUDE_FORMAT_IO_INT_FMT)) || \
(!defined(EXCLUDE_FORMAT_IO_DEC_FMT))
case 'd': /* signed int */
case 'i':
if (prec_flag) /* no pad char if prec speced*/
PADCHAR_EXP (padchar = ' ');
len = _ltoa(LONGARG_EXP (longarg) ?
va_arg (arg, long) : /* long */
(SHORTARG_EXP (shortarg) ? /* short */
((long) (short) va_arg (arg, int)) :
((long) va_arg (arg, int)) /* int */
), ++str);
if (*str != '-' && (PLUS_EXP(plus)||SPACE_EXP(space))) {
*--str = PLUS_EXP (plus) ? '+' : ' ';
len++;
}
#endif /* (! EXCLUDE_FORMAT_IO_INT_FMT) || (! EXCLUDE_FORMAT_IO_DEC_FMT) */
#if (!defined(EXCLUDE_FORMAT_IO_INT_FMT)) || \
(!defined(EXCLUDE_FORMAT_IO_DEC_FMT)) || \
(!defined(EXCLUDE_FORMAT_IO_OCT_FMT)) || \
(!defined(EXCLUDE_FORMAT_IO_UNS_FMT)) || \
(!defined(EXCLUDE_FORMAT_IO_HEX_FMT)) || \
(!defined(EXCLUDE_FORMAT_IO_PNT_FMT))
yy:
if ((*str=='-') || (*str=='+') || (*str==' ')) {
prefix_cnt = 1;
}
if (prec >= 0) {
if (prec < (len - prefix_cnt))
prec = len - prefix_cnt;
if (width < (prec + prefix_cnt))
width = prec + prefix_cnt;
}
break;
#endif /* (! EXCLUDE_FORMAT_IO_INT_FMT) || .... */
#ifndef EXCLUDE_FORMAT_IO_UNS_FMT
case 'u': /* unsigned int */
n = 10;
goto xx;
#endif /* EXCLUDE_FORMAT_IO_UNS_FMT */
#ifndef EXCLUDE_FORMAT_IO_OCT_FMT
case 'o': /* octal format */
n = 8;
goto xx;
#endif /* EXCLUDE_FORMAT_IO_OCT_FMT */
#ifndef EXCLUDE_FORMAT_IO_HEX_FMT
case 'X': /* hex (upper case ABCDEF) */
case 'x': /* hex (lower case abcdef) */
n = 16;
#endif /* EXCLUDE_FORMAT_IO_HEX_FMT */
#if (!defined(EXCLUDE_FORMAT_IO_OCT_FMT)) || \
(!defined(EXCLUDE_FORMAT_IO_HEX_FMT)) || \
(!defined(EXCLUDE_FORMAT_IO_UNS_FMT))
xx:
if (prec_flag) /* no pad char if prec spec'ed*/
PADCHAR_EXP (padchar = ' ');
tempLong = LONGARG_EXP (longarg) ?
va_arg (arg, long) :
(SHORTARG_EXP (shortarg) ?
((long)(unsigned short) va_arg(arg, unsigned)) :
((long) va_arg (arg, unsigned)));
len = _ltostr (tempLong, str += 2, n);
if (ALT_EXP (alt) && (n != 10)) {
if ((n == 8) && (tempLong != 0)) {
if (prec <= len) {
prec = len+1; /* alt format in octal fmt */
}
}
else {
if ((n == 16) && (tempLong)) {
prefix_cnt = 2; /* hex alt format */
len += 2;
str -= 2;
*str = '0';
*(str + 1) = 'X';
}
}
}
if (c == 'x') {
char *tempStr = str;
for ( ; *tempStr; tempStr++)
if (*tempStr >= 'A')
*tempStr += 'a' - 'A'; /* to lower case */
}
goto yy;
#endif /* (! EXCLUDE_FORMAT_IO_OCT_FMT) || .... */
#ifndef EXCLUDE_FORMAT_IO_FLOAT_FMT
case 'E': /* E format */
case 'e': /* e format */
case 'f': /* f format */
case 'G': /* G format */
case 'g': /* g format */
/* cgd no longer called here */
len = _ftoa (va_arg (arg, double), ++str,
c | (ALT_EXP(alt) ? (char) 0x80 : (char) 0) , prec);
/* hide alt in "fmt" */
if (*str == '-') {
prefix_cnt = 1;
} else {
if (PLUS_EXP(plus)||SPACE_EXP(space)) {
*--str = PLUS_EXP (plus) ? '+' : ' ';
len++;
prefix_cnt = 1;
}
}
prec = -1;
break;
#endif /* ! EXCLUDE_FORMAT_IO_FLOAT_FMT */
#ifndef EXCLUDE_FORMAT_IO_PNT_FMT
case 'p': /* pointer */
len = _ltostr ((long)(va_arg (arg, void *)), str, 16);
goto yy;
#endif /* ! EXCLUDE_FORMAT_IO_PNT_FMT */
#ifndef EXCLUDE_FORMAT_IO_NUMB_FMT
case 'n': /* write current nc */
if (LONGARG_EXP (longarg))
*(va_arg (arg, long *)) = nc;
else if (SHORTARG_EXP (shortarg))
*(va_arg (arg, short *)) = nc;
else
*(va_arg (arg, int *)) = nc;
continue; /* no output */
#endif /* ! EXCLUDE_FORMAT_IO_NUMB_FMT */
default:
(*trans)(c,fp);
nc++;
continue;
}
if ((n = width - len) > 0) /* extra space */
nc += n;
if (!LEFTJ_EXP(leftj)) { /* if not left-justified */
pad_field = width - max (prec + prefix_cnt, len);
if (PADCHAR_EXP (padchar == '0') && (len > 0)) {
while (prefix_cnt-- > 0) {
(*trans)(*str,fp); /* output char if needed */
str++;
nc++;
len--;
}
}
for (++pad_field; --pad_field > 0;) { /* Pad if */
(*trans)(PADCHAR_CHAR(padchar), fp); /* necessary */
--n;
}
if (PADCHAR_EXP (padchar == ' ') && (len > 0)) {
while (prefix_cnt-- > 0) {
(*trans)(*str,fp); /* output char if needed */
str++; /* for situation driven by */
nc++; /* precision */
len--;
}
}
for (++n; --n > 0;) /* pad */
(*trans)(char_flag ? ' ': '0', fp);
}
nc += len;
if (len > 0){
while (prefix_cnt-- > 0) {
(*trans)(*str,fp); /* output char if needed */
str++; /* for situation driven by */
len--; /* precision */
}
}
if (n > 0) { /* only true for left just. */
pad_field = prec - len; /* leading zeros ? */
for (++pad_field; --pad_field > 0;) {
(*trans)('0', fp);
--n; /* adjust counter */
}
}
for (++len; --len > 0;) {
(*trans)(*str,fp);
str++;
}
for (++n; --n > 0;) /* Pad on right w. blanks */
(*trans)(' ', fp);
}
}
return (nc);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -