aboutsummaryrefslogtreecommitdiff
path: root/coreutils/printf.c
diff options
context:
space:
mode:
authorGravatar Denis Vlasenko <vda.linux@googlemail.com>2007-03-09 16:43:01 +0000
committerGravatar Denis Vlasenko <vda.linux@googlemail.com>2007-03-09 16:43:01 +0000
commit339f5eb2e0676da591150015e157c38c4ab52a3e (patch)
tree99cb25fc88b576cdc2d795a61fd85655922b8748 /coreutils/printf.c
parent48e71c188f324a6d20189ddee3c2456c4f016e86 (diff)
downloadbusybox-339f5eb2e0676da591150015e157c38c4ab52a3e.tar.gz
busybox-339f5eb2e0676da591150015e157c38c4ab52a3e.tar.bz2
printf: allow hex/oct numbers; move functions around
so that we have no forward declarations
Diffstat (limited to 'coreutils/printf.c')
-rw-r--r--coreutils/printf.c217
1 files changed, 104 insertions, 113 deletions
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;
}