|
1 | 1 | #include "builtin.h"
|
| 2 | +#include "cache.h" |
2 | 3 |
|
3 | 4 | /*
|
4 |
| - * Remove empty lines from the beginning and end. |
| 5 | + * Remove trailing spaces from a line. |
5 | 6 | *
|
6 |
| - * Turn multiple consecutive empty lines into just one |
7 |
| - * empty line. Return true if it is an incomplete line. |
| 7 | + * If the line ends with newline, it will be removed too. |
| 8 | + * Returns the new length of the string. |
8 | 9 | */
|
9 |
| -static int cleanup(char *line) |
| 10 | +static int cleanup(char *line, int len) |
10 | 11 | {
|
11 |
| - int len = strlen(line); |
| 12 | + if (len) { |
| 13 | + if (line[len - 1] == '\n') |
| 14 | + len--; |
12 | 15 |
|
13 |
| - if (len && line[len-1] == '\n') { |
14 |
| - if (len == 1) |
15 |
| - return 0; |
16 |
| - do { |
17 |
| - unsigned char c = line[len-2]; |
| 16 | + while (len) { |
| 17 | + unsigned char c = line[len - 1]; |
18 | 18 | if (!isspace(c))
|
19 | 19 | break;
|
20 |
| - line[len-2] = '\n'; |
21 | 20 | len--;
|
22 |
| - line[len] = 0; |
23 |
| - } while (len > 1); |
24 |
| - return 0; |
| 21 | + } |
| 22 | + line[len] = 0; |
25 | 23 | }
|
26 |
| - return 1; |
| 24 | + return len; |
27 | 25 | }
|
28 | 26 |
|
29 |
| -static void stripspace(FILE *in, FILE *out) |
| 27 | +/* |
| 28 | + * Remove empty lines from the beginning and end |
| 29 | + * and also trailing spaces from every line. |
| 30 | + * |
| 31 | + * Turn multiple consecutive empty lines between paragraphs |
| 32 | + * into just one empty line. |
| 33 | + * |
| 34 | + * If the input has only empty lines and spaces, |
| 35 | + * no output will be produced. |
| 36 | + * |
| 37 | + * Enable skip_comments to skip every line starting with "#". |
| 38 | + */ |
| 39 | +void stripspace(FILE *in, FILE *out, int skip_comments) |
30 | 40 | {
|
31 | 41 | int empties = -1;
|
32 |
| - int incomplete = 0; |
33 |
| - char line[1024]; |
| 42 | + int alloc = 1024; |
| 43 | + char *line = xmalloc(alloc); |
| 44 | + |
| 45 | + while (fgets(line, alloc, in)) { |
| 46 | + int len = strlen(line); |
34 | 47 |
|
35 |
| - while (fgets(line, sizeof(line), in)) { |
36 |
| - incomplete = cleanup(line); |
| 48 | + while (len == alloc - 1 && line[len - 1] != '\n') { |
| 49 | + alloc = alloc_nr(alloc); |
| 50 | + line = xrealloc(line, alloc); |
| 51 | + fgets(line + len, alloc - len, in); |
| 52 | + len += strlen(line + len); |
| 53 | + } |
| 54 | + |
| 55 | + if (skip_comments && line[0] == '#') |
| 56 | + continue; |
| 57 | + len = cleanup(line, len); |
37 | 58 |
|
38 | 59 | /* Not just an empty line? */
|
39 |
| - if (line[0] != '\n') { |
| 60 | + if (len) { |
40 | 61 | if (empties > 0)
|
41 | 62 | fputc('\n', out);
|
42 | 63 | empties = 0;
|
43 | 64 | fputs(line, out);
|
| 65 | + fputc('\n', out); |
44 | 66 | continue;
|
45 | 67 | }
|
46 | 68 | if (empties < 0)
|
47 | 69 | continue;
|
48 | 70 | empties++;
|
49 | 71 | }
|
50 |
| - if (incomplete) |
51 |
| - fputc('\n', out); |
| 72 | + free(line); |
52 | 73 | }
|
53 | 74 |
|
54 | 75 | int cmd_stripspace(int argc, const char **argv, const char *prefix)
|
55 | 76 | {
|
56 |
| - stripspace(stdin, stdout); |
| 77 | + stripspace(stdin, stdout, 0); |
57 | 78 | return 0;
|
58 | 79 | }
|
0 commit comments