aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/printf.c108
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
155static size_t fwrite_stdout(const char *s, const char *t) 155static int buflen = 0;
156static int bufmax = 0;
157static char *buffer = NULL;
158
159static 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
168static 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
180static 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 */
162static int print_esc_string(const char *str) 216static 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
213static void print_direc(char *format, unsigned fmt_length, 246static 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):