Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/coreutils/printf.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/coreutils/printf.c
r821 r1770 31 31 %b = print an argument string, interpreting backslash escapes 32 32 33 The `format' argument is re-used as many times as necessary33 The 'format' argument is re-used as many times as necessary 34 34 to convert all of the given arguments. 35 35 … … 39 39 // 19990508 Busy Boxed! Dave Cinege 40 40 41 #include <unistd.h> 42 #include <stdio.h> 43 #include <sys/types.h> 44 #include <string.h> 45 #include <errno.h> 46 #include <stdlib.h> 47 #include <fcntl.h> 48 #include <ctype.h> 49 #include <assert.h> 50 #include "busybox.h" 51 52 static int print_formatted (char *format, int argc, char **argv); 53 static void print_direc (char *start, size_t length, 54 int field_width, int precision, char *argument); 55 56 typedef int (*converter)(char *arg, void *result); 57 static void multiconvert(char *arg, void *result, converter convert) 58 { 59 char s[16]; 41 #include "libbb.h" 42 43 typedef void (*converter)(const char *arg, void *result); 44 45 static void multiconvert(const char *arg, void *result, converter convert) 46 { 47 char s[sizeof(int)*3 + 2]; 48 60 49 if (*arg == '"' || *arg == '\'') { 61 sprintf(s,"%d",(unsigned)*(++arg)); 62 arg=s; 63 } 64 if(convert(arg,result)) fprintf(stderr, "%s", arg); 65 } 66 67 static unsigned long xstrtoul(char *arg) 50 sprintf(s, "%d", (unsigned char)arg[1]); 51 arg = s; 52 } 53 convert(arg, result); 54 /* if there was conversion error, print unconverted string */ 55 if (errno) 56 fputs(arg, stderr); 57 } 58 59 static void conv_strtoul(const char *arg, void *result) 60 { 61 *(unsigned long*)result = bb_strtoul(arg, NULL, 0); 62 } 63 static void conv_strtol(const char *arg, void *result) 64 { 65 *(long*)result = bb_strtol(arg, NULL, 0); 66 } 67 static void conv_strtod(const char *arg, void *result) 68 { 69 char *end; 70 /* Well, this one allows leading whitespace... so what */ 71 /* What I like much less is that "-" is accepted too! :( */ 72 *(double*)result = strtod(arg, &end); 73 if (end[0]) errno = ERANGE; 74 } 75 76 static unsigned long my_xstrtoul(const char *arg) 68 77 { 69 78 unsigned long result; 70 71 multiconvert(arg,&result, (converter)safe_strtoul); 79 multiconvert(arg, &result, conv_strtoul); 72 80 return result; 73 81 } 74 82 75 static long xstrtol(char *arg)83 static long my_xstrtol(const char *arg) 76 84 { 77 85 long result; 78 multiconvert(arg, &result, (converter)safe_strtol);86 multiconvert(arg, &result, conv_strtol); 79 87 return result; 80 88 } 81 89 82 static double xstrtod(char *arg)90 static double my_xstrtod(const char *arg) 83 91 { 84 92 double result; 85 multiconvert(arg, &result, (converter)safe_strtod);93 multiconvert(arg, &result, conv_strtod); 86 94 return result; 87 95 } … … 100 108 } 101 109 102 int printf_main(int argc, char **argv) 103 { 104 char *format; 105 int args_used; 106 107 if (argc <= 1 || **(argv + 1) == '-') { 108 bb_show_usage(); 109 } 110 111 format = argv[1]; 112 argc -= 2; 113 argv += 2; 114 115 do { 116 args_used = print_formatted(format, argc, argv); 117 argc -= args_used; 118 argv += args_used; 119 } 120 while (args_used > 0 && argc > 0); 121 122 /* 123 if (argc > 0) 124 fprintf(stderr, "excess args ignored"); 125 */ 126 127 return EXIT_SUCCESS; 110 static void print_direc(char *start, size_t length, int field_width, int precision, 111 const char *argument) 112 { 113 char *p; /* Null-terminated copy of % directive. */ 114 115 p = xmalloc((unsigned) (length + 1)); 116 strncpy(p, start, length); 117 p[length] = 0; 118 119 switch (p[length - 1]) { 120 case 'd': 121 case 'i': 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; 183 } 184 185 free(p); 128 186 } 129 187 130 188 /* Print the text in FORMAT, using ARGV (with ARGC elements) for 131 arguments to any `%' directives.189 arguments to any '%' directives. 132 190 Return the number of elements of ARGV used. */ 133 191 134 192 static int print_formatted(char *format, int argc, char **argv) 135 193 { 136 int save_argc = argc; 137 char *f; /* Pointer into `format'. */138 char *direc_start; 139 size_t direc_length; 140 int field_width; 141 int precision; 194 int save_argc = argc; /* Preserve original value. */ 195 char *f; /* Pointer into 'format'. */ 196 char *direc_start; /* Start of % directive. */ 197 size_t direc_length; /* Length of % directive. */ 198 int field_width; /* Arg to first '*', or -1 if none. */ 199 int precision; /* Arg to second '*', or -1 if none. */ 142 200 143 201 for (f = format; *f; ++f) { … … 167 225 ++direc_length; 168 226 if (argc > 0) { 169 field_width = xstrtoul(*argv);227 field_width = my_xstrtoul(*argv); 170 228 ++argv; 171 229 --argc; 172 230 } else 173 231 field_width = 0; 174 } else 232 } else { 175 233 while (isdigit(*f)) { 176 234 ++f; 177 235 ++direc_length; 178 236 } 237 } 179 238 if (*f == '.') { 180 239 ++f; … … 184 243 ++direc_length; 185 244 if (argc > 0) { 186 precision = xstrtoul(*argv);245 precision = my_xstrtoul(*argv); 187 246 ++argv; 188 247 --argc; … … 200 259 } 201 260 /* 202 203 204 261 if (!strchr ("diouxXfeEgGcs", *f)) 262 fprintf(stderr, "%%%c: invalid directive", *f); 263 */ 205 264 ++direc_length; 206 265 if (argc > 0) { … … 213 272 precision, ""); 214 273 break; 215 216 274 case '\\': 217 275 if (*++f == 'c') … … 220 278 f--; 221 279 break; 222 223 280 default: 224 281 putchar(*f); … … 229 286 } 230 287 231 static void 232 print_direc(char *start, size_t length, int field_width, int precision, 233 char *argument) 234 { 235 char *p; /* Null-terminated copy of % directive. */ 236 237 p = xmalloc((unsigned) (length + 1)); 238 strncpy(p, start, length); 239 p[length] = 0; 240 241 switch (p[length - 1]) { 242 case 'd': 243 case 'i': 244 if (field_width < 0) { 245 if (precision < 0) 246 printf(p, xstrtol(argument)); 247 else 248 printf(p, precision, xstrtol(argument)); 249 } else { 250 if (precision < 0) 251 printf(p, field_width, xstrtol(argument)); 252 else 253 printf(p, field_width, precision, xstrtol(argument)); 254 } 255 break; 256 257 case 'o': 258 case 'u': 259 case 'x': 260 case 'X': 261 if (field_width < 0) { 262 if (precision < 0) 263 printf(p, xstrtoul(argument)); 264 else 265 printf(p, precision, xstrtoul(argument)); 266 } else { 267 if (precision < 0) 268 printf(p, field_width, xstrtoul(argument)); 269 else 270 printf(p, field_width, precision, xstrtoul(argument)); 271 } 272 break; 273 274 case 'f': 275 case 'e': 276 case 'E': 277 case 'g': 278 case 'G': 279 if (field_width < 0) { 280 if (precision < 0) 281 printf(p, xstrtod(argument)); 282 else 283 printf(p, precision, xstrtod(argument)); 284 } else { 285 if (precision < 0) 286 printf(p, field_width, xstrtod(argument)); 287 else 288 printf(p, field_width, precision, xstrtod(argument)); 289 } 290 break; 291 292 case 'c': 293 printf(p, *argument); 294 break; 295 296 case 's': 297 if (field_width < 0) { 298 if (precision < 0) 299 printf(p, argument); 300 else 301 printf(p, precision, argument); 302 } else { 303 if (precision < 0) 304 printf(p, field_width, argument); 305 else 306 printf(p, field_width, precision, argument); 307 } 308 break; 309 } 310 311 free(p); 312 } 288 int printf_main(int argc, char **argv); 289 int printf_main(int argc, char **argv) 290 { 291 char *format; 292 int args_used; 293 294 if (argc <= 1 || argv[1][0] == '-') { 295 bb_show_usage(); 296 } 297 298 format = argv[1]; 299 argc -= 2; 300 argv += 2; 301 302 do { 303 args_used = print_formatted(format, argc, argv); 304 argc -= args_used; 305 argv += args_used; 306 } while (args_used > 0 && argc > 0); 307 308 /* if (argc > 0) 309 fprintf(stderr, "excess args ignored"); 310 */ 311 312 return EXIT_SUCCESS; 313 }
Note:
See TracChangeset
for help on using the changeset viewer.