From 339f5eb2e0676da591150015e157c38c4ab52a3e Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Fri, 9 Mar 2007 16:43:01 +0000 Subject: printf: allow hex/oct numbers; move functions around so that we have no forward declarations --- coreutils/printf.c | 217 +++++++++++++++++++++++++---------------------------- 1 file changed, 104 insertions(+), 113 deletions(-) (limited to 'coreutils/printf.c') diff --git a/coreutils/printf.c b/coreutils/printf.c index 0180d0e5a..a2a82d249 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -40,31 +40,29 @@ #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); static void multiconvert(const char *arg, void *result, converter convert) { - char s[16]; + char s[sizeof(int)*3 + 2]; + if (*arg == '"' || *arg == '\'') { sprintf(s, "%d", (unsigned char)arg[1]); arg = s; } convert(arg, result); - if (errno) /* Huh, looks strange... bug? */ + /* if there was conversion error, print unconverted string */ + if (errno) fputs(arg, stderr); } 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) { - *(long*)result = bb_strtol(arg, NULL, 10); + *(long*)result = bb_strtol(arg, NULL, 0); } 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); -int printf_main(int argc, char **argv) +static void print_direc(char *start, size_t length, int field_width, int precision, + const char *argument) { - char *format; - int args_used; - - if (argc <= 1 || argv[1][0] == '-') { - bb_show_usage(); - } + char *p; /* Null-terminated copy of % directive. */ - format = argv[1]; - argc -= 2; - argv += 2; + p = xmalloc((unsigned) (length + 1)); + strncpy(p, start, length); + p[length] = 0; - do { - args_used = print_formatted(format, argc, argv); - argc -= args_used; - argv += args_used; + 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; } - while (args_used > 0 && argc > 0); -/* if (argc > 0) - fprintf(stderr, "excess args ignored"); -*/ - - return EXIT_SUCCESS; + free(p); } /* 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) { - int save_argc = argc; /* Preserve original value. */ - char *f; /* Pointer into 'format'. */ - char *direc_start; /* Start of % directive. */ - size_t direc_length; /* Length of % directive. */ - int field_width; /* Arg to first '*', or -1 if none. */ - int precision; /* Arg to second '*', or -1 if none. */ + int save_argc = argc; /* Preserve original value. */ + char *f; /* Pointer into 'format'. */ + char *direc_start; /* Start of % directive. */ + size_t direc_length; /* Length of % directive. */ + int field_width; /* Arg to first '*', or -1 if none. */ + int precision; /* Arg to second '*', or -1 if none. */ for (f = format; *f; ++f) { switch (*f) { @@ -181,11 +229,12 @@ static int print_formatted(char *format, int argc, char **argv) --argc; } else field_width = 0; - } else + } else { while (isdigit(*f)) { ++f; ++direc_length; } + } if (*f == '.') { ++f; ++direc_length; @@ -222,14 +271,12 @@ static int print_formatted(char *format, int argc, char **argv) print_direc(direc_start, direc_length, field_width, precision, ""); break; - case '\\': if (*++f == 'c') exit(0); putchar(bb_process_escape_sequence((const char **)&f)); f--; break; - default: putchar(*f); } @@ -238,85 +285,29 @@ static int print_formatted(char *format, int argc, char **argv) return save_argc - argc; } -static void -print_direc(char *start, size_t length, int field_width, int precision, - const char *argument) +int printf_main(int argc, char **argv); +int printf_main(int argc, char **argv) { - 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; + char *format; + int args_used; - 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; + if (argc <= 1 || argv[1][0] == '-') { + bb_show_usage(); + } - 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; + format = argv[1]; + argc -= 2; + argv += 2; - case 'c': - printf(p, *argument); - break; + do { + args_used = print_formatted(format, argc, argv); + argc -= args_used; + argv += args_used; + } while (args_used > 0 && argc > 0); - 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; - } +/* if (argc > 0) + fprintf(stderr, "excess args ignored"); +*/ - free(p); + return EXIT_SUCCESS; } -- cgit v1.2.3