aboutsummaryrefslogtreecommitdiff
path: root/coreutils/fold.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-01-04 20:49:58 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-01-04 20:49:58 +0100
commit28055028a709020ba7eb44f9e5037d0a952b51d6 (patch)
treebb5dc7052f04e66ad74bbbcc9917d638cd603b24 /coreutils/fold.c
parentd2b1ba6fdee59645763e915ade3ec55e67d5839a (diff)
downloadbusybox-w32-28055028a709020ba7eb44f9e5037d0a952b51d6.tar.gz
busybox-w32-28055028a709020ba7eb44f9e5037d0a952b51d6.tar.bz2
busybox-w32-28055028a709020ba7eb44f9e5037d0a952b51d6.zip
fold: unicode support. Based on a patch by Tomas Heinrich <heinrich.tomas@gmail.com>
General Unicode support is tweaked to expose unicode_status. function old new delta init_unicode - 77 +77 write2stdout - 19 +19 adjust_column 68 71 +3 unicode_status - 1 +1 unicode_is_enabled 1 - -1 grep_main 780 773 -7 fold_main 619 552 -67 check_unicode_in_env 77 - -77 ------------------------------------------------------------------------------ (add/remove: 3/2 grow/shrink: 1/2 up/down: 100/-152) Total: -52 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils/fold.c')
-rw-r--r--coreutils/fold.c161
1 files changed, 88 insertions, 73 deletions
diff --git a/coreutils/fold.c b/coreutils/fold.c
index 56a346680..cbea31fad 100644
--- a/coreutils/fold.c
+++ b/coreutils/fold.c
@@ -9,8 +9,8 @@
9 9
10 Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 10 Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
11*/ 11*/
12
13#include "libbb.h" 12#include "libbb.h"
13#include "unicode.h"
14 14
15/* Must match getopt32 call */ 15/* Must match getopt32 call */
16#define FLAG_COUNT_BYTES 1 16#define FLAG_COUNT_BYTES 1
@@ -20,39 +20,53 @@
20/* Assuming the current column is COLUMN, return the column that 20/* Assuming the current column is COLUMN, return the column that
21 printing C will move the cursor to. 21 printing C will move the cursor to.
22 The first column is 0. */ 22 The first column is 0. */
23static int adjust_column(int column, char c) 23static int adjust_column(unsigned column, char c)
24{ 24{
25 if (!(option_mask32 & FLAG_COUNT_BYTES)) { 25 if (option_mask32 & FLAG_COUNT_BYTES)
26 if (c == '\b') { 26 return ++column;
27 if (column > 0) 27
28 column--; 28 if (c == '\t')
29 } else if (c == '\r') 29 return column + 8 - column % 8;
30
31 if (c == '\b') {
32 if ((int)--column < 0)
30 column = 0; 33 column = 0;
31 else if (c == '\t') 34 }
32 column = column + 8 - column % 8; 35 else if (c == '\r')
33 else /* if (isprint(c)) */ 36 column = 0;
37 else { /* just a printable char */
38 if (unicode_status != UNICODE_ON /* every byte is a new char */
39 || (c & 0xc0) != 0x80 /* it isn't a 2nd+ byte of a Unicode char */
40 ) {
34 column++; 41 column++;
35 } else 42 }
36 column++; 43 }
37 return column; 44 return column;
38} 45}
39 46
47/* Note that this function can write NULs, unlike fputs etc. */
48static void write2stdout(const void *buf, unsigned size)
49{
50 fwrite(buf, 1, size, stdout);
51}
52
40int fold_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 53int fold_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
41int fold_main(int argc UNUSED_PARAM, char **argv) 54int fold_main(int argc UNUSED_PARAM, char **argv)
42{ 55{
43 char *line_out = NULL; 56 char *line_out = NULL;
44 int allocated_out = 0; 57 const char *w_opt = "80";
45 char *w_opt; 58 unsigned width;
46 int width = 80; 59 smallint exitcode = EXIT_SUCCESS;
47 int i; 60
48 int errs = 0; 61 init_unicode();
49 62
50 if (ENABLE_INCLUDE_SUSv2) { 63 if (ENABLE_INCLUDE_SUSv2) {
51 /* Turn any numeric options into -w options. */ 64 /* Turn any numeric options into -w options. */
65 int i;
52 for (i = 1; argv[i]; i++) { 66 for (i = 1; argv[i]; i++) {
53 char const *a = argv[i]; 67 const char *a = argv[i];
54 68 if (*a == '-') {
55 if (*a++ == '-') { 69 a++;
56 if (*a == '-' && !a[1]) /* "--" */ 70 if (*a == '-' && !a[1]) /* "--" */
57 break; 71 break;
58 if (isdigit(*a)) 72 if (isdigit(*a))
@@ -62,8 +76,7 @@ int fold_main(int argc UNUSED_PARAM, char **argv)
62 } 76 }
63 77
64 getopt32(argv, "bsw:", &w_opt); 78 getopt32(argv, "bsw:", &w_opt);
65 if (option_mask32 & FLAG_WIDTH) 79 width = xatou_range(w_opt, 1, 10000);
66 width = xatoul_range(w_opt, 1, 10000);
67 80
68 argv += optind; 81 argv += optind;
69 if (!*argv) 82 if (!*argv)
@@ -72,79 +85,81 @@ int fold_main(int argc UNUSED_PARAM, char **argv)
72 do { 85 do {
73 FILE *istream = fopen_or_warn_stdin(*argv); 86 FILE *istream = fopen_or_warn_stdin(*argv);
74 int c; 87 int c;
75 int column = 0; /* Screen column where next char will go. */ 88 unsigned column = 0; /* Screen column where next char will go */
76 int offset_out = 0; /* Index in 'line_out' for next char. */ 89 unsigned offset_out = 0; /* Index in 'line_out' for next char */
77 90
78 if (istream == NULL) { 91 if (istream == NULL) {
79 errs |= EXIT_FAILURE; 92 exitcode = EXIT_FAILURE;
80 continue; 93 continue;
81 } 94 }
82 95
83 while ((c = getc(istream)) != EOF) { 96 while ((c = getc(istream)) != EOF) {
84 if (offset_out + 1 >= allocated_out) { 97 /* We grow line_out in chunks of 0x1000 bytes */
85 allocated_out += 1024; 98 if ((offset_out & 0xfff) == 0) {
86 line_out = xrealloc(line_out, allocated_out); 99 line_out = xrealloc(line_out, offset_out + 0x1000);
87 } 100 }
88 101 rescan:
102 line_out[offset_out] = c;
89 if (c == '\n') { 103 if (c == '\n') {
90 line_out[offset_out++] = c; 104 write2stdout(line_out, offset_out + 1);
91 fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
92 column = offset_out = 0; 105 column = offset_out = 0;
93 continue; 106 continue;
94 } 107 }
95 rescan:
96 column = adjust_column(column, c); 108 column = adjust_column(column, c);
109 if (column <= width || offset_out == 0) {
110 /* offset_out == 0 case happens
111 * with small width (say, 1) and tabs.
112 * The very first tab already goes to column 8,
113 * but we must not wrap it */
114 offset_out++;
115 continue;
116 }
97 117
98 if (column > width) { 118 /* This character would make the line too long.
99 /* This character would make the line too long. 119 * Print the line plus a newline, and make this character
100 Print the line plus a newline, and make this character 120 * start the next line */
101 start the next line. */ 121 if (option_mask32 & FLAG_BREAK_SPACES) {
102 if (option_mask32 & FLAG_BREAK_SPACES) { 122 unsigned i;
103 /* Look for the last blank. */ 123 unsigned logical_end;
104 int logical_end; 124
105 125 /* Look for the last blank. */
106 for (logical_end = offset_out - 1; logical_end >= 0; logical_end--) { 126 for (logical_end = offset_out - 1; (int)logical_end >= 0; logical_end--) {
107 if (isblank(line_out[logical_end])) { 127 if (!isblank(line_out[logical_end]))
108 break; 128 continue;
109 } 129
130 /* Found a space or tab.
131 * Output up to and including it, and start a new line */
132 logical_end++;
133 /*line_out[logical_end] = '\n'; - NO! this nukes one buffered character */
134 write2stdout(line_out, logical_end);
135 putchar('\n');
136 /* Move the remainder to the beginning of the next line.
137 * The areas being copied here might overlap. */
138 memmove(line_out, line_out + logical_end, offset_out - logical_end);
139 offset_out -= logical_end;
140 for (column = i = 0; i < offset_out; i++) {
141 column = adjust_column(column, line_out[i]);
110 } 142 }
111 if (logical_end >= 0) { 143 goto rescan;
112 /* Found a blank. Don't output the part after it. */
113 logical_end++;
114 fwrite(line_out, sizeof(char), (size_t) logical_end, stdout);
115 bb_putchar('\n');
116 /* Move the remainder to the beginning of the next line.
117 The areas being copied here might overlap. */
118 memmove(line_out, line_out + logical_end, offset_out - logical_end);
119 offset_out -= logical_end;
120 for (column = i = 0; i < offset_out; i++) {
121 column = adjust_column(column, line_out[i]);
122 }
123 goto rescan;
124 }
125 }
126 if (offset_out == 0) {
127 line_out[offset_out++] = c;
128 continue;
129 } 144 }
130 line_out[offset_out++] = '\n'; 145 /* No blank found, wrap will split the overlong word */
131 fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
132 column = offset_out = 0;
133 goto rescan;
134 } 146 }
135 147 /* Output what we accumulated up to now, and start a new line */
136 line_out[offset_out++] = c; 148 line_out[offset_out] = '\n';
137 } 149 write2stdout(line_out, offset_out + 1);
150 column = offset_out = 0;
151 goto rescan;
152 } /* while (not EOF) */
138 153
139 if (offset_out) { 154 if (offset_out) {
140 fwrite(line_out, sizeof(char), (size_t) offset_out, stdout); 155 write2stdout(line_out, offset_out);
141 } 156 }
142 157
143 if (fclose_if_not_stdin(istream)) { 158 if (fclose_if_not_stdin(istream)) {
144 bb_simple_perror_msg(*argv); /* Avoid multibyte problems. */ 159 bb_simple_perror_msg(*argv);
145 errs |= EXIT_FAILURE; 160 exitcode = EXIT_FAILURE;
146 } 161 }
147 } while (*++argv); 162 } while (*++argv);
148 163
149 fflush_stdout_and_exit(errs); 164 fflush_stdout_and_exit(exitcode);
150} 165}