static void print_direc(char *start, size_t length, int field_width, int precision, const char *argument) { char *p; /* Null-terminated copy of % directive. */ p = xmalloc((unsigned) (length + 1)); strncpy(p, start, length); p[length] = 0; switch (p[length - 1]) { case 'd': case 'i': if (field_width < 0) { if (precision < 0) printf(p, my_xstrtol(argument)); else printf(p, precision, my_xstrtol(argument)); } else { if (precision < 0) printf(p, field_width, my_xstrtol(argument)); else printf(p, field_width, precision, my_xstrtol(argument)); } break; case 'o': case 'u': case 'x': case 'X': if (field_width < 0) { if (precision < 0) printf(p, my_xstrtoul(argument)); else printf(p, precision, my_xstrtoul(argument)); } else { if (precision < 0) printf(p, field_width, my_xstrtoul(argument)); else printf(p, field_width, precision, my_xstrtoul(argument)); } break; case 'f': case 'e': case 'E': case 'g': case 'G': if (field_width < 0) { if (precision < 0) printf(p, my_xstrtod(argument)); else printf(p, precision, my_xstrtod(argument)); } else { if (precision < 0) printf(p, field_width, my_xstrtod(argument)); else printf(p, field_width, precision, my_xstrtod(argument)); } break; case 'c': printf(p, *argument); break; case 's': if (field_width < 0) { if (precision < 0) printf(p, argument); else printf(p, precision, argument); } else { if (precision < 0) printf(p, field_width, argument); else printf(p, field_width, precision, argument); } break; } free(p); }
static void print_direc(char *format, unsigned fmt_length, int field_width, int precision, const char *argument) { long lv; double dv; char saved; char *have_prec, *have_width; have_prec = strstr(format, ".*"); have_width = strchr(format, '*'); if (have_width - 1 == have_prec) have_width = NULL; saved = format[fmt_length]; format[fmt_length] = '\0'; switch (format[fmt_length - 1]) { case 'c': printf(format, *argument); break; case 'd': case 'i': lv = my_xstrtol(argument); print_long: /* if (errno) return; - see comment at the top */ if (!have_width) { if (!have_prec) printf(format, lv); else printf(format, precision, lv); } else { if (!have_prec) printf(format, field_width, lv); else printf(format, field_width, precision, lv); } break; case 'o': case 'u': case 'x': case 'X': lv = my_xstrtoul(argument); /* cheat: unsigned long and long have same width, so... */ goto print_long; case 's': /* Are char* and long the same? (true for most arches) */ if (sizeof(argument) == sizeof(lv)) { lv = (long)(ptrdiff_t)argument; goto print_long; } else { /* Hope compiler will optimize it out */ if (!have_width) { if (!have_prec) printf(format, argument); else printf(format, precision, argument); } else { if (!have_prec) printf(format, field_width, argument); else printf(format, field_width, precision, argument); } break; } case 'f': case 'e': case 'E': case 'g': case 'G': dv = my_xstrtod(argument); /* if (errno) return; */ 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 */ format[fmt_length] = saved; }