in Frameworks/Foundation/FormatPrintf.mm [1049:1373]
int _doprnt(register const PrintType* fmt, va_list ap, PrintOutput* stream)
/* [<][>][^][v][top][bottom][index][help] */
{
register PrintType* s;
register int j;
int i, c, width, precision, zfill, flags, between_fill;
int nrchars = 0;
const PrintType* oldfmt;
PrintType *s1, buf[1025];
char *cs = NULL, *cs1 = NULL;
while ((c = *fmt++)) {
if (c != '%') {
#ifdef CPM
if (c == '\n') {
if (PrintPutC('\r', stream) == EOF)
return nrchars ? -nrchars : -1;
nrchars++;
}
#endif
if (PrintPutC(c, stream) == EOF) {
return nrchars ? -nrchars : -1;
}
nrchars++;
continue;
}
flags = 0;
do {
switch (*fmt) {
case '-':
flags |= FL_LJUST;
break;
case '+':
flags |= FL_SIGN;
break;
case ' ':
flags |= FL_SPACE;
break;
case '#':
flags |= FL_ALT;
break;
case '0':
flags |= FL_ZEROFILL;
break;
default:
flags |= FL_NOMORE;
continue;
}
fmt++;
} while (!(flags & FL_NOMORE));
oldfmt = fmt;
fmt = gnum(fmt, &width, &ap);
if (fmt != oldfmt) {
flags |= FL_WIDTHSPEC;
}
if (*fmt == '.') {
fmt++;
oldfmt = fmt;
fmt = gnum(fmt, &precision, &ap);
if (precision >= 0) {
flags |= FL_PRECSPEC;
}
}
if ((flags & FL_WIDTHSPEC) && width < 0) {
width = -width;
flags |= FL_LJUST;
}
if (!(flags & FL_WIDTHSPEC)) {
width = 0;
}
if (flags & FL_SIGN) {
flags &= ~FL_SPACE;
}
if (flags & FL_LJUST) {
flags &= ~FL_ZEROFILL;
}
s = s1 = buf;
switch (*fmt) {
case 'h':
fmt++;
if (*fmt == 'h') {
flags |= FL_CHAR;
fmt++;
} else {
flags |= FL_SHORT;
}
break;
case 'l':
flags |= FL_LONG;
fmt++;
break;
case 'L':
flags |= FL_LONGDOUBLE;
fmt++;
break;
#if SIZE_MAX != UINT_MAX
#error Unexpected size_t size
#elif PTRDIFF_MAX != INT_MAX
#error Unexpected ptrdiff_t size
#endif
case 'z': // size_t specifier
case 't': // ptrdiff_t specifier
fmt++;
break;
#if INTMAX_MAX != LLONG_MAX
#error Unexpected intmax_t size
#endif
case 'q': // long long specifier
case 'j': // intmax_t specifier
flags |= FL_LONG | FL_LONGLONG;
fmt++;
break;
}
if (*fmt == 'l') {
flags |= FL_LONGLONG;
fmt++;
}
switch (c = *fmt++) {
default:
#ifdef CPM
if (c == '\n') {
if (PrintPutC('\r', stream) == EOF)
return nrchars ? -nrchars : -1;
nrchars++;
}
#endif
if (PrintPutC(c, stream) == EOF) {
return nrchars ? -nrchars : -1;
}
nrchars++;
continue;
case 'n':
if (flags & FL_SHORT) {
*EbrPtr(ap, short*) = (short)nrchars;
} else if (flags & FL_LONG) {
*EbrPtr(ap, long*) = (long)nrchars;
} else {
*EbrPtr(ap, int*) = (int)nrchars;
}
continue;
case 's':
case 'S':
#ifdef UTF8CStrings
cs1 = EbrPtr(ap, char*);
if (cs1 == NULL) {
cs1 = PrintNullStringC; //"(null)";
}
cs = cs1;
while (precision || !(flags & FL_PRECSPEC)) {
if (*cs == '\0') {
break;
}
cs++;
precision--;
}
#else
s1 = EbrPtr(ap, PrintType*);
if (s1 == NULL)
s1 = PrintNullString; //"(null)";
s = s1;
while (precision || !(flags & FL_PRECSPEC)) {
if (*s == '\0')
break;
s++;
precision--;
}
#endif
break;
case '@': {
id ptr = EbrVal(ap, id);
id str = [ptr description];
s1 = (PrintType*)[str cStringUsingEncoding:PrintEncodingType];
if (s1 == NULL) {
s1 = PrintNullString; //"(null)";
}
s = s1;
while (precision || !(flags & FL_PRECSPEC)) {
if (*s == '\0') {
break;
}
s++;
precision--;
}
} break;
case 'p':
set_pointer(flags);
/* fallthrough */
case 'b':
case 'o':
case 'u':
case 'x':
case 'X':
if (!(flags & FL_PRECSPEC)) {
precision = 1;
} else if (c != 'p') {
flags &= ~FL_ZEROFILL;
}
s = o_print(&ap, flags, s, c, precision, 0);
break;
case 'd':
case 'i':
flags |= FL_SIGNEDCONV;
if (!(flags & FL_PRECSPEC)) {
precision = 1;
} else {
flags &= ~FL_ZEROFILL;
}
s = o_print(&ap, flags, s, c, precision, 1);
break;
case 'c':
case 'C':
*s++ = EbrVal(ap, int);
break;
#ifndef NOFLOAT
case 'G':
case 'g':
if ((flags & FL_PRECSPEC) && (precision == 0)) {
precision = 1;
}
case 'f':
case 'E':
case 'e':
if (!(flags & FL_PRECSPEC)) {
precision = 6;
}
if (precision >= sizeof(buf)) {
precision = sizeof(buf) - 1;
}
flags |= FL_SIGNEDCONV;
s = _f_print(&ap, flags, s, c, precision);
break;
#endif /* NOFLOAT */
case 'r':
assert(0);
/*
ap = va_arg(ap, StackReader*);
fmt = va_arg(ap, char *);
*/
continue;
}
zfill = ' ';
if (flags & FL_ZEROFILL) {
zfill = '0';
}
j = s - s1;
if (cs != NULL) {
j = cs - cs1;
}
/* between_fill is true under the following conditions:
* 1- the fill character is '0'
* and
* 2a- the number is of the form 0x... or 0X...
* or
* 2b- the number contains a sign or space
*/
between_fill = 0;
if ((flags & FL_ZEROFILL) &&
(((c == 'x' || c == 'X') && (flags & FL_ALT)) || (c == 'p') ||
((flags & FL_SIGNEDCONV) && ((cs1 ? *cs1 : *s1) == '+' || (cs1 ? *cs1 : *s1) == '-' || (cs1 ? *cs1 : *s1) == ' ')))) {
between_fill++;
}
if ((i = width - j) > 0) {
if (!(flags & FL_LJUST)) { /* right justify */
nrchars += i;
if (between_fill) {
if (flags & FL_SIGNEDCONV) {
j--;
nrchars++;
if (PrintPutC(cs1 ? *cs1++ : *s1++, stream) == EOF) {
return nrchars ? -nrchars : -1;
}
} else {
j -= 2;
nrchars += 2;
if ((PrintPutC(cs1 ? *cs1++ : *s1++, stream) == EOF) || (PrintPutC(cs1 ? *cs1++ : *s1++, stream) == EOF)) {
return nrchars ? -nrchars : -1;
}
}
}
do {
if (PrintPutC(zfill, stream) == EOF) {
return nrchars ? -nrchars : -1;
}
} while (--i);
}
}
nrchars += j;
while (--j >= 0) {
if (PrintPutC(cs1 ? *cs1++ : *s1++, stream) == EOF) {
return nrchars ? -nrchars : -1;
}
}
cs = cs1 = NULL;
if (i > 0) {
nrchars += i;
}
while (--i >= 0) {
if (PrintPutC(zfill, stream) == EOF) {
return nrchars ? -nrchars : -1;
}
}
}
return nrchars;
}