doprnt.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 792 行 · 第 1/2 页
C
792 行
/* Scan the field width and precision */ case '.': flagword |= DOTSEEN; prec = 0; goto charswitch; case '*': if (!(flagword & DOTSEEN)) { width = va_arg(args, int); if (width < 0) { width = -width; flagword ^= FMINUS; } } else { prec = va_arg(args, int); if (prec < 0) prec = 0; } goto charswitch; case '0': /* obsolescent spec: leading zero in width */ /* means pad with leading zeros */ if (!(flagword & (DOTSEEN | FMINUS))) flagword |= PADZERO; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { register num = fcode - '0'; while (isdigit(fcode = *format)) { num = num * 10 + fcode - '0'; format++; } if (flagword & DOTSEEN) prec = num; else width = num; goto charswitch; } /* Scan the length modifier */ case 'l': flagword |= LENGTH; /* No break */ case 'h': goto charswitch; /* * The character addressed by format must be * the format letter -- there is nothing * left for it to be. * * The status of the +, -, #, and blank * flags are reflected in the variable * "flagword". "width" and "prec" contain * numbers corresponding to the digit * strings before and after the decimal * point, respectively. If there was no * decimal point, then flagword & DOTSEEN * is false and the value of prec is meaningless. * * The following switch cases set things up * for printing. What ultimately gets * printed will be padding blanks, a * prefix, left padding zeroes, a value, * right padding zeroes, a suffix, and * more padding blanks. Padding blanks * will not appear simultaneously on both * the left and the right. Each case in * this switch will compute the value, and * leave in several variables the informa- * tion necessary to construct what is to * be printed. * * The prefix is a sign, a blank, "0x", * "0X", or null, and is addressed by * "prefix". * * The suffix is either null or an * exponent, and is addressed by "suffix". * If there is a suffix, the flagword bit * SUFFIX will be set. * * The value to be printed starts at "bp" * and continues up to and not including * "p". * * "lzero" and "rzero" will contain the * number of padding zeroes required on * the left and right, respectively. * The flagword bits LZERO and RZERO tell * whether padding zeros are required. * * The number of padding blanks, and * whether they go on the left or the * right, will be computed on exit from * the switch. */ /* * decimal fixed point representations * * HIBITL is 100...000 * binary, and is equal to the maximum * negative number. * We assume a 2's complement machine */ case 'd': /* 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: { 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': /* 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': mradix = 7; lradix = 2; goto fixed; case 'X': case 'x': mradix = 15; lradix = 3; fixed: /* 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': 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 '%': 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; 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)) blankpad(width - k); } /* Prefix, if any */ if (prefixlength != 0) PUT(prefix, prefixlength); /* Zeroes on the left */ if (flagword & LZERO) zeropad(lzero); /* The value itself */ if (n > 0) PUT(bp, n); if (flagword & (RZERO | SUFFIX | FMINUS)) { /* Zeroes on the right */ if (flagword & RZERO) zeropad(rzero); /* The suffix */ if (flagword & SUFFIX) PUT(suffix, suffixlength); /* Blanks on the right if required */ if (flagword & FMINUS && width > k) blankpad(width - k); } }}/* * Padding was done very naively before. It assumed no more than 20 * characters of padding. csh needs 21 in one place and maybe more. * * The routines below handle all cases. */staticblankpad(n)int n;{ static char *blanks = " "; /* 20 blanks */ while (n >= 20) { PUT(blanks, 20); n -= 20; } if (n > 0) { PUT(blanks, n); }}staticzeropad(n)int n;{ static char *zeros = "00000000000000000000"; /* 20 zeros */ while (n >= 20) { PUT(zeros, 20); n -= 20; } if (n > 0) { PUT(zeros, n); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?