fold.c - sbase - suckless unix tools | |
git clone git://git.suckless.org/sbase | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
fold.c (2616B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include <ctype.h> | |
3 #include <stdint.h> | |
4 #include <stdio.h> | |
5 #include <stdlib.h> | |
6 #include <string.h> | |
7 | |
8 #include "text.h" | |
9 #include "util.h" | |
10 #include "utf.h" | |
11 | |
12 static int bflag = 0; | |
13 static int sflag = 0; | |
14 static size_t width = 80; | |
15 | |
16 static void | |
17 foldline(struct line *l, const char *fname) { | |
18 size_t i, col, last, spacesect, len; | |
19 Rune r; | |
20 int runelen; | |
21 | |
22 for (i = 0, last = 0, col = 0, spacesect = 0; i < l->len; i += r… | |
23 if (col >= width && ((l->data[i] != '\r' && l->data[i] !… | |
24 if (bflag && col > width) | |
25 i -= runelen; /* never split a ch… | |
26 len = ((sflag && spacesect) ? spacesect : i) - l… | |
27 if (fwrite(l->data + last, 1, len, stdout) != le… | |
28 eprintf("fwrite <stdout>:"); | |
29 if (l->data[i] != '\n') | |
30 putchar('\n'); | |
31 if (sflag && spacesect) | |
32 i = spacesect; | |
33 last = i; | |
34 col = 0; | |
35 spacesect = 0; | |
36 } | |
37 runelen = charntorune(&r, l->data + i, l->len - i); | |
38 if (!runelen || r == Runeerror) | |
39 eprintf("charntorune: %s: invalid utf\n", fname); | |
40 if (sflag && isblankrune(r)) | |
41 spacesect = i + runelen; | |
42 if (!bflag && iscntrl(l->data[i])) { | |
43 switch(l->data[i]) { | |
44 case '\b': | |
45 col -= (col > 0); | |
46 break; | |
47 case '\r': | |
48 col = 0; | |
49 break; | |
50 case '\t': | |
51 col += (8 - (col % 8)); | |
52 if (col >= width) | |
53 i--; | |
54 break; | |
55 } | |
56 } else { | |
57 col += bflag ? runelen : 1; | |
58 } | |
59 } | |
60 if (l->len - last) | |
61 fwrite(l->data + last, 1, l->len - last, stdout); | |
62 } | |
63 | |
64 static void | |
65 fold(FILE *fp, const char *fname) | |
66 { | |
67 static struct line line; | |
68 static size_t size = 0; | |
69 ssize_t len; | |
70 | |
71 while ((len = getline(&line.data, &size, fp)) > 0) { | |
72 line.len = len; | |
73 foldline(&line, fname); | |
74 } | |
75 if (ferror(fp)) | |
76 eprintf("getline %s:", fname); | |
77 } | |
78 | |
79 static void | |
80 usage(void) | |
81 { | |
82 eprintf("usage: %s [-bs] [-w num | -num] [FILE ...]\n", argv0); | |
83 } | |
84 | |
85 int | |
86 main(int argc, char *argv[]) | |
87 { | |
88 FILE *fp; | |
89 int ret = 0; | |
90 | |
91 ARGBEGIN { | |
92 case 'b': | |
93 bflag = 1; | |
94 break; | |
95 case 's': | |
96 sflag = 1; | |
97 break; | |
98 case 'w': | |
99 width = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SIZE… | |
100 break; | |
101 ARGNUM: | |
102 if (!(width = ARGNUMF())) | |
103 eprintf("illegal width value, too small\n"); | |
104 break; | |
105 default: | |
106 usage(); | |
107 } ARGEND | |
108 | |
109 if (!argc) { | |
110 fold(stdin, "<stdin>"); | |
111 } else { | |
112 for (; *argv; argc--, argv++) { | |
113 if (!strcmp(*argv, "-")) { | |
114 *argv = "<stdin>"; | |
115 fp = stdin; | |
116 } else if (!(fp = fopen(*argv, "r"))) { | |
117 weprintf("fopen %s:", *argv); | |
118 ret = 1; | |
119 continue; | |
120 } | |
121 fold(fp, *argv); | |
122 if (fp != stdin && fshut(fp, *argv)) | |
123 ret = 1; | |
124 } | |
125 } | |
126 | |
127 ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>"); | |
128 | |
129 return ret; | |
130 } |