diff options
-rw-r--r-- | coreutils/printf.c | 108 |
1 files changed, 60 insertions, 48 deletions
diff --git a/coreutils/printf.c b/coreutils/printf.c index 01f730073..7d36fdd61 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c | |||
@@ -152,22 +152,70 @@ static double my_xstrtod(const char *arg) | |||
152 | } | 152 | } |
153 | 153 | ||
154 | #if ENABLE_PLATFORM_MINGW32 | 154 | #if ENABLE_PLATFORM_MINGW32 |
155 | static size_t fwrite_stdout(const char *s, const char *t) | 155 | static int buflen = 0; |
156 | static int bufmax = 0; | ||
157 | static char *buffer = NULL; | ||
158 | |||
159 | static void my_flush(void) | ||
160 | { | ||
161 | if (buffer) | ||
162 | full_write(STDOUT_FILENO, buffer, buflen); | ||
163 | free(buffer); | ||
164 | buffer = NULL; | ||
165 | buflen = bufmax = 0; | ||
166 | } | ||
167 | |||
168 | static int my_putchar(int ch) | ||
156 | { | 169 | { |
157 | return fwrite(s, t - s, 1, stdout); | 170 | if (buflen + 1 >= bufmax) { |
171 | bufmax += 256; | ||
172 | buffer = xrealloc(buffer, bufmax); | ||
173 | } | ||
174 | buffer[buflen++] = ch; | ||
175 | if (buflen > 40 && ch == '\n') | ||
176 | my_flush(); | ||
177 | return ch; | ||
158 | } | 178 | } |
179 | |||
180 | static int my_printf(const char *format, ...) | ||
181 | { | ||
182 | va_list list; | ||
183 | char *str; | ||
184 | int len; | ||
185 | |||
186 | va_start(list, format); | ||
187 | len = vasprintf(&str, format, list); | ||
188 | va_end(list); | ||
189 | |||
190 | if (len < 0) | ||
191 | bb_die_memory_exhausted(); | ||
192 | |||
193 | if (buflen + len >= bufmax) { | ||
194 | bufmax += 256 + len; | ||
195 | buffer = xrealloc(buffer, bufmax); | ||
196 | } | ||
197 | memcpy(buffer + buflen, str, len); | ||
198 | buflen += len; | ||
199 | free(str); | ||
200 | |||
201 | if (buflen > 40 && buffer[buflen-1] == '\n') | ||
202 | my_flush(); | ||
203 | |||
204 | return len; | ||
205 | } | ||
206 | |||
207 | #undef bb_putchar | ||
208 | #undef putchar | ||
209 | #undef printf | ||
210 | #define bb_putchar(c) my_putchar(c) | ||
211 | #define putchar(c) my_putchar(c) | ||
212 | #define printf(...) my_printf(__VA_ARGS__) | ||
159 | #endif | 213 | #endif |
160 | 214 | ||
161 | /* Handles %b; return 1 if output is to be short-circuited by \c */ | 215 | /* Handles %b; return 1 if output is to be short-circuited by \c */ |
162 | static int print_esc_string(const char *str) | 216 | static int print_esc_string(const char *str) |
163 | { | 217 | { |
164 | char c; | 218 | char c; |
165 | #if ENABLE_PLATFORM_MINGW32 | ||
166 | char *s, *t; | ||
167 | int ret = 0; | ||
168 | |||
169 | s = t = xstrdup(str); | ||
170 | #endif | ||
171 | while ((c = *str) != '\0') { | 219 | while ((c = *str) != '\0') { |
172 | str++; | 220 | str++; |
173 | if (c == '\\') { | 221 | if (c == '\\') { |
@@ -179,12 +227,7 @@ static int print_esc_string(const char *str) | |||
179 | } | 227 | } |
180 | } | 228 | } |
181 | else if (*str == 'c') { | 229 | else if (*str == 'c') { |
182 | #if ENABLE_PLATFORM_MINGW32 | ||
183 | ret = 1; | ||
184 | goto finish; | ||
185 | #else | ||
186 | return 1; | 230 | return 1; |
187 | #endif | ||
188 | } | 231 | } |
189 | { | 232 | { |
190 | /* optimization: don't force arg to be on-stack, | 233 | /* optimization: don't force arg to be on-stack, |
@@ -194,20 +237,10 @@ static int print_esc_string(const char *str) | |||
194 | str = z; | 237 | str = z; |
195 | } | 238 | } |
196 | } | 239 | } |
197 | #if ENABLE_PLATFORM_MINGW32 | ||
198 | *t++ = c; | ||
199 | #else | ||
200 | putchar(c); | 240 | putchar(c); |
201 | #endif | ||
202 | } | 241 | } |
203 | #if ENABLE_PLATFORM_MINGW32 | 242 | |
204 | finish: | ||
205 | fwrite_stdout(s, t); | ||
206 | free(s); | ||
207 | return ret; | ||
208 | #else | ||
209 | return 0; | 243 | return 0; |
210 | #endif | ||
211 | } | 244 | } |
212 | 245 | ||
213 | static void print_direc(char *format, unsigned fmt_length, | 246 | static void print_direc(char *format, unsigned fmt_length, |
@@ -321,18 +354,10 @@ static char **print_formatted(char *f, char **argv, int *conv_err) | |||
321 | int field_width; /* Arg to first '*' */ | 354 | int field_width; /* Arg to first '*' */ |
322 | int precision; /* Arg to second '*' */ | 355 | int precision; /* Arg to second '*' */ |
323 | char **saved_argv = argv; | 356 | char **saved_argv = argv; |
324 | #if ENABLE_PLATFORM_MINGW32 | ||
325 | char *s, *t; | ||
326 | s = t = auto_string(xstrdup(f)); | ||
327 | #endif | ||
328 | 357 | ||
329 | for (; *f; ++f) { | 358 | for (; *f; ++f) { |
330 | switch (*f) { | 359 | switch (*f) { |
331 | case '%': | 360 | case '%': |
332 | #if ENABLE_PLATFORM_MINGW32 | ||
333 | fwrite_stdout(s, t); | ||
334 | t = s; | ||
335 | #endif | ||
336 | direc_start = f++; | 361 | direc_start = f++; |
337 | direc_length = 1; | 362 | direc_length = 1; |
338 | field_width = precision = 0; | 363 | field_width = precision = 0; |
@@ -421,18 +446,6 @@ static char **print_formatted(char *f, char **argv, int *conv_err) | |||
421 | free(p); | 446 | free(p); |
422 | } | 447 | } |
423 | break; | 448 | break; |
424 | #if ENABLE_PLATFORM_MINGW32 | ||
425 | case '\\': | ||
426 | if (*++f == 'c') { | ||
427 | fwrite_stdout(s, t); | ||
428 | return saved_argv; /* causes main() to exit */ | ||
429 | } | ||
430 | *t++ = bb_process_escape_sequence((const char **)&f); | ||
431 | f--; | ||
432 | break; | ||
433 | default: | ||
434 | *t++ = *f; | ||
435 | #else | ||
436 | case '\\': | 449 | case '\\': |
437 | if (*++f == 'c') { | 450 | if (*++f == 'c') { |
438 | return saved_argv; /* causes main() to exit */ | 451 | return saved_argv; /* causes main() to exit */ |
@@ -442,12 +455,8 @@ static char **print_formatted(char *f, char **argv, int *conv_err) | |||
442 | break; | 455 | break; |
443 | default: | 456 | default: |
444 | putchar(*f); | 457 | putchar(*f); |
445 | #endif | ||
446 | } | 458 | } |
447 | } | 459 | } |
448 | #if ENABLE_PLATFORM_MINGW32 | ||
449 | fwrite_stdout(s, t); | ||
450 | #endif | ||
451 | 460 | ||
452 | return argv; | 461 | return argv; |
453 | } | 462 | } |
@@ -495,6 +504,9 @@ int printf_main(int argc UNUSED_PARAM, char **argv) | |||
495 | do { | 504 | do { |
496 | argv = argv2; | 505 | argv = argv2; |
497 | argv2 = print_formatted(format, argv, &conv_err); | 506 | argv2 = print_formatted(format, argv, &conv_err); |
507 | #if ENABLE_PLATFORM_MINGW32 | ||
508 | my_flush(); | ||
509 | #endif | ||
498 | } while (argv2 > argv && *argv2); | 510 | } while (argv2 > argv && *argv2); |
499 | 511 | ||
500 | /* coreutils compat (bash doesn't do this): | 512 | /* coreutils compat (bash doesn't do this): |