aboutsummaryrefslogtreecommitdiff
path: root/coreutils/printf.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-03-09 16:43:01 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-03-09 16:43:01 +0000
commit339f5eb2e0676da591150015e157c38c4ab52a3e (patch)
tree99cb25fc88b576cdc2d795a61fd85655922b8748 /coreutils/printf.c
parent48e71c188f324a6d20189ddee3c2456c4f016e86 (diff)
downloadbusybox-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.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 @@
40 40
41#include "busybox.h" 41#include "busybox.h"
42 42
43static int print_formatted(char *format, int argc, char **argv);
44static void print_direc(char *start, size_t length,
45 int field_width, int precision, const char *argument);
46
47typedef void (*converter)(const char *arg, void *result); 43typedef void (*converter)(const char *arg, void *result);
48 44
49static void multiconvert(const char *arg, void *result, converter convert) 45static 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
61static void conv_strtoul(const char *arg, void *result) 59static 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}
65static void conv_strtol(const char *arg, void *result) 63static 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}
69static void conv_strtod(const char *arg, void *result) 67static 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
112int printf_main(int argc, char **argv); 110static void print_direc(char *start, size_t length, int field_width, int precision,
113int 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
144static int print_formatted(char *format, int argc, char **argv) 192static 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
241static void 288int printf_main(int argc, char **argv);
242print_direc(char *start, size_t length, int field_width, int precision, 289int 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}