diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-09 16:43:01 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-09 16:43:01 +0000 |
commit | 339f5eb2e0676da591150015e157c38c4ab52a3e (patch) | |
tree | 99cb25fc88b576cdc2d795a61fd85655922b8748 /coreutils/printf.c | |
parent | 48e71c188f324a6d20189ddee3c2456c4f016e86 (diff) | |
download | busybox-w32-339f5eb2e0676da591150015e157c38c4ab52a3e.tar.gz busybox-w32-339f5eb2e0676da591150015e157c38c4ab52a3e.tar.bz2 busybox-w32-339f5eb2e0676da591150015e157c38c4ab52a3e.zip |
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.c | 217 |
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 @@ | |||
40 | 40 | ||
41 | #include "busybox.h" | 41 | #include "busybox.h" |
42 | 42 | ||
43 | static int print_formatted(char *format, int argc, char **argv); | ||
44 | static void print_direc(char *start, size_t length, | ||
45 | int field_width, int precision, const char *argument); | ||
46 | |||
47 | typedef void (*converter)(const char *arg, void *result); | 43 | typedef void (*converter)(const char *arg, void *result); |
48 | 44 | ||
49 | static void multiconvert(const char *arg, void *result, converter convert) | 45 | static void multiconvert(const char *arg, void *result, converter convert) |
50 | { | 46 | { |
51 | char s[16]; | 47 | char s[sizeof(int)*3 + 2]; |
48 | |||
52 | if (*arg == '"' || *arg == '\'') { | 49 | if (*arg == '"' || *arg == '\'') { |
53 | sprintf(s, "%d", (unsigned char)arg[1]); | 50 | sprintf(s, "%d", (unsigned char)arg[1]); |
54 | arg = s; | 51 | arg = s; |
55 | } | 52 | } |
56 | convert(arg, result); | 53 | convert(arg, result); |
57 | if (errno) /* Huh, looks strange... bug? */ | 54 | /* if there was conversion error, print unconverted string */ |
55 | if (errno) | ||
58 | fputs(arg, stderr); | 56 | fputs(arg, stderr); |
59 | } | 57 | } |
60 | 58 | ||
61 | static void conv_strtoul(const char *arg, void *result) | 59 | static void conv_strtoul(const char *arg, void *result) |
62 | { | 60 | { |
63 | *(unsigned long*)result = bb_strtoul(arg, NULL, 10); | 61 | *(unsigned long*)result = bb_strtoul(arg, NULL, 0); |
64 | } | 62 | } |
65 | static void conv_strtol(const char *arg, void *result) | 63 | static void conv_strtol(const char *arg, void *result) |
66 | { | 64 | { |
67 | *(long*)result = bb_strtol(arg, NULL, 10); | 65 | *(long*)result = bb_strtol(arg, NULL, 0); |
68 | } | 66 | } |
69 | static void conv_strtod(const char *arg, void *result) | 67 | static void conv_strtod(const char *arg, void *result) |
70 | { | 68 | { |
@@ -109,32 +107,82 @@ static void print_esc_string(char *str) | |||
109 | } | 107 | } |
110 | } | 108 | } |
111 | 109 | ||
112 | int printf_main(int argc, char **argv); | 110 | static void print_direc(char *start, size_t length, int field_width, int precision, |
113 | int printf_main(int argc, char **argv) | 111 | const char *argument) |
114 | { | 112 | { |
115 | char *format; | 113 | char *p; /* Null-terminated copy of % directive. */ |
116 | int args_used; | ||
117 | |||
118 | if (argc <= 1 || argv[1][0] == '-') { | ||
119 | bb_show_usage(); | ||
120 | } | ||
121 | 114 | ||
122 | format = argv[1]; | 115 | p = xmalloc((unsigned) (length + 1)); |
123 | argc -= 2; | 116 | strncpy(p, start, length); |
124 | argv += 2; | 117 | p[length] = 0; |
125 | 118 | ||
126 | do { | 119 | switch (p[length - 1]) { |
127 | args_used = print_formatted(format, argc, argv); | 120 | case 'd': |
128 | argc -= args_used; | 121 | case 'i': |
129 | argv += args_used; | 122 | if (field_width < 0) { |
123 | if (precision < 0) | ||
124 | printf(p, my_xstrtol(argument)); | ||
125 | else | ||
126 | printf(p, precision, my_xstrtol(argument)); | ||
127 | } else { | ||
128 | if (precision < 0) | ||
129 | printf(p, field_width, my_xstrtol(argument)); | ||
130 | else | ||
131 | printf(p, field_width, precision, my_xstrtol(argument)); | ||
132 | } | ||
133 | break; | ||
134 | case 'o': | ||
135 | case 'u': | ||
136 | case 'x': | ||
137 | case 'X': | ||
138 | if (field_width < 0) { | ||
139 | if (precision < 0) | ||
140 | printf(p, my_xstrtoul(argument)); | ||
141 | else | ||
142 | printf(p, precision, my_xstrtoul(argument)); | ||
143 | } else { | ||
144 | if (precision < 0) | ||
145 | printf(p, field_width, my_xstrtoul(argument)); | ||
146 | else | ||
147 | printf(p, field_width, precision, my_xstrtoul(argument)); | ||
148 | } | ||
149 | break; | ||
150 | case 'f': | ||
151 | case 'e': | ||
152 | case 'E': | ||
153 | case 'g': | ||
154 | case 'G': | ||
155 | if (field_width < 0) { | ||
156 | if (precision < 0) | ||
157 | printf(p, my_xstrtod(argument)); | ||
158 | else | ||
159 | printf(p, precision, my_xstrtod(argument)); | ||
160 | } else { | ||
161 | if (precision < 0) | ||
162 | printf(p, field_width, my_xstrtod(argument)); | ||
163 | else | ||
164 | printf(p, field_width, precision, my_xstrtod(argument)); | ||
165 | } | ||
166 | break; | ||
167 | case 'c': | ||
168 | printf(p, *argument); | ||
169 | break; | ||
170 | case 's': | ||
171 | if (field_width < 0) { | ||
172 | if (precision < 0) | ||
173 | printf(p, argument); | ||
174 | else | ||
175 | printf(p, precision, argument); | ||
176 | } else { | ||
177 | if (precision < 0) | ||
178 | printf(p, field_width, argument); | ||
179 | else | ||
180 | printf(p, field_width, precision, argument); | ||
181 | } | ||
182 | break; | ||
130 | } | 183 | } |
131 | while (args_used > 0 && argc > 0); | ||
132 | 184 | ||
133 | /* if (argc > 0) | 185 | free(p); |
134 | fprintf(stderr, "excess args ignored"); | ||
135 | */ | ||
136 | |||
137 | return EXIT_SUCCESS; | ||
138 | } | 186 | } |
139 | 187 | ||
140 | /* Print the text in FORMAT, using ARGV (with ARGC elements) for | 188 | /* Print the text in FORMAT, using ARGV (with ARGC elements) for |
@@ -143,12 +191,12 @@ int printf_main(int argc, char **argv) | |||
143 | 191 | ||
144 | static int print_formatted(char *format, int argc, char **argv) | 192 | static int print_formatted(char *format, int argc, char **argv) |
145 | { | 193 | { |
146 | int save_argc = argc; /* Preserve original value. */ | 194 | int save_argc = argc; /* Preserve original value. */ |
147 | char *f; /* Pointer into 'format'. */ | 195 | char *f; /* Pointer into 'format'. */ |
148 | char *direc_start; /* Start of % directive. */ | 196 | char *direc_start; /* Start of % directive. */ |
149 | size_t direc_length; /* Length of % directive. */ | 197 | size_t direc_length; /* Length of % directive. */ |
150 | int field_width; /* Arg to first '*', or -1 if none. */ | 198 | int field_width; /* Arg to first '*', or -1 if none. */ |
151 | int precision; /* Arg to second '*', or -1 if none. */ | 199 | int precision; /* Arg to second '*', or -1 if none. */ |
152 | 200 | ||
153 | for (f = format; *f; ++f) { | 201 | for (f = format; *f; ++f) { |
154 | switch (*f) { | 202 | switch (*f) { |
@@ -181,11 +229,12 @@ static int print_formatted(char *format, int argc, char **argv) | |||
181 | --argc; | 229 | --argc; |
182 | } else | 230 | } else |
183 | field_width = 0; | 231 | field_width = 0; |
184 | } else | 232 | } else { |
185 | while (isdigit(*f)) { | 233 | while (isdigit(*f)) { |
186 | ++f; | 234 | ++f; |
187 | ++direc_length; | 235 | ++direc_length; |
188 | } | 236 | } |
237 | } | ||
189 | if (*f == '.') { | 238 | if (*f == '.') { |
190 | ++f; | 239 | ++f; |
191 | ++direc_length; | 240 | ++direc_length; |
@@ -222,14 +271,12 @@ static int print_formatted(char *format, int argc, char **argv) | |||
222 | print_direc(direc_start, direc_length, field_width, | 271 | print_direc(direc_start, direc_length, field_width, |
223 | precision, ""); | 272 | precision, ""); |
224 | break; | 273 | break; |
225 | |||
226 | case '\\': | 274 | case '\\': |
227 | if (*++f == 'c') | 275 | if (*++f == 'c') |
228 | exit(0); | 276 | exit(0); |
229 | putchar(bb_process_escape_sequence((const char **)&f)); | 277 | putchar(bb_process_escape_sequence((const char **)&f)); |
230 | f--; | 278 | f--; |
231 | break; | 279 | break; |
232 | |||
233 | default: | 280 | default: |
234 | putchar(*f); | 281 | putchar(*f); |
235 | } | 282 | } |
@@ -238,85 +285,29 @@ static int print_formatted(char *format, int argc, char **argv) | |||
238 | return save_argc - argc; | 285 | return save_argc - argc; |
239 | } | 286 | } |
240 | 287 | ||
241 | static void | 288 | int printf_main(int argc, char **argv); |
242 | print_direc(char *start, size_t length, int field_width, int precision, | 289 | int printf_main(int argc, char **argv) |
243 | const char *argument) | ||
244 | { | 290 | { |
245 | char *p; /* Null-terminated copy of % directive. */ | 291 | char *format; |
246 | 292 | int args_used; | |
247 | p = xmalloc((unsigned) (length + 1)); | ||
248 | strncpy(p, start, length); | ||
249 | p[length] = 0; | ||
250 | |||
251 | switch (p[length - 1]) { | ||
252 | case 'd': | ||
253 | case 'i': | ||
254 | if (field_width < 0) { | ||
255 | if (precision < 0) | ||
256 | printf(p, my_xstrtol(argument)); | ||
257 | else | ||
258 | printf(p, precision, my_xstrtol(argument)); | ||
259 | } else { | ||
260 | if (precision < 0) | ||
261 | printf(p, field_width, my_xstrtol(argument)); | ||
262 | else | ||
263 | printf(p, field_width, precision, my_xstrtol(argument)); | ||
264 | } | ||
265 | break; | ||
266 | 293 | ||
267 | case 'o': | 294 | if (argc <= 1 || argv[1][0] == '-') { |
268 | case 'u': | 295 | bb_show_usage(); |
269 | case 'x': | 296 | } |
270 | case 'X': | ||
271 | if (field_width < 0) { | ||
272 | if (precision < 0) | ||
273 | printf(p, my_xstrtoul(argument)); | ||
274 | else | ||
275 | printf(p, precision, my_xstrtoul(argument)); | ||
276 | } else { | ||
277 | if (precision < 0) | ||
278 | printf(p, field_width, my_xstrtoul(argument)); | ||
279 | else | ||
280 | printf(p, field_width, precision, my_xstrtoul(argument)); | ||
281 | } | ||
282 | break; | ||
283 | 297 | ||
284 | case 'f': | 298 | format = argv[1]; |
285 | case 'e': | 299 | argc -= 2; |
286 | case 'E': | 300 | argv += 2; |
287 | case 'g': | ||
288 | case 'G': | ||
289 | if (field_width < 0) { | ||
290 | if (precision < 0) | ||
291 | printf(p, my_xstrtod(argument)); | ||
292 | else | ||
293 | printf(p, precision, my_xstrtod(argument)); | ||
294 | } else { | ||
295 | if (precision < 0) | ||
296 | printf(p, field_width, my_xstrtod(argument)); | ||
297 | else | ||
298 | printf(p, field_width, precision, my_xstrtod(argument)); | ||
299 | } | ||
300 | break; | ||
301 | 301 | ||
302 | case 'c': | 302 | do { |
303 | printf(p, *argument); | 303 | args_used = print_formatted(format, argc, argv); |
304 | break; | 304 | argc -= args_used; |
305 | argv += args_used; | ||
306 | } while (args_used > 0 && argc > 0); | ||
305 | 307 | ||
306 | case 's': | 308 | /* if (argc > 0) |
307 | if (field_width < 0) { | 309 | fprintf(stderr, "excess args ignored"); |
308 | if (precision < 0) | 310 | */ |
309 | printf(p, argument); | ||
310 | else | ||
311 | printf(p, precision, argument); | ||
312 | } else { | ||
313 | if (precision < 0) | ||
314 | printf(p, field_width, argument); | ||
315 | else | ||
316 | printf(p, field_width, precision, argument); | ||
317 | } | ||
318 | break; | ||
319 | } | ||
320 | 311 | ||
321 | free(p); | 312 | return EXIT_SUCCESS; |
322 | } | 313 | } |