printf: allow hex/oct numbers; move functions around

so that we have no forward declarations
This commit is contained in:
Denis Vlasenko 2007-03-09 16:43:01 +00:00
parent 48e71c188f
commit 339f5eb2e0

View File

@ -40,31 +40,29 @@
#include "busybox.h" #include "busybox.h"
static int print_formatted(char *format, int argc, char **argv);
static void print_direc(char *start, size_t length,
int field_width, int precision, const char *argument);
typedef void (*converter)(const char *arg, void *result); typedef void (*converter)(const char *arg, void *result);
static void multiconvert(const char *arg, void *result, converter convert) static void multiconvert(const char *arg, void *result, converter convert)
{ {
char s[16]; char s[sizeof(int)*3 + 2];
if (*arg == '"' || *arg == '\'') { if (*arg == '"' || *arg == '\'') {
sprintf(s, "%d", (unsigned char)arg[1]); sprintf(s, "%d", (unsigned char)arg[1]);
arg = s; arg = s;
} }
convert(arg, result); convert(arg, result);
if (errno) /* Huh, looks strange... bug? */ /* if there was conversion error, print unconverted string */
if (errno)
fputs(arg, stderr); fputs(arg, stderr);
} }
static void conv_strtoul(const char *arg, void *result) static void conv_strtoul(const char *arg, void *result)
{ {
*(unsigned long*)result = bb_strtoul(arg, NULL, 10); *(unsigned long*)result = bb_strtoul(arg, NULL, 0);
} }
static void conv_strtol(const char *arg, void *result) static void conv_strtol(const char *arg, void *result)
{ {
*(long*)result = bb_strtol(arg, NULL, 10); *(long*)result = bb_strtol(arg, NULL, 0);
} }
static void conv_strtod(const char *arg, void *result) static void conv_strtod(const char *arg, void *result)
{ {
@ -109,32 +107,82 @@ static void print_esc_string(char *str)
} }
} }
int printf_main(int argc, char **argv); static void print_direc(char *start, size_t length, int field_width, int precision,
int printf_main(int argc, char **argv) const char *argument)
{ {
char *format; char *p; /* Null-terminated copy of % directive. */
int args_used;
if (argc <= 1 || argv[1][0] == '-') { p = xmalloc((unsigned) (length + 1));
bb_show_usage(); 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;
} }
format = argv[1]; free(p);
argc -= 2;
argv += 2;
do {
args_used = print_formatted(format, argc, argv);
argc -= args_used;
argv += args_used;
}
while (args_used > 0 && argc > 0);
/* if (argc > 0)
fprintf(stderr, "excess args ignored");
*/
return EXIT_SUCCESS;
} }
/* Print the text in FORMAT, using ARGV (with ARGC elements) for /* Print the text in FORMAT, using ARGV (with ARGC elements) for
@ -143,12 +191,12 @@ int printf_main(int argc, char **argv)
static int print_formatted(char *format, int argc, char **argv) static int print_formatted(char *format, int argc, char **argv)
{ {
int save_argc = argc; /* Preserve original value. */ int save_argc = argc; /* Preserve original value. */
char *f; /* Pointer into 'format'. */ char *f; /* Pointer into 'format'. */
char *direc_start; /* Start of % directive. */ char *direc_start; /* Start of % directive. */
size_t direc_length; /* Length of % directive. */ size_t direc_length; /* Length of % directive. */
int field_width; /* Arg to first '*', or -1 if none. */ int field_width; /* Arg to first '*', or -1 if none. */
int precision; /* Arg to second '*', or -1 if none. */ int precision; /* Arg to second '*', or -1 if none. */
for (f = format; *f; ++f) { for (f = format; *f; ++f) {
switch (*f) { switch (*f) {
@ -181,11 +229,12 @@ static int print_formatted(char *format, int argc, char **argv)
--argc; --argc;
} else } else
field_width = 0; field_width = 0;
} else } else {
while (isdigit(*f)) { while (isdigit(*f)) {
++f; ++f;
++direc_length; ++direc_length;
} }
}
if (*f == '.') { if (*f == '.') {
++f; ++f;
++direc_length; ++direc_length;
@ -222,14 +271,12 @@ static int print_formatted(char *format, int argc, char **argv)
print_direc(direc_start, direc_length, field_width, print_direc(direc_start, direc_length, field_width,
precision, ""); precision, "");
break; break;
case '\\': case '\\':
if (*++f == 'c') if (*++f == 'c')
exit(0); exit(0);
putchar(bb_process_escape_sequence((const char **)&f)); putchar(bb_process_escape_sequence((const char **)&f));
f--; f--;
break; break;
default: default:
putchar(*f); putchar(*f);
} }
@ -238,85 +285,29 @@ static int print_formatted(char *format, int argc, char **argv)
return save_argc - argc; return save_argc - argc;
} }
static void int printf_main(int argc, char **argv);
print_direc(char *start, size_t length, int field_width, int precision, int printf_main(int argc, char **argv)
const char *argument)
{ {
char *p; /* Null-terminated copy of % directive. */ char *format;
int args_used;
p = xmalloc((unsigned) (length + 1)); if (argc <= 1 || argv[1][0] == '-') {
strncpy(p, start, length); bb_show_usage();
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); format = argv[1];
argc -= 2;
argv += 2;
do {
args_used = print_formatted(format, argc, argv);
argc -= args_used;
argv += args_used;
} while (args_used > 0 && argc > 0);
/* if (argc > 0)
fprintf(stderr, "excess args ignored");
*/
return EXIT_SUCCESS;
} }