doprnt.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,011 行 · 第 1/2 页
C
1,011 行
* binary, and is equal to the maximum * negative number. * We assume a 2's complement machine */ case 'd': case 'D': case 'i': case 'I': /* Fetch the argument to be printed */ if (flagword & LENGTH) val = va_arg(args, long); else val = va_arg(args, int); /* Set buffer pointer to last digit */ p = bp = buf + MAXDIGS; /* If signed conversion, make sign */ if (val < 0) { prefix = "-"; prefixlength = 1; /* * Negate, checking in * advance for possible * overflow. */ if (val != HIBITL) val = -val; else /* number is -HIBITL; convert last */ /* digit now and get positive number */ *--bp = _lowdigit(&val); } else if (flagword & FPLUS) { prefix = "+"; prefixlength = 1; } else if (flagword & FBLANK) { prefix = " "; prefixlength = 1; } decimal: /* * If both the zero pad specifier and precision are * specified, the zero pad specifier is ignored. */ if((flagword & (DOTSEEN|PADZERO)) == (DOTSEEN|PADZERO)) flagword &= ~PADZERO; { register long qval = val; if (qval <= 9) { if (qval != 0 || !(flagword & DOTSEEN)) *--bp = qval + '0'; } else { do { n = qval; qval /= 10; *--bp = n - qval * 10 + '0'; } while (qval > 9); *--bp = qval + '0'; } } /* Calculate minimum padding zero requirement */ if (flagword & DOTSEEN) { register leadzeroes = prec - (p - bp); if (leadzeroes > 0) { otherlength = lzero = leadzeroes; flagword |= LZERO; } } break; case 'U': case 'u': /* Fetch the argument to be printed */ if (flagword & LENGTH) val = va_arg(args, long); else val = va_arg(args, unsigned); p = bp = buf + MAXDIGS; if (val & HIBITL) *--bp = _lowdigit(&val); goto decimal; /* * non-decimal fixed point representations * for radix equal to a power of two * * "mradix" is one less than the radix for the conversion. * "lradix" is one less than the base 2 log * of the radix for the conversion. Conversion is unsigned. * HIBITL is 100...000 * binary, and is equal to the maximum * negative number. * We assume a 2's complement machine */ case 'O': case 'o': mradix = 7; lradix = 2; goto fixed; case 'p': /* pointer: treat as %08x */ width = 8; prec = 0; flagword = PADZERO; /* FALLTHRU */ case 'X': case 'x': mradix = 15; lradix = 3; fixed: /* * If both the zero pad specifier and precision are * specified, the zero pad specifier is ignored. */ if((flagword & (DOTSEEN|PADZERO)) == (DOTSEEN|PADZERO)) flagword &= ~PADZERO; /* Fetch the argument to be printed */ if (flagword & LENGTH) val = va_arg(args, long); else val = va_arg(args, unsigned); /* Set translate table for digits */ tab = (fcode == 'X') ? "0123456789ABCDEF" : "0123456789abcdef"; /* Develop the digits of the value */ p = bp = buf + MAXDIGS; { register long qval = val; if (qval == 0) { if (!(flagword & DOTSEEN)) { otherlength = lzero = 1; flagword |= LZERO; } } else do { *--bp = tab[qval & mradix]; qval = ((qval >> 1) & ~HIBITL) >> lradix; } while (qval != 0); } /* Calculate minimum padding zero requirement */ if (flagword & DOTSEEN) { register leadzeroes = prec - (p - bp); if (leadzeroes > 0) { otherlength = lzero = leadzeroes; flagword |= LZERO; } } /* Handle the # flag */ if (flagword & FSHARP && val != 0) switch (fcode) { case 'O': case 'o': if (!(flagword & LZERO)) { otherlength = lzero = 1; flagword |= LZERO; } break; case 'x': prefix = "0x"; prefixlength = 2; break; case 'X': prefix = "0X"; prefixlength = 2; break; } break; case 'E': case 'e': /* * E-format. The general strategy * here is fairly easy: we take * what ecvt gives us and re-format it. */ /* Establish default precision */ if (!(flagword & DOTSEEN)) prec = 6; /* Develop the mantissa */ bp = cvt(&args, min(prec + 1, MAXECVT), &decpt, &sign, 0, &fp_class, &is_zero); /* Determine the prefix */ e_merge:#if defined(mips) && !defined(MOXIE) if (fp_class == FP_QNAN || fp_class == FP_SNAN) { bp = "NaN"; p = bp + strlen(bp); break; } if (fp_class == FP_POS_INF) { if(flagword & FPLUS) bp = "+Infinity"; else bp = "Infinity"; p = bp + strlen(bp); break; } if (fp_class == FP_NEG_INF) { bp = "-Infinity"; p = bp + strlen(bp); break; }#endif if (sign) { prefix = "-"; prefixlength = 1; } else if (flagword & FPLUS) { prefix = "+"; prefixlength = 1; } else if (flagword & FBLANK) { prefix = " "; prefixlength = 1; } /* Place the first digit in the buffer*/ p = &buf[0]; *p++ = (*bp != '\0') ? *bp++ : '0'; /* Put in a decimal point if needed */ if (prec != 0 || (flagword & FSHARP)) *p++ = _lc_radix; /* Create the rest of the mantissa */ { register rz = prec; for ( ; rz > 0 && *bp != '\0'; --rz) *p++ = *bp++; if (rz > 0) { otherlength = rzero = rz; flagword |= RZERO; } } bp = &buf[0]; /* Create the exponent */ *(suffix = &expbuf[MAXESIZ]) = '\0'; if (!is_zero) { register int nn = decpt - 1; if (nn < 0) nn = -nn; for ( ; nn > 9; nn /= 10) *--suffix = todigit(nn % 10); *--suffix = todigit(nn); } /* Prepend leading zeroes to the exponent */ while (suffix > &expbuf[MAXESIZ - 2]) *--suffix = '0'; /* Put in the exponent sign */ *--suffix = (decpt > 0 || is_zero) ? '+' : '-'; /* Put in the e */ *--suffix = isupper(fcode) ? 'E' : 'e'; /* compute size of suffix */ otherlength += (suffixlength = &expbuf[MAXESIZ] - suffix); flagword |= SUFFIX; break; case 'f': /* * F-format floating point. This is a * good deal less simple than E-format. * The overall strategy will be to call * fcvt, reformat its result into buf, * and calculate how many trailing * zeroes will be required. There will * never be any leading zeroes needed. */ /* Establish default precision */ if (!(flagword & DOTSEEN)) prec = 6; /* Do the conversion */ bp = cvt(&args, min(prec, MAXFCVT), &decpt, &sign, 1, &fp_class, &is_zero); /* Determine the prefix */ f_merge:#if defined(mips) && !defined(MOXIE) if (fp_class == FP_QNAN || fp_class == FP_SNAN) { bp = "NaN"; p = bp + strlen(bp); break; } if (fp_class == FP_POS_INF) { if(flagword & FPLUS) bp = "+Infinity"; else bp = "Infinity"; p = bp + strlen(bp); break; } if (fp_class == FP_NEG_INF) { bp = "-Infinity"; p = bp + strlen(bp); break; }#endif if (sign && decpt > -prec && *bp != '0') { prefix = "-"; prefixlength = 1; } else if (flagword & FPLUS) { prefix = "+"; prefixlength = 1; } else if (flagword & FBLANK) { prefix = " "; prefixlength = 1; } /* Initialize buffer pointer */ p = &buf[0]; { register int nn = decpt; /* Emit the digits before the decimal point */ k = 0; do { *p++ = (nn <= 0 || *bp == '\0' || k >= MAXFSIG) ? '0' : (k++, *bp++); } while (--nn > 0); /* Decide whether we need a decimal point */ if ((flagword & FSHARP) || prec > 0) *p++ = _lc_radix; /* Digits (if any) after the decimal point */ nn = min(prec, MAXFCVT); if (prec > nn) { flagword |= RZERO; otherlength = rzero = prec - nn; } while (--nn >= 0) *p++ = (++decpt <= 0 || *bp == '\0' || k >= MAXFSIG) ? '0' : (k++, *bp++); } bp = &buf[0]; break; case 'G': case 'g': /* * g-format. We play around a bit * and then jump into e or f, as needed. */ /* Establish default precision */ if (!(flagword & DOTSEEN)) prec = 6; else if (prec == 0) prec = 1; /* Do the conversion */ bp = cvt(&args, min(prec, MAXECVT), &decpt, &sign, 0, &fp_class, &is_zero); if (is_zero) decpt = 1; { register int kk = prec; if (!(flagword & FSHARP)) { n = strlen(bp); if (n < kk) kk = n; while (kk >= 1 && bp[kk-1] == '0') --kk; } if (decpt < -3 || decpt > prec) { prec = kk - 1; goto e_merge; } prec = kk - decpt; goto f_merge; } case '%': buf[0] = fcode; goto c_merge; case 'c': buf[0] = va_arg(args, int); c_merge: p = (bp = &buf[0]) + 1; break; case 's': bp = va_arg(args, char *); if (bp == NULL) { /* DAG -- robustness addition */ bp = "(null)"; flagword &= ~DOTSEEN; } if (!(flagword & DOTSEEN)) p = bp + strlen(bp); else { /* a strnlen function would be useful here! */ register char *qp = bp; while (*qp++ != '\0' && --prec >= 0) ; p = qp - 1; } break; case 'n': if(flagword & LENGTH){ lnp = va_arg(args, long *); if (lnp != NULL) *lnp = count; } else if(flagword & SHORT){ snp = va_arg(args, short *); if (snp != NULL) *snp = count; } else { np = va_arg(args, int *); if (np != NULL) *np = count; } p = bp = &buf[0]; width = prefixlength = otherlength = flagword = 0; break; default: /* this is technically an error; what we do is to */ /* back up the format pointer to the offending char */ /* and continue with the format scan */ format--; continue; } /* Calculate number of padding blanks */ k = (n = p - bp) + prefixlength + otherlength; if (width <= k) count += k; else { count += width; /* Set up for padding zeroes if requested */ /* Otherwise emit padding blanks unless output is */ /* to be left-justified. */ if (flagword & PADZERO) { if (!(flagword & LZERO)) { flagword |= LZERO; lzero = width - k; } else lzero += width - k; k = width; /* cancel padding blanks */ } else /* Blanks on left if required */ if (!(flagword & FMINUS)) PAD(_blanks, width - k); } /* Prefix, if any */ if (prefixlength != 0) PUT(prefix, prefixlength); /* Zeroes on the left */ if (flagword & LZERO) PAD(_zeroes, lzero); /* The value itself */ if (n > 0) PUT(bp, n); if (flagword & (RZERO | SUFFIX | FMINUS)) { /* Zeroes on the right */ if (flagword & RZERO) PAD(_zeroes, rzero); /* The suffix */ if (flagword & SUFFIX) PUT(suffix, suffixlength); /* Blanks on the right if required */ if (flagword & FMINUS && width > k) PAD(_blanks, width - k); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?