+ switch (format[fmt_length - 1]) {
+ case 'c':
+ printf(format, *argument);
+ break;
+ case 'd':
+ case 'i':
+ llv = my_xstrtoll(argument);
+ print_long:
+ if (!have_width) {
+ if (!have_prec)
+ printf(format, llv);
+ else
+ printf(format, precision, llv);
+ } else {
+ if (!have_prec)
+ printf(format, field_width, llv);
+ else
+ printf(format, field_width, precision, llv);
+ }
+ break;
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ llv = my_xstrtoull(argument);
+ /* cheat: unsigned long and long have same width, so... */
+ goto print_long;
+ case 's':
+ /* Are char* and long long the same? */
+ if (sizeof(argument) == sizeof(llv)) {
+ llv = (long long)(ptrdiff_t)argument;
+ goto print_long;
+ } else {
+ /* Hope compiler will optimize it out by moving call
+ * instruction after the ifs... */
+ if (!have_width) {
+ if (!have_prec)
+ printf(format, argument, /*unused:*/ argument, argument);
+ else
+ printf(format, precision, argument, /*unused:*/ argument);
+ } else {
+ if (!have_prec)
+ printf(format, field_width, argument, /*unused:*/ argument);
+ else
+ printf(format, field_width, precision, argument);
+ }
+ break;
+ }
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ dv = my_xstrtod(argument);
+ if (!have_width) {
+ if (!have_prec)
+ printf(format, dv);
+ else
+ printf(format, precision, dv);
+ } else {
+ if (!have_prec)
+ printf(format, field_width, dv);
+ else
+ printf(format, field_width, precision, dv);
+ }
+ break;
+ } /* switch */